Tabs, Spaces, and Scripting

Any good editor papers over the difference between tabs and spaces so that it's unnecessary (e.g, a backspace at a 4-space "tab" automatically removes all 4 spaces in one go. This is how it works in VSCode, Sublime, IntelliJ, PyCharm, etc.)

I'm generally pro-spaces, but I'm much more strongly in the camp of "just use an automated formatter and stop bickering about the shape of the code, the AST is the thing that matters". Unfortunately, Python is one of the unicorns with semantic whitespace, so this kind of debate rages forevermore. And obviously Ignition's situation is far from the ideal software development workflow (much as I'd like to change that over time).

Wait, are you indenting with 3 spaces ?
What kind of monster are you ?

2 Likes

Haha, no I have never indented with spaces, I just assumed that's what people used :person_shrugging:

We had a very odd situation today with tabs and spaces. We had the Whitespace Toggle turned off in a Gateway Tag Change Script event, and it was executing the code improperly. Once the Whitespace Toggle was turned on, we discovered that there were a few lines of code that included both spaces and tabs, and those lines of code were skipped without any error thrown.

We were able to replicate the issue in the console. As you can see from the example below, lines 6 and 7 do not execute and no error is thrown for the mixed spaces and tabs.

As soon as we replace the spaces with tabs, the code executes as expected.

I don't know if it is a bug, but I'm curious if anyone knows if this is expected behavior.

It's expected behavior for Python 2. Python 3 fixed it (it will throw an error at mixed tabs & spaces). The else is being interpreted as closing the first if, rather than the second.

1 Like

I can say that as of 8.1.31, this is still a problem. Mixed whitespace is not detected by the script engine, and causes not only the headache of whack-a-mole dedent errors in the editor, it causes the infinitely more nefarious problem of block code executing inside the wrong block with no error behavior. Yes, I know it is a python 2 problem, but I assume that the script editor engine is capable of someing like

for i, _line in enumerate(lines): 
    line = _line.replace("\t", "    ")
    if len(line) - len(line.lstrip()) % 4 != 0: 
        raise Exception("SOMETHING OBVIOUSLY WRONG WITH YOUR WHITESPACE ON LINE {}".format(i))

I have been manually copying out the code and forcing all the whitespace to be spaces using VSCode, but when I go to edit in the native code editor this backfires because the interpreter seems to mess up " \t" as a legal whitespacing.

1 Like

To not screw up the mix with the native editor, set your external editor to use tabs instead of spaces, with 4 characters per tab. Full stop.

4 Likes

We are planning to add some kind of "inspection" that will visibly warn on mixed indentation content. But no timeline on exactly when that will happen.

Ah the apparently simple solution to the age old conflict.

Unfortunately, it is not quite so simple as I do not love the idea of having to change the settings of my primary IDE because of one compatibility issue. Static spacing is my preferred style, and while I recognize some value of using tabs over spaces, the mixture of the two is always the problem. And as tabs could be spaces but only in a novel twist of use could spaces be used as tabs, the choice is not 50/50 to me :slightly_smiling_face:

@PGriffith an introspective warning system would be very nice. I hope any new features or even beta tests would be well advertised! Also, if you're adding things, the ability to hook into the scripting files using an external editor and have it seamlessly synchronize with the designer would be :100:. I regularly enjoy the ability of VSCode/Sublime/NP++ to handle remotely mounted file systems.

Isn't this what everyone does as the first thing they do after installing an editor? Otherwise, the Earth must be flat.

Edit: Totally missed OP's latest reply :joy: I guess the Earth is flat after all. I never understood using spaces as tabs, but then, I don't understand using imperial units over metric either and a lot would disagree with me (only because they were indoctrinated into imperial and have been using it for centuries though :wink: )

Only joking. Sort of :upside_down_face:

1 Like

Imperial units are naturally binary, mostly, when not powers of two and three. Proper tech-heads are fans of many unit systems.

1 Like

In my indoctrinated opinion, the French got it wrong when they kept the metric system base 10 because it behaves the exact same way as the imperial system fractionally. Unfortunately, if we corrected the metric system now by making it base 12, we would just end up having to maintain three sets of tools, so I say we simply stick with status quo since the refactor wouldn't be worth the added expense.

1 Like

Tabs characters are useful if you need a delimiter that prints in variable size or if you need formatting that is variable depending on where you look at it. I use them a lot in print statements because of the useful effect of collimation that they can have in a lot of environments (e.g. bash outputs).

Python requires very specific whitespace formatting, and so having two different whitespace characters being used can cause problems and is explicitly disallowed. For languages that ignore whitespace, tabs vs spaces is often a purely stylistic difference. I like having my tab button spit out 4 spaces in general, I am not a psychopath that hits spacebar 4 times!

PEP8 explicitly indicates that spaces are preferred to tabs (in case any IA devs here need fuel for fixing the script editor): PEP 8 – Style Guide for Python Code | peps.python.org. The noted exception is in the event that existing code is already tab-delimited (but best practice would have you replace all of the spaces with tabs to fit the primary preference).

When I read this today, it made me contemplate this post and others like it:

...but seriously: Tabs

1 Like

Wish this topic had bubble up a few days earlier. Would have saved me an hour of hair-pulling wondering why the example code from the manual worked but when I made one small change (e.g., /t/tprint 'hello world') it wouldn't.

Also, tabs and a code formatter.
And it's data. Even if there is only one.