Indentation appears in the output string when broken it over multiple lines - python-3.x

I have large f-string, and I am braking it (see below), for code readability.
but when I print (print to file, it is String.IO object) the string I get the indentation leading each new line (except the first), and I don't want that (my IDE is vscode).
When taking the same f-string below, to the python shell interpreter (REPL), the output string is proper.
def foo():
ml.append(f"""
#define {ip}_{mtype}_{secname}_{fieldname}_MASK (MASK({H},{L}))
#define {ip}_{mtype}_{secname}_{fieldname}_START_BIT ({fieldsb})\n""")
the output file looks like:
#define QM_MEM_CBTIRDY_LENGTH (0x40) //good line
#define QM_MEM_CBTIRDY_DATA_MASK (GENMASK(31,0)) //bad line (with indentation)
#define QM_MEM_CBTIRDY_DATA_START_BIT (0)
I have fix it by removing the indentation between each new line (but its ugly cos the strings with the same function def indentation level, and this is ugly)
def foo():
ml.append(f"""
#define {ip}_{mtype}_{secname}_{fieldname}_MASK (MASK({H},{L}))
define {ip}_{mtype}_{secname}_{fieldname}_START_BIT ({fieldsb})\n""")
how can i get rid of these indentation characters in the final string ?

Triple-quoted (multiline) strings are supposed to preserve the formatting, so that's why you're getting those identations.
You can use concatenation instead:
ml.append(f"#define {ip}_{mtype}_{secname}_{fieldname}_MASK (MASK({H},{L}))\n"
f"#define {ip}_{mtype}_{secname}_{fieldname}_START_BIT ({fieldsb})\n")
or if you still prefer multi-line strings, you can trim them in a similar way to docstrings.

Related

Python equivalen to clean() function in Excel

In Excel there is a function called clean(), which removes all nonprintable characters from text. Reference https://support.microsoft.com/en-us/office/clean-function-26f3d7c5-475f-4a9c-90e5-4b8ba987ba41#:~:text=Removes%20all%20nonprintable%20characters%20from,files%20and%20cannot%20be%20printed.
I am wondering if there is any direct function/method in python to achieve the same.
Also, how can I mimic clean() function in python just using Regular expression?
Any pointer will be very helpful
The CLEAN function in Excel removes only "the first 32 nonprinting characters in the 7-bit ASCII code (values 0 through 31)", according to the documentation you link to, so to mimic it, you can filter characters of a given string whose ord values are less than 32:
def clean(s):
return ''.join(c for c in s if ord(c) < 32)
Or you can use a regular expression substitution to remove characters with hex values between \x00 and \x1f:
import re
def clean(s):
return re.sub(r'[\x00-\x1f]+', '', s)

How do I output a block text in coffeescript with spaces BEFORE everything

