summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Misc/python-mode.el211
1 files changed, 105 insertions, 106 deletions
diff --git a/Misc/python-mode.el b/Misc/python-mode.el
index d5fb956..91b1a9f 100644
--- a/Misc/python-mode.el
+++ b/Misc/python-mode.el
@@ -86,6 +86,12 @@
Note that `\\[py-guess-indent-offset]' can usually guess a good value
when you're editing someone else's Python code.")
+(defvar py-align-multiline-strings-p t
+ "*Flag describing how multiline triple quoted strings are aligned.
+When this flag is non-nil, continuation lines are lined up under the
+preceding line's indentation. When this flag is nil, continuation
+lines are aligned to column zero.")
+
(defvar py-block-comment-prefix "##"
"*String used by `py-comment-region' to comment out a block of code.
This should follow the convention for non-indenting comment lines so
@@ -793,116 +799,109 @@ the new line indented."
(defun py-compute-indentation ()
(save-excursion
- (beginning-of-line)
- (cond
- ;; are we inside a string or comment?
- ((save-excursion
- (let ((pps (parse-partial-sexp (save-excursion
- (beginning-of-python-def-or-class)
- (point))
- (point))))
- (or (nth 3 pps) (nth 4 pps))))
- (save-excursion
+ (let ((pps (parse-partial-sexp (save-excursion
+ (beginning-of-python-def-or-class)
+ (point))
+ (point))))
+ (beginning-of-line)
+ (cond
+ ;; are we inside a string or comment?
+ ((or (nth 3 pps) (nth 4 pps))
+ (save-excursion
+ (if (not py-align-multiline-strings-p) 0
+ ;; skip back over blank & non-indenting comment lines
+ ;; note: will skip a blank or non-indenting comment line
+ ;; that happens to be a continuation line too
+ (re-search-backward "^[ \t]*\\([^ \t\n#]\\|#[ \t\n]\\)" nil 'move)
+ (back-to-indentation)
+ (current-column))))
+ ;; are we on a continuation line?
+ ((py-continuation-line-p)
+ (let ((startpos (point))
+ (open-bracket-pos (py-nesting-level))
+ endpos searching found)
+ (if open-bracket-pos
+ (progn
+ ;; align with first item in list; else a normal
+ ;; indent beyond the line with the open bracket
+ (goto-char (1+ open-bracket-pos)) ; just beyond bracket
+ ;; is the first list item on the same line?
+ (skip-chars-forward " \t")
+ (if (null (memq (following-char) '(?\n ?# ?\\)))
+ ; yes, so line up with it
+ (current-column)
+ ;; first list item on another line, or doesn't exist yet
+ (forward-line 1)
+ (while (and (< (point) startpos)
+ (looking-at "[ \t]*[#\n\\\\]")) ; skip noise
+ (forward-line 1))
+ (if (< (point) startpos)
+ ;; again mimic the first list item
+ (current-indentation)
+ ;; else they're about to enter the first item
+ (goto-char open-bracket-pos)
+ (+ (current-indentation) py-indent-offset))))
+
+ ;; else on backslash continuation line
+ (forward-line -1)
+ (if (py-continuation-line-p) ; on at least 3rd line in block
+ (current-indentation) ; so just continue the pattern
+ ;; else started on 2nd line in block, so indent more.
+ ;; if base line is an assignment with a start on a RHS,
+ ;; indent to 2 beyond the leftmost "="; else skip first
+ ;; chunk of non-whitespace characters on base line, + 1 more
+ ;; column
+ (end-of-line)
+ (setq endpos (point) searching t)
+ (back-to-indentation)
+ (setq startpos (point))
+ ;; look at all "=" from left to right, stopping at first
+ ;; one not nested in a list or string
+ (while searching
+ (skip-chars-forward "^=" endpos)
+ (if (= (point) endpos)
+ (setq searching nil)
+ (forward-char 1)
+ (setq state (parse-partial-sexp startpos (point)))
+ (if (and (zerop (car state)) ; not in a bracket
+ (null (nth 3 state))) ; & not in a string
+ (progn
+ (setq searching nil) ; done searching in any case
+ (setq found
+ (not (or
+ (eq (following-char) ?=)
+ (memq (char-after (- (point) 2))
+ '(?< ?> ?!)))))))))
+ (if (or (not found) ; not an assignment
+ (looking-at "[ \t]*\\\\")) ; <=><spaces><backslash>
+ (progn
+ (goto-char startpos)
+ (skip-chars-forward "^ \t\n")))
+ (1+ (current-column))))))
+
+ ;; not on a continuation line
+
+ ;; if at start of restriction, or on a non-indenting comment
+ ;; line, assume they intended whatever's there
+ ((or (bobp) (looking-at "[ \t]*#[^ \t\n]"))
+ (current-indentation))
+
+ ;; else indentation based on that of the statement that
+ ;; precedes us; use the first line of that statement to
+ ;; establish the base, in case the user forced a non-std
+ ;; indentation for the continuation lines (if any)
+ (t
;; skip back over blank & non-indenting comment lines note:
;; will skip a blank or non-indenting comment line that
;; happens to be a continuation line too
(re-search-backward "^[ \t]*\\([^ \t\n#]\\|#[ \t\n]\\)" nil 'move)
- (back-to-indentation)
- (current-column)))
- ;; are we on a continuation line?
- ((py-continuation-line-p)
- (let ((startpos (point))
- (open-bracket-pos (py-nesting-level))
- endpos searching found)
- (if open-bracket-pos
- (progn
- ;; align with first item in list; else a normal
- ;; indent beyond the line with the open bracket
- (goto-char (1+ open-bracket-pos)) ; just beyond bracket
- ;; is the first list item on the same line?
- (skip-chars-forward " \t")
- (if (null (memq (following-char) '(?\n ?# ?\\)))
- ; yes, so line up with it
- (current-column)
- ;; first list item on another line, or doesn't exist yet
- (forward-line 1)
- (while (and (< (point) startpos)
- (looking-at "[ \t]*[#\n\\\\]")) ; skip noise
- (forward-line 1))
- (if (< (point) startpos)
- ;; again mimic the first list item
- (current-indentation)
- ;; else they're about to enter the first item
- (goto-char open-bracket-pos)
- (+ (current-indentation) py-indent-offset))))
-
- ;; else on backslash continuation line
- (forward-line -1)
- (if (py-continuation-line-p) ; on at least 3rd line in block
- (current-indentation) ; so just continue the pattern
- ;; else started on 2nd line in block, so indent more.
- ;; if base line is an assignment with a start on a RHS,
- ;; indent to 2 beyond the leftmost "="; else skip first
- ;; chunk of non-whitespace characters on base line, + 1 more
- ;; column
- (end-of-line)
- (setq endpos (point) searching t)
- (back-to-indentation)
- (setq startpos (point))
- ;; look at all "=" from left to right, stopping at first
- ;; one not nested in a list or string
- (while searching
- (skip-chars-forward "^=" endpos)
- (if (= (point) endpos)
- (setq searching nil)
- (forward-char 1)
- (setq state (parse-partial-sexp startpos (point)))
- (if (and (zerop (car state)) ; not in a bracket
- (null (nth 3 state))) ; & not in a string
- (progn
- (setq searching nil) ; done searching in any case
- (setq found
- (not (or
- (eq (following-char) ?=)
- (memq (char-after (- (point) 2))
- '(?< ?> ?!)))))))))
- (if (or (not found) ; not an assignment
- (looking-at "[ \t]*\\\\")) ; <=><spaces><backslash>
- (progn
- (goto-char startpos)
- (skip-chars-forward "^ \t\n")))
- (1+ (current-column))))))
-
- ;; not on a continuation line
-
- ;; if at start of restriction, or on a non-indenting comment line,
- ;; assume they intended whatever's there
- ((or (bobp) (looking-at "[ \t]*#[^ \t\n]"))
- (current-indentation))
-
- ;; else indentation based on that of the statement that precedes
- ;; us; use the first line of that statement to establish the base,
- ;; in case the user forced a non-std indentation for the
- ;; continuation lines (if any)
- (t
- ;; skip back over blank & non-indenting comment lines
- ;; note: will skip a blank or non-indenting comment line that
- ;; happens to be a continuation line too
- (re-search-backward "^[ \t]*\\([^ \t\n#]\\|#[ \t\n]\\)"
- nil 'move)
- ;; if we landed inside a string, go to the beginning of that
- ;; string. this handles triple quoted, multi-line spanning
- ;; strings.
- (let ((state (parse-partial-sexp
- (save-excursion (beginning-of-python-def-or-class)
- (point))
- (point))))
- (if (nth 3 state)
- (goto-char (nth 2 state))))
- (py-goto-initial-line)
- (if (py-statement-opens-block-p)
- (+ (current-indentation) py-indent-offset)
- (current-indentation))))))
+ ;; if we landed inside a string, go to the beginning of that
+ ;; string. this handles triple quoted, multi-line spanning
+ ;; strings.
+ (py-goto-initial-line)
+ (if (py-statement-opens-block-p)
+ (+ (current-indentation) py-indent-offset)
+ (current-indentation)))))))
(defun py-guess-indent-offset (&optional global)
"Guess a good value for, and change, `py-indent-offset'.