Josh Katofsky
Josh Katofsky

Reputation: 541

Atom auto indentation script ruins Python indentation

I wrote this function in the init.coffee file for my Atom config to auto indent an entire file:

atom.commands.add 'body', 'custom:auto-format', ->
    editor = atom.workspace.getActiveTextEditor();

    oldSelection = editor.getSelectedBufferRanges();

    editor.selectAll();
    editor.autoIndentSelectedRows();

    editor.setSelectedBufferRanges(oldSelection);

For every language EXCEPT Python, it works perfectly! I was very happy with the results. However, the CoffeeScript auto-indentation totally messes up with Phyton code.

It takes this file:

import sys

def factorial (n):
    if n == 1:
        return 1
    else:
        return n * factorial(n-1)

if __name__ == "__main__":
    for arg in sys.argv[1:]:
        n = factorial(int(arg))
        print("The factorial of " + arg + " is " + str(n))

And is unable to recognize where the factorial function ends, and thus indents like this:

import sys

def factorial (n):
    if n == 1:
        return 1
    else:
        return n * factorial(n-1)

        if __name__ == "__main__":
            for arg in sys.argv[1:]:
                n = factorial(int(arg))
                print("The factorial of " + arg + " is " + str(n))

If anyone has any insight into how to remedy this it would be greatly appreciated!

Upvotes: 0

Views: 326

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121486

You can't auto-indent Python code, full stop.

Auto-indentation only works for languages where blocks are delineated by explicit start- and end markers, such as curly braces. Indentation in such languages is essentially optional, only used by the human software developer to aid reading.

But in Python indentation carries meaning; how code is executed changes with the indentation. Asking software to decide how much indentation to apply is like asking for the computer to read your mind, to second-guess what the programmer wanted the code to do to begin with.

For example, the following un-indented code can be indented in different ways, and lead to different results. Which one interpretation is correct?

var = 'foobar'
for i in range(5):
if var.endswith('bar'):
print('Hello')
if i == 0:
print('World')
break
var += 'spam'
else:
print('!')

It doesn't matter that you see the if __name__ == '__main__': test as a top-level statement. Python can't know that, and such a test would be legal anywhere in Python code, and may even make sense inside a function or class definition sometimes.

Upvotes: 3

Related Questions