From bc9222c93463e8aaaf116ed945c3d2007adf771d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fabi=C3=A1n=20Ezequiel=20Gallina?= Date: Thu, 12 Dec 2013 20:32:05 -0300 Subject: [PATCH] * lisp/progmodes/python.el (python-indent-calculate-indentation): Fix de-denters cornercase. * test/automated/python-tests.el (python-indent-dedenters-2): New test. Fixes: debbugs:15731 --- lisp/ChangeLog | 5 +++++ lisp/progmodes/python.el | 38 ++++++++++++++++++++++------------ test/ChangeLog | 4 ++++ test/automated/python-tests.el | 22 ++++++++++++++++++++ 4 files changed, 56 insertions(+), 13 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 59fe5fff0b8..11dd2d69c04 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,8 @@ +2013-12-12 Fabián Ezequiel Gallina + + * progmodes/python.el (python-indent-calculate-indentation): Fix + de-denters cornercase. (Bug#15731) + 2013-12-12 Stefan Monnier * emacs-lisp/nadvice.el: Add `depth' property to manage ordering. diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 33039a4d087..8de1717096f 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -780,19 +780,31 @@ START is the buffer position where the sexp starts." ;; indentation, in the case current line starts with a ;; `python-indent-dedenters' de-indent one level. (`after-line - (- - (save-excursion - (goto-char context-start) - (current-indentation)) - (if (or (save-excursion - (back-to-indentation) - (looking-at (regexp-opt python-indent-dedenters))) - (save-excursion - (python-util-forward-comment -1) - (python-nav-beginning-of-statement) - (looking-at (regexp-opt python-indent-block-enders)))) - python-indent-offset - 0))) + (let* ((pair (save-excursion + (goto-char context-start) + (cons + (current-indentation) + (python-info-beginning-of-block-p)))) + (context-indentation (car pair)) + (after-block-start-p (cdr pair)) + (adjustment + (if (or (save-excursion + (back-to-indentation) + (and + ;; De-indent only when dedenters are not + ;; next to a block start. This allows + ;; one-liner constructs such as: + ;; if condition: print "yay" + ;; else: print "wry" + (not after-block-start-p) + (looking-at (regexp-opt python-indent-dedenters)))) + (save-excursion + (python-util-forward-comment -1) + (python-nav-beginning-of-statement) + (looking-at (regexp-opt python-indent-block-enders)))) + python-indent-offset + 0))) + (- context-indentation adjustment))) ;; When inside of a string, do nothing. just use the current ;; indentation. XXX: perhaps it would be a good idea to ;; invoke standard text indentation here diff --git a/test/ChangeLog b/test/ChangeLog index 9931e81eb43..6f75b33af95 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,7 @@ +2013-12-12 Fabián Ezequiel Gallina + + * automated/python-tests.el (python-indent-dedenters-2): New test. + 2013-12-12 Fabián Ezequiel Gallina * automated/python-tests.el (python-indent-after-comment-1) diff --git a/test/automated/python-tests.el b/test/automated/python-tests.el index 84be598b6dd..5756507fc92 100644 --- a/test/automated/python-tests.el +++ b/test/automated/python-tests.el @@ -458,6 +458,28 @@ def foo(a, b, c): (should (eq (car (python-indent-context)) 'after-beginning-of-block)) (should (= (python-indent-calculate-indentation) 12)))) +(ert-deftest python-indent-dedenters-2 () + "Check one-liner block special case.." + (python-tests-with-temp-buffer + " +cond = True +if cond: + + if cond: print 'True' +else: print 'False' + +else: + return +" + (python-tests-look-at "else: print 'False'") + ;; When a block has code after ":" it's just considered a simple + ;; line as that's a common thing to happen in one-liners. + (should (eq (car (python-indent-context)) 'after-line)) + (should (= (python-indent-calculate-indentation) 4)) + (python-tests-look-at "else:") + (should (eq (car (python-indent-context)) 'after-line)) + (should (= (python-indent-calculate-indentation) 0)))) + (ert-deftest python-indent-after-backslash-1 () "The most common case." (python-tests-with-temp-buffer -- 2.39.2