diff options
| author | Fabián Ezequiel Gallina | 2015-04-09 01:41:55 -0300 |
|---|---|---|
| committer | Fabián Ezequiel Gallina | 2015-04-09 01:41:55 -0300 |
| commit | c9415ccbf84fce152e0f4b98ac2ed60680272a47 (patch) | |
| tree | c80e692a8b2871eb66eedd2736259d9335ad8e14 | |
| parent | 911ed2eba4ad691b35e4b81bcd8b24f58b0375ca (diff) | |
| download | emacs-c9415ccbf84fce152e0f4b98ac2ed60680272a47.tar.gz emacs-c9415ccbf84fce152e0f4b98ac2ed60680272a47.zip | |
python.el: Indent docstring lines to base-indent
Fixes: debbugs:19595
Thanks to immerrr <immerrr@gmail.com> 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.
| -rw-r--r-- | lisp/progmodes/python.el | 15 | ||||
| -rw-r--r-- | 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 | |||
| 844 | ;; Inside a string. | 844 | ;; Inside a string. |
| 845 | ((let ((start (python-syntax-context 'string ppss))) | 845 | ((let ((start (python-syntax-context 'string ppss))) |
| 846 | (when start | 846 | (when start |
| 847 | (cons :inside-string start)))) | 847 | (cons (if (python-info-docstring-p) |
| 848 | :inside-docstring | ||
| 849 | :inside-string) start)))) | ||
| 848 | ;; Inside a paren. | 850 | ;; Inside a paren. |
| 849 | ((let* ((start (python-syntax-context 'paren ppss)) | 851 | ((let* ((start (python-syntax-context 'paren ppss)) |
| 850 | (starts-in-newline | 852 | (starts-in-newline |
| @@ -989,6 +991,12 @@ possibilities can be narrowed to specific indentation points." | |||
| 989 | ;; Copy previous indentation. | 991 | ;; Copy previous indentation. |
| 990 | (goto-char start) | 992 | (goto-char start) |
| 991 | (current-indentation)) | 993 | (current-indentation)) |
| 994 | (`(:inside-docstring . ,start) | ||
| 995 | (let* ((line-indentation (current-indentation)) | ||
| 996 | (base-indent (progn | ||
| 997 | (goto-char start) | ||
| 998 | (current-indentation)))) | ||
| 999 | (max line-indentation base-indent))) | ||
| 992 | (`(,(or :after-block-start | 1000 | (`(,(or :after-block-start |
| 993 | :after-backslash-first-line | 1001 | :after-backslash-first-line |
| 994 | :inside-paren-newline-start) . ,start) | 1002 | :inside-paren-newline-start) . ,start) |
| @@ -1138,14 +1146,15 @@ Called from a program, START and END specify the region to indent." | |||
| 1138 | (not line-is-comment-p)) | 1146 | (not line-is-comment-p)) |
| 1139 | (python-info-current-line-empty-p))))) | 1147 | (python-info-current-line-empty-p))))) |
| 1140 | ;; Don't mess with strings, unless it's the | 1148 | ;; Don't mess with strings, unless it's the |
| 1141 | ;; enclosing set of quotes. | 1149 | ;; enclosing set of quotes or a docstring. |
| 1142 | (or (not (python-syntax-context 'string)) | 1150 | (or (not (python-syntax-context 'string)) |
| 1143 | (eq | 1151 | (eq |
| 1144 | (syntax-after | 1152 | (syntax-after |
| 1145 | (+ (1- (point)) | 1153 | (+ (1- (point)) |
| 1146 | (current-indentation) | 1154 | (current-indentation) |
| 1147 | (python-syntax-count-quotes (char-after) (point)))) | 1155 | (python-syntax-count-quotes (char-after) (point)))) |
| 1148 | (string-to-syntax "|"))) | 1156 | (string-to-syntax "|")) |
| 1157 | (python-info-docstring-p)) | ||
| 1149 | ;; Skip if current line is a block start, a | 1158 | ;; Skip if current line is a block start, a |
| 1150 | ;; dedenter or block ender. | 1159 | ;; dedenter or block ender. |
| 1151 | (save-excursion | 1160 | (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 | |||
| 1014 | def fn(a, b, c=True): | 1014 | def fn(a, b, c=True): |
| 1015 | '''docstring | 1015 | '''docstring |
| 1016 | bunch | 1016 | bunch |
| 1017 | of | 1017 | of |
| 1018 | lines | 1018 | lines |
| 1019 | ''' | 1019 | ''' |
| 1020 | " | 1020 | " |
| @@ -1022,16 +1022,17 @@ def fn(a, b, c=True): | |||
| 1022 | (should (eq (car (python-indent-context)) :after-block-start)) | 1022 | (should (eq (car (python-indent-context)) :after-block-start)) |
| 1023 | (should (= (python-indent-calculate-indentation) 4)) | 1023 | (should (= (python-indent-calculate-indentation) 4)) |
| 1024 | (python-tests-look-at "bunch") | 1024 | (python-tests-look-at "bunch") |
| 1025 | (should (eq (car (python-indent-context)) :inside-string)) | 1025 | (should (eq (car (python-indent-context)) :inside-docstring)) |
| 1026 | (should (= (python-indent-calculate-indentation) 4)) | 1026 | (should (= (python-indent-calculate-indentation) 4)) |
| 1027 | (python-tests-look-at "of") | 1027 | (python-tests-look-at "of") |
| 1028 | (should (eq (car (python-indent-context)) :inside-string)) | 1028 | (should (eq (car (python-indent-context)) :inside-docstring)) |
| 1029 | (should (= (python-indent-calculate-indentation) 4)) | 1029 | ;; Any indentation deeper than the base-indent must remain unmodified. |
| 1030 | (should (= (python-indent-calculate-indentation) 8)) | ||
| 1030 | (python-tests-look-at "lines") | 1031 | (python-tests-look-at "lines") |
| 1031 | (should (eq (car (python-indent-context)) :inside-string)) | 1032 | (should (eq (car (python-indent-context)) :inside-docstring)) |
| 1032 | (should (= (python-indent-calculate-indentation) 4)) | 1033 | (should (= (python-indent-calculate-indentation) 4)) |
| 1033 | (python-tests-look-at "'''") | 1034 | (python-tests-look-at "'''") |
| 1034 | (should (eq (car (python-indent-context)) :inside-string)) | 1035 | (should (eq (car (python-indent-context)) :inside-docstring)) |
| 1035 | (should (= (python-indent-calculate-indentation) 4)))) | 1036 | (should (= (python-indent-calculate-indentation) 4)))) |
| 1036 | 1037 | ||
| 1037 | (ert-deftest python-indent-inside-string-3 () | 1038 | (ert-deftest python-indent-inside-string-3 () |
| @@ -1189,21 +1190,33 @@ def f(): | |||
| 1189 | expected))))) | 1190 | expected))))) |
| 1190 | 1191 | ||
| 1191 | (ert-deftest python-indent-region-5 () | 1192 | (ert-deftest python-indent-region-5 () |
| 1192 | "Test region indentation leaves strings untouched (start delimiter)." | 1193 | "Test region indentation for docstrings." |
| 1193 | (let ((contents " | 1194 | (let ((contents " |
| 1194 | def f(): | 1195 | def f(): |
| 1195 | ''' | 1196 | ''' |
| 1196 | this is | 1197 | this is |
| 1197 | a multiline | 1198 | a multiline |
| 1198 | string | 1199 | string |
| 1199 | ''' | 1200 | ''' |
| 1201 | x = \\ | ||
| 1202 | ''' | ||
| 1203 | this is an arbitrarily | ||
| 1204 | indented multiline | ||
| 1205 | string | ||
| 1206 | ''' | ||
| 1200 | ") | 1207 | ") |
| 1201 | (expected " | 1208 | (expected " |
| 1202 | def f(): | 1209 | def f(): |
| 1203 | ''' | 1210 | ''' |
| 1204 | this is | 1211 | this is |
| 1205 | a multiline | 1212 | a multiline |
| 1206 | string | 1213 | string |
| 1214 | ''' | ||
| 1215 | x = \\ | ||
| 1216 | ''' | ||
| 1217 | this is an arbitrarily | ||
| 1218 | indented multiline | ||
| 1219 | string | ||
| 1207 | ''' | 1220 | ''' |
| 1208 | ")) | 1221 | ")) |
| 1209 | (python-tests-with-temp-buffer | 1222 | (python-tests-with-temp-buffer |