3

Because I have

(setq python-indent-offset 4)

in my .emacs, when I start with code such as

def fn():
  foo = bar()
  if bar1 == bar2:
    if blah1 == blah2:
      return yay

and mark-whole-buffer (C-x h) followed by indent-region (C-M-\ ), I am expecting to get:

def fn():
    foo = bar()
    if bar1 == bar2:
        if blah1 == blah2:
            return yay

but I get instead:

def fn():
    foo = bar()
  if bar1 == bar2:
    if blah1 == blah2:
      return yay

Yet indent-region works just fine with curly-brace delimited languages. Is there a way to get it to work with an indentation-based language such as Python?

Please note:

  1. I am aware of Reindent but I'd like to stay within Emacs.
  2. I am well acquainted with string-rectangle (C-x r t) and python-indent-shift-right/left (C-c >), but neither these nor their variants do what I'm asking.
Community
  • 1
  • 1
Calaf
  • 10,113
  • 15
  • 57
  • 120
  • 1
    The issue seems to be that in `python-indent-region`, there is a check to see if the line is on a block start. If it is on a block start (such as if in an if statement) it will skip the line and not change the indentation. You should raise it as a bug. – Jules Jun 03 '16 at 15:44

2 Answers2

1

I'm not sure if this is a perfect solution and as such I would not want to push this as a patch to emacs-devel but since the issue is in python-indent-region (I left a note about this as a comment). We can try to redefine that function as such:

(defun python-indent-region (start end)
  "Indent a Python region automagically.

Called from a program, START and END specify the region to indent."
  (let ((deactivate-mark nil))
    (save-excursion
      (goto-char end)
      (setq end (point-marker))
      (goto-char start)
      (or (bolp) (forward-line 1))
      (while (< (point) end)
        (or (and (bolp) (eolp))
            (when (and
                   ;; Skip if previous line is empty or a comment.
                   (save-excursion
                     (let ((line-is-comment-p
                            (python-info-current-line-comment-p)))
                       (forward-line -1)
                       (not
                        (or (and (python-info-current-line-comment-p)
                                 ;; Unless this line is a comment too.
                                 (not line-is-comment-p))
                            (python-info-current-line-empty-p)))))
                   ;; Don't mess with strings, unless it's the
                   ;; enclosing set of quotes or a docstring.
                   (or (not (python-syntax-context 'string))
                       (eq
                        (syntax-after
                         (+ (1- (point))
                            (current-indentation)
                            (python-syntax-count-quotes (char-after) (point))))
                        (string-to-syntax "|"))
                       (python-info-docstring-p)))
              (python-indent-line)))
        (forward-line 1))
      (move-marker end nil))))

The part that I changed was simply removing the check to see if the line was a block ender, denter, or block-start and running (python-indent-line) in all of those cases.

I've tested this on this example and some others and they seem to work. If it doesn't work I'd love to know!

Jules
  • 973
  • 4
  • 10
  • Hmm.. After eval-region, restarting Emacs, and using another (bleeding edge) version of Emacs, the function name python-indent-region is not recognized after M-x. Investigating. I've also tried to change that name. – Calaf Jun 03 '16 at 16:11
  • It shouldn't be visible through m-x, it should be called by C-M-\ though when you use that command – Jules Jun 03 '16 at 19:01
0

Alternatively you can call the python package from within emacs and have it replace the buffer.

(defun my-py-reindent ()
         "Reindent the current file with pypi's reindent."
         (interactive)
           (shell-command-to-string (format "reindent %s" (buffer-file-name)))
           (revert-buffer t t t))

Pretty easy ! (doc used: http://wikemacs.org/wiki/Emacs_Lisp_Cheat_Sheet#File)

Ehvince
  • 17,274
  • 7
  • 58
  • 79