redditFunny = """
TEST TEST
"""
console.log redditFunny
compiles into
var redditFunny;
redditFunny = "TEST TEST";
console.log(redditFunny);
I just want to output it as is
From the fine manual:
Block strings can be used to hold formatted or indentation-sensitive text (or, if you just don't feel like escaping quotes and apostrophes). The indentation level that begins the block is maintained throughout, so you can keep it all aligned with the body of your code.
Emphasis mine. The example they give is that this CoffeeScript:
html = """
<strong>
cup of coffeescript
</strong>
"""
becomes this JavaScript:
html = "<strong>\n cup of coffeescript\n</strong>";
Note that the "inner" indentation is preserved while the "outer" indentation is removed.
The trick is to make CoffeeScript think you have a zero length "outer" indentation so that it will strip off zero leading spaces. Something like this chicanery for example:
s = """
\ this
is indented
"""
will become this JavaScript:
s = "\ this\n is indented"
// ^^ ^
Note that '\ ' is a complicated way of writing ' ' because an escaped space is just a space.
You could also use the fact that \u0020 is the Unicode escape for a space and say:
s = """
\u0020this
is indented
"""
to achieve the same output.
This seems a bit dodgy and fragile to me but similar things are the recommended way to deal with leading #s in block regexes so this should be pretty safe.
I would probably avoid all this cleverness and write a little indenting function that split a string on '\n' and pasted it back together with leading indentation so that I could say:
indent(some_string_with_newlines, ' ')
to indent the block with eleven spaces.

Is there an operator that can trim indentation in multi-line string?

This is really nice in Groovy:
println '''First line,
second line,
last line'''
Multi-line strings. I have seen in some languages tools that take a step further and can remove the indentation of line 2 and so, so that statement would print:
First line,
second line,
last line
and not
First line,
second line,
last line
Is it possible in Groovy?
You can use stripMargin() for this:
println """hello world!
|from groovy
|multiline string
""".stripMargin()
If you don't want leading character (like pipe in this case), there is stripIndent() as well, but string will need to be formatted little differently (as minimum indent is important)
println """
hello world!
from groovy
multiline string
""".stripIndent()
from docs of stripIndent
Strip leading spaces from every line in a String. The line with the least number of leading spaces determines the number to remove. Lines only containing whitespace are ignored when calculating the number of leading spaces to strip.
Update:
Regarding using a operator for doing it, I, personally, would not recommend doing so. But for records, it can be done by using Extension Mechanism or using Categories (simpler and clunkier). Categories example is as follows:
class StringCategory {
static String previous(String string) { // overloads `--`
return string.stripIndent()
}
}
use (StringCategory) {
println(--'''
hello world!
from groovy
multiline string
''')
}

Multiline string literal in Matlab?

Is there a multiline string literal syntax in Matlab or is it necessary to concatenate multiple lines?
I found the verbatim package, but it only works in an m-file or function and not interactively within editor cells.
EDIT: I am particularly after readbility and ease of modifying the literal in the code (imagine it contains indented blocks of different levels) - it is easy to make multiline strings, but I am looking for the most convenient sytax for doing that.
So far I have
t = {...
'abc'...
'def'};
t = cellfun(#(x) [x sprintf('\n')],t,'Unif',false);
t = horzcat(t{:});
which gives size(t) = 1 8, but is obviously a bit of a mess.
EDIT 2: Basically verbatim does what I want except it doesn't work in Editor cells, but maybe my best bet is to update it so it does. I think it should be possible to get current open file and cursor position from the java interface to the Editor. The problem would be if there were multiple verbatim calls in the same cell how would you distinguish between them.
I'd go for:
multiline = sprintf([ ...
'Line 1\n'...
'Line 2\n'...
]);
Matlab is an oddball in that escape processing in strings is a function of the printf family of functions instead of the string literal syntax. And no multiline literals. Oh well.
I've ended up doing two things. First, make CR() and LF() functions that just return processed \r and \n respectively, so you can use them as pseudo-literals in your code. I prefer doing this way rather than sending entire strings through sprintf(), because there might be other backslashes in there you didn't want processed as escape sequences (e.g. if some of your strings came from function arguments or input read from elsewhere).
function out = CR()
out = char(13); % # sprintf('\r')
function out = LF()
out = char(10); % # sprintf('\n');
Second, make a join(glue, strs) function that works like Perl's join or the cellfun/horzcat code in your example, but without the final trailing separator.
function out = join(glue, strs)
strs = strs(:)';
strs(2,:) = {glue};
strs = strs(:)';
strs(end) = [];
out = cat(2, strs{:});
And then use it with cell literals like you do.
str = join(LF, {
'abc'
'defghi'
'jklm'
});
You don't need the "..." ellipses in cell literals like this; omitting them does a vertical vector construction, and it's fine if the rows have different lengths of char strings because they're each getting stuck inside a cell. That alone should save you some typing.
Bit of an old thread but I got this
multiline = join([
"Line 1"
"Line 2"
], newline)
I think if makes things pretty easy but obviously it depends on what one is looking for :)

"undeclared identifier" error in simple macro expansion

I have a very simple macro that I use for shorthand when declaring exceptions. When in debug mode it adds the current file and line number.
I'm in the process of modifying my code to support unicode, and suddenly I'm getting "undeclared identifier" errors whenever my macro is used. I'm probably missing something really simple, as the macro itself is rather simple. Can anyone tell what the issue is?
Here's the macro declaration:
#ifdef _DEBUG
#define EXCEPTION(msg, mm) Exception(msg, mm, _T(__FILE__), _T(__LINE__))
#else
#define EXCEPTION(msg, mm) Exception(msg, mm)
#endif
I don't think it's needed, but just in case, here's the Exception constructor declaration:
Exception(LPCTSTR msg, BOOL manageMsg = FALSE, LPCTSTR f = NULL, int l = -1);
When compiling in release mode I don't get any errors, but when in debug mode I do, so it's something with the __FILE__ and __LINE__ bits, but I can't figure out what the actual issue is.
This wasn't exactly the same problem I had, but I am posting the solution to my issue here because I came across this question during my investigations.
If you encounter this error message with a multiline macro, turn on visible whitespace in your editor. You may have whitespace after the '\' continuation character at the end of the line:
#define FOO_BAR(aFoo) \
FOO_BASE(aFoo, "bar")
The space at the end causes the parser to parse the first line of the macro definition as complete (FOO_BAR expands to '\ '), and the second line is interpreted as a function declaration, hence "undeclared identifier 'aFoo'").
The __LINE__ macro evaluates to an integer. The _T macro puts an L on the front of strings to make them Unicode strings. It's meant to be followed by an opening double quotation mark, like L"file.cpp". But in your case, it's followed by the integer literal that __LINE__ expands to. You're getting something like this: L23. Get rid of the second _T call.
#define EXCEPTION(msg, mm) Exception(msg, mm, _T(__FILE__), __LINE__)
This might have been more easily diagnosed if you had included the name of the identifier that the compiler didn't recognize. Compilers usually include that information in their error messages.

Resources