[EMACS] python-mode patch, 1.08a -> 1.08ax

Tim Peters (tim@ksr.com)
Sat, 16 Apr 94 01:44:16 -0400

Attached is a patch to be applied against the Python/Misc/python-mode.el
distributed with Python 1.0.0:

cd $YOUR_ROOT/Python/Misc
patch < this_message

Don's change for indenting continuation lines in open paren/brace/bracket
structures is implemented close to the way he did it, and indentation of
backslash continuation lines now follows a different scheme suggested by
Guido. See the long form of the mode docs for details (`C-c ?').
Sometimes the suggested indentation under both schemes is irritating (no
more so than under the old scheme, though!); send examples of what you
don't like along with a precise statement of what you _would_ have liked
instead, & I'll try to infer better rules. Examples that require
telepathy or prognostication are especially encouraged <snort>.

WARNING: The old py-continuation-offset variable is gone. I never liked
it, and it doesn't make sense under the new schemes. For backward
compatibility, don't apply the patch <wink>.

Besides continuation-line fiddling, the Emacs indent-region function has
been declawed in py-mode buffers, and a bug fixed that was introduced
when Python added double-quoted strings.

almost-forgot-those-last-two-ly y'rs - tim

Tim Peters tim@ksr.com
not speaking for Kendall Square Research Corp

Change log

version 1.08ax
teach py-stringlit-re and py-continued-re about double-quoted strings
e.g. a = "#" + \
wasn't recognized as a continued line
make indent-region-function a local vrbl & set to py-indent-region
fiddle indentation for continuation lines
adapt unclosed brace/bracket/paren scheme from donald beaudry
implement guido's suggestion for backslash lines
purge py-continuation-offset
update docs

*** python-mode.el Sat Apr 16 00:56:35 1994
--- ../python-mode.el Sat Apr 16 00:42:56 1994
***************
*** 1,4 ****
! ;;; Major mode for editing Python programs, version 1.08a
;; by: Tim Peters <tim@ksr.com>
;; after an original idea by: Michael A. Guravage
;;
--- 1,4 ----
! ;;; Major mode for editing Python programs, version 1.08ax
;; by: Tim Peters <tim@ksr.com>
;; after an original idea by: Michael A. Guravage
;;
***************
*** 40,55 ****
Note that `\\[py-guess-indent-offset]' can usually guess a good value when you're
editing someone else's Python code.")

- (defvar py-continuation-offset 2
- "*Indentation (in addition to py-indent-offset) for continued lines.
- The additional indentation given to the first continuation line in a
- multi-line statement. Each subsequent continuation line in the
- statement inherits its indentation from the line that precedes it, so if
- you don't like the default indentation given to the first continuation
- line, change it to something you do like and Python-mode will
- automatically use that for the remaining continuation lines (or, until
- you change the indentation again).")
-
(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
--- 40,45 ----
***************
*** 204,210 ****
( ?\# . "<") ; hash starts comment
( ?\n . ">")))) ; newline ends comment

! (defconst py-stringlit-re "'\\([^'\n\\]\\|\\\\.\\)*'"
"regexp matching a Python string literal")

;; this is tricky because a trailing backslash does not mean
--- 194,204 ----
( ?\# . "<") ; hash starts comment
( ?\n . ">")))) ; newline ends comment

! (defconst py-stringlit-re
! (concat
! "'\\([^'\n\\]\\|\\\\.\\)*'" ; single-quoted
! "\\|" ; or
! "\"\\([^\"\n\\]\\|\\\\.\\)*\"") ; double-quoted
"regexp matching a Python string literal")

;; this is tricky because a trailing backslash does not mean
***************
*** 211,219 ****
;; continuation if it's in a comment
(defconst py-continued-re
(concat
! "\\(" "[^#'\n\\]" "\\|" py-stringlit-re "\\)*"
"\\\\$")
! "regexp matching Python lines that are continued")

(defconst py-blank-or-comment-re "[ \t]*\\($\\|#\\)"
"regexp matching blank or comment lines")
--- 205,213 ----
;; continuation if it's in a comment
(defconst py-continued-re
(concat
! "\\(" "[^#'\"\n\\]" "\\|" py-stringlit-re "\\)*"
"\\\\$")
! "regexp matching Python lines that are continued via backslash")

