From c9415ccbf84fce152e0f4b98ac2ed60680272a47 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fabi=C3=A1n=20Ezequiel=20Gallina?= Date: Thu, 9 Apr 2015 01:41:55 -0300 Subject: [PATCH] python.el: Indent docstring lines to base-indent Fixes: debbugs:19595 Thanks to immerrr for reporting and providing an initial patch. * lisp/progmodes/python.el (python-indent-context): Add :inside-docstring context. (python-indent--calculate-indentation): Handle :inside-docstring. (python-indent-region): Re-indent docstrings. * test/automated/python-tests.el (python-indent-region-5) (python-indent-inside-string-2): Fix tests. --- lisp/progmodes/python.el | 15 ++++++++++++--- test/automated/python-tests.el | 35 ++++++++++++++++++++++++----------- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index da38152558f..856ed322ec6 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -844,7 +844,9 @@ keyword ;; Inside a string. ((let ((start (python-syntax-context 'string ppss))) (when start - (cons :inside-string start)))) + (cons (if (python-info-docstring-p) + :inside-docstring + :inside-string) start)))) ;; Inside a paren. ((let* ((start (python-syntax-context 'paren ppss)) (starts-in-newline @@ -989,6 +991,12 @@ possibilities can be narrowed to specific indentation points." ;; Copy previous indentation. (goto-char start) (current-indentation)) + (`(:inside-docstring . ,start) + (let* ((line-indentation (current-indentation)) + (base-indent (progn + (goto-char start) + (current-indentation)))) + (max line-indentation base-indent))) (`(,(or :after-block-start :after-backslash-first-line :inside-paren-newline-start) . ,start) @@ -1138,14 +1146,15 @@ Called from a program, START and END specify the region to indent." (not line-is-comment-p)) (python-info-current-line-empty-p))))) ;; Don't mess with strings, unless it's the - ;; enclosing set of quotes. + ;; 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 "|"))) + (string-to-syntax "|")) + (python-info-docstring-p)) ;; Skip if current line is a block start, a ;; dedenter or block ender. (save-excursion diff --git a/test/automated/python-tests.el b/test/automated/python-tests.el index 22c111fc04a..47264c3ad31 100644 --- a/test/automated/python-tests.el +++ b/test/automated/python-tests.el @@ -1014,7 +1014,7 @@ lines def fn(a, b, c=True): '''docstring bunch - of + of lines ''' " @@ -1022,16 +1022,17 @@ def fn(a, b, c=True): (should (eq (car (python-indent-context)) :after-block-start)) (should (= (python-indent-calculate-indentation) 4)) (python-tests-look-at "bunch") - (should (eq (car (python-indent-context)) :inside-string)) + (should (eq (car (python-indent-context)) :inside-docstring)) (should (= (python-indent-calculate-indentation) 4)) (python-tests-look-at "of") - (should (eq (car (python-indent-context)) :inside-string)) - (should (= (python-indent-calculate-indentation) 4)) + (should (eq (car (python-indent-context)) :inside-docstring)) + ;; Any indentation deeper than the base-indent must remain unmodified. + (should (= (python-indent-calculate-indentation) 8)) (python-tests-look-at "lines") - (should (eq (car (python-indent-context)) :inside-string)) + (should (eq (car (python-indent-context)) :inside-docstring)) (should (= (python-indent-calculate-indentation) 4)) (python-tests-look-at "'''") - (should (eq (car (python-indent-context)) :inside-string)) + (should (eq (car (python-indent-context)) :inside-docstring)) (should (= (python-indent-calculate-indentation) 4)))) (ert-deftest python-indent-inside-string-3 () @@ -1189,21 +1190,33 @@ def f(): expected))))) (ert-deftest python-indent-region-5 () - "Test region indentation leaves strings untouched (start delimiter)." + "Test region indentation for docstrings." (let ((contents " def f(): ''' this is -a multiline + a multiline string ''' + x = \\ + ''' +this is an arbitrarily + indented multiline + string +''' ") (expected " def f(): ''' -this is -a multiline -string + this is + a multiline + string + ''' + x = \\ + ''' +this is an arbitrarily + indented multiline + string ''' ")) (python-tests-with-temp-buffer -- 2.11.4.GIT