2

I am running Emacs with python-mode.el for coding in Python. I hope to learn how to make a region of code indented well automatically.

Following code is not indented well.

while match != None:

        if match.group(1):
            titles.append(match.group(1))

        if match.group(2):
            if match.group(2) != '':
                pns.append(int(match.group(2)))
            else:
                pns.append('')
        else:
            pns.append('')

        if match.group(3):
            closings.append(len(''.join(match.group(3).split())))
        else:
            closings.append(0)

    match = pat.search(match.group(4))

If I select the region, and hit M-x indent-region, it becomes totally wrong:

while match != None:

    if match.group(1):
        titles.append(match.group(1))

        if match.group(2):
            if match.group(2) != '':
                pns.append(int(match.group(2)))
            else:
                pns.append('')
        else:
            pns.append('')

            if match.group(3):
                closings.append(len(''.join(match.group(3).split())))
            else:
                closings.append(0)

                match = pat.search(match.group(4))

The ideal should be:

while match != None:

    if match.group(1):
        titles.append(match.group(1))

    if match.group(2):
        if match.group(2) != '':
            pns.append(int(match.group(2)))
        else:
            pns.append('')
    else:
        pns.append('')

    if match.group(3):
        closings.append(len(''.join(match.group(3).split())))
    else:
        closings.append(0)

    match = pat.search(match.group(4))
  1. Why does M-x indent-region incorrectly understand the indent relation between lines of code? Is it because my code is ambiguous?
  2. What should I do then?

Thanks.

Tim
  • 1
  • 141
  • 372
  • 590

2 Answers2

3

The problem is that emacs has no way of knowing where you want an if-block to end. Both your desired code and the code indent-region produces are valid python. In C-like languages this isn't a problem due to the braces deciding the length of blocks. For python, since emacs can't know for sure it assumes each line of code is still part of the previous block.

You might want to look at python-indent-left (bound to "C-c <") and python-indent-right ("C-c >"). To fix your example, you'd highlight everything apart from the first line, and run python-indent-left.

Jamie Nicol
  • 31
  • 1
  • 3
1

As said, in Python you can't auto-indent larger sections reliably.

However, there is a way to speed up doing it line by line. This is in use here:

(defun indent-and-forward ()
  "Indent current line and go forward one line. "
  (interactive "*")
  (if (empty-line-p)
      (fixup-whitespace)
      (indent-according-to-mode))
  (if (eobp)
      (newline-and-indent)
    (forward-line 1))
  (back-to-indentation))

BTW it should work with other modes too, not just Python. Keys here are

(global-set-key [(super i)] 'indent-and-forward)

This keys pressed, you may travel large parts - just keep an eye it still does what you want. If not - use TAB-key for just this line and proceed with the next one.

Andreas Röhler
  • 4,804
  • 14
  • 18