(defconst py-blank-or-comment-re "[ \t]*\\($\\|#\\)"
"regexp matching blank or comment lines")
***************
*** 231,237 ****
VARIABLES

py-indent-offset\tindentation increment
- py-continuation-offset\textra indentation given to continuation lines
py-block-comment-prefix\tcomment string used by py-comment-region
py-python-command\tshell command to invoke Python interpreter
py-scroll-process-buffer\talways scroll Python process buffer
--- 225,230 ----
***************
*** 254,259 ****
--- 247,253 ----
(comment-start . "# ")
(comment-start-skip . "# *")
(comment-column . 40)
+ (indent-region-function . py-indent-region)
(indent-line-function . py-indent-line)))

;; hack to allow overriding the tabsize in the file (see tokenizer.c)
***************
*** 515,526 ****
(cond
;; are we on a continuation line?
( (py-continuation-line-p)
! (forward-line -1)
! (if (py-continuation-line-p) ; on at least 3rd line in block
! (current-indentation) ; so just continue the pattern
! ;; else on 2nd line in block, so indent more
! (+ (current-indentation) py-indent-offset
! py-continuation-offset)))
;; not on a continuation line

;; if at start of restriction, or on a non-indenting comment line,
--- 509,535 ----
(cond
;; are we on a continuation line?
( (py-continuation-line-p)
! (let ( (open-bracket-pos (py-nesting-level)) )
! (if open-bracket-pos
! ;; line up with first real character (not whitespace or
! ;; comment hash) after open bracket; if none, to one
! ;; column beyond the open bracket
! (progn
! (goto-char (1+ open-bracket-pos)) ; just beyond bracket
! (and (looking-at "[ \t]*[^ \t\n#]")
! (goto-char (1- (match-end 0))))
! (current-column))
! ;; 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;
! ;; skip first chunk of non-whitespace characters on base
! ;; line, + 1 more column
! (back-to-indentation)
! (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,
***************
*** 1144,1150 ****
@VARIABLES

py-indent-offset\tindentation increment
- py-continuation-offset\textra indentation given to continuation lines
py-block-comment-prefix\tcomment string used by py-comment-region

py-python-command\tshell command to invoke Python interpreter
--- 1153,1158 ----
***************
*** 1153,1159 ****

py-beep-if-tab-change\tring the bell if tab-width is changed
%v:py-indent-offset
- %v:py-continuation-offset
%v:py-block-comment-prefix
%v:py-python-command
%v:py-scroll-process-buffer
--- 1161,1166 ----
***************
*** 1209,1225 ****
statement containing point, even if point happens to be in the middle of
some continuation line.

- A Bad Idea

- Always put something on the initial line of a multi-line statement
- besides the backslash! E.g., don't do this:
-
- \t\\
- \ta = b # what's the indentation of this stmt?
-
- While that's legal Python, it's silly & would be very expensive for
- Python mode to handle correctly.
-
@INDENTATION

Primarily for entering new code:
--- 1216,1222 ----
***************
*** 1265,1270 ****
--- 1262,1280 ----
statement has `:' as its last significant (non-whitespace and non-
comment) character. If the suggested indentation is too much, use
\\[py-delete-char] to reduce it.
+
+ Continuation lines are given extra indentation. If a line is a
+ continuation line by virtue of being in an unclosed paren/bracket/
+ brace structure, it's indented to line up with the first non-whitespace
+ and non-comment character following the opening paren/bracket/brace
+ of the smallest such enclosing structure. If no such character exists,
+ it's indented to one column beyond the opening paren/bracket/brace.
+
+ If a line is a continuation line because the line preceding it ends with
+ a backslash, the third and following lines of the continuation block
+ inherit their indentation from the line preceding them, while the second
+ line in the block is indented to one column beyond the first chunk of
+ non-whitespace characters in the block's initial line.

Warning: indent-region should not normally be used! It calls \\[indent-for-tab-command]
repeatedly, and as explained above, \\[indent-for-tab-command] can't guess the block

>>> END OF PATCH