|
6 | 6 | ;; 1992-1994 Tim Peters |
7 | 7 | |
8 | 8 | ;; Created: Feb 1992 |
9 | | -;; Version: 2.26 |
10 | | -;; Last Modified: 1995/07/05 23:26:15 |
| 9 | +;; Version: 2.30 |
| 10 | +;; Last Modified: 1995/09/19 20:01:42 |
11 | 11 | ;; Keywords: python editing language major-mode |
12 | 12 |
|
13 | 13 | ;; This software is provided as-is, without express or implied |
|
70 | 70 | ;; LCD Archive Entry: |
71 | 71 | ;; python-mode|Barry A. Warsaw|[email protected] |
72 | 72 | ;; |Major mode for editing Python programs |
73 | | -;; |1995/07/05 23:26:15|2.26| |
| 73 | +;; |1995/09/19 20:01:42|2.30| |
74 | 74 |
|
75 | 75 | ;;; Code: |
76 | 76 |
|
|
86 | 86 | Note that `\\[py-guess-indent-offset]' can usually guess a good value |
87 | 87 | when you're editing someone else's Python code.") |
88 | 88 |
|
| 89 | +(defvar py-align-multiline-strings-p t |
| 90 | + "*Flag describing how multiline triple quoted strings are aligned. |
| 91 | +When this flag is non-nil, continuation lines are lined up under the |
| 92 | +preceding line's indentation. When this flag is nil, continuation |
| 93 | +lines are aligned to column zero.") |
| 94 | + |
89 | 95 | (defvar py-block-comment-prefix "##" |
90 | 96 | "*String used by `py-comment-region' to comment out a block of code. |
91 | 97 | This should follow the convention for non-indenting comment lines so |
@@ -407,6 +413,9 @@ py-beep-if-tab-change\tring the bell if tab-width is changed" |
407 | 413 | mode-name "Python" |
408 | 414 | local-abbrev-table python-mode-abbrev-table) |
409 | 415 | (use-local-map py-mode-map) |
| 416 | + ;; Emacs 19 requires this |
| 417 | + (if (or py-this-is-lucid-emacs-p py-this-is-emacs-19-p) |
| 418 | + (setq comment-multi-line nil)) |
410 | 419 | ;; BAW -- style... |
411 | 420 | (mapcar (function (lambda (x) |
412 | 421 | (make-local-variable (car x)) |
@@ -468,31 +477,39 @@ py-beep-if-tab-change\tring the bell if tab-width is changed" |
468 | 477 | (defun py-electric-colon (arg) |
469 | 478 | "Insert a colon. |
470 | 479 | In certain cases the line is outdented appropriately. If a numeric |
471 | | -argument is provided, that many colons are inserted non-electrically." |
| 480 | +argument is provided, that many colons are inserted non-electrically. |
| 481 | +Electric behavior is inhibited inside a string or comment." |
472 | 482 | (interactive "P") |
473 | 483 | (self-insert-command (prefix-numeric-value arg)) |
474 | | - (save-excursion |
475 | | - (let ((here (point)) |
476 | | - (outdent 0) |
477 | | - (indent (py-compute-indentation))) |
478 | | - (if (and (not arg) |
479 | | - (py-outdent-p) |
480 | | - (= indent (save-excursion |
481 | | - (forward-line -1) |
482 | | - (py-compute-indentation))) |
483 | | - ) |
484 | | - (setq outdent py-indent-offset)) |
485 | | - ;; Don't indent, only outdent. This assumes that any lines that |
486 | | - ;; are already outdented relative to py-compute-indentation were |
487 | | - ;; put there on purpose. Its highly annoying to have `:' indent |
488 | | - ;; for you. Use TAB, C-c C-l or C-c C-r to adjust. TBD: Is |
489 | | - ;; there a better way to determine this??? |
490 | | - (if (< (current-indentation) indent) nil |
491 | | - (goto-char here) |
492 | | - (beginning-of-line) |
493 | | - (delete-horizontal-space) |
494 | | - (indent-to (- indent outdent)) |
495 | | - )))) |
| 484 | + ;; are we in a string or comment? |
| 485 | + (if (save-excursion |
| 486 | + (let ((pps (parse-partial-sexp (save-excursion |
| 487 | + (beginning-of-python-def-or-class) |
| 488 | + (point)) |
| 489 | + (point)))) |
| 490 | + (not (or (nth 3 pps) (nth 4 pps))))) |
| 491 | + (save-excursion |
| 492 | + (let ((here (point)) |
| 493 | + (outdent 0) |
| 494 | + (indent (py-compute-indentation))) |
| 495 | + (if (and (not arg) |
| 496 | + (py-outdent-p) |
| 497 | + (= indent (save-excursion |
| 498 | + (forward-line -1) |
| 499 | + (py-compute-indentation))) |
| 500 | + ) |
| 501 | + (setq outdent py-indent-offset)) |
| 502 | + ;; Don't indent, only outdent. This assumes that any lines that |
| 503 | + ;; are already outdented relative to py-compute-indentation were |
| 504 | + ;; put there on purpose. Its highly annoying to have `:' indent |
| 505 | + ;; for you. Use TAB, C-c C-l or C-c C-r to adjust. TBD: Is |
| 506 | + ;; there a better way to determine this??? |
| 507 | + (if (< (current-indentation) indent) nil |
| 508 | + (goto-char here) |
| 509 | + (beginning-of-line) |
| 510 | + (delete-horizontal-space) |
| 511 | + (indent-to (- indent outdent)) |
| 512 | + ))))) |
496 | 513 |
|
497 | 514 | (defun py-indent-right (arg) |
498 | 515 | "Indent the line by one `py-indent-offset' level. |
@@ -782,102 +799,109 @@ the new line indented." |
782 | 799 |
|
783 | 800 | (defun py-compute-indentation () |
784 | 801 | (save-excursion |
785 | | - (beginning-of-line) |
786 | | - (cond |
787 | | - ;; are we on a continuation line? |
788 | | - ((py-continuation-line-p) |
789 | | - (let ((startpos (point)) |
790 | | - (open-bracket-pos (py-nesting-level)) |
791 | | - endpos searching found) |
792 | | - (if open-bracket-pos |
793 | | - (progn |
794 | | - ;; align with first item in list; else a normal |
795 | | - ;; indent beyond the line with the open bracket |
796 | | - (goto-char (1+ open-bracket-pos)) ; just beyond bracket |
797 | | - ;; is the first list item on the same line? |
798 | | - (skip-chars-forward " \t") |
799 | | - (if (null (memq (following-char) '(?\n ?# ?\\))) |
800 | | - ; yes, so line up with it |
801 | | - (current-column) |
802 | | - ;; first list item on another line, or doesn't exist yet |
803 | | - (forward-line 1) |
804 | | - (while (and (< (point) startpos) |
805 | | - (looking-at "[ \t]*[#\n\\\\]")) ; skip noise |
806 | | - (forward-line 1)) |
807 | | - (if (< (point) startpos) |
808 | | - ;; again mimic the first list item |
809 | | - (current-indentation) |
810 | | - ;; else they're about to enter the first item |
811 | | - (goto-char open-bracket-pos) |
812 | | - (+ (current-indentation) py-indent-offset)))) |
813 | | - |
814 | | - ;; else on backslash continuation line |
815 | | - (forward-line -1) |
816 | | - (if (py-continuation-line-p) ; on at least 3rd line in block |
817 | | - (current-indentation) ; so just continue the pattern |
818 | | - ;; else started on 2nd line in block, so indent more. |
819 | | - ;; if base line is an assignment with a start on a RHS, |
820 | | - ;; indent to 2 beyond the leftmost "="; else skip first |
821 | | - ;; chunk of non-whitespace characters on base line, + 1 more |
822 | | - ;; column |
823 | | - (end-of-line) |
824 | | - (setq endpos (point) searching t) |
| 802 | + (let ((pps (parse-partial-sexp (save-excursion |
| 803 | + (beginning-of-python-def-or-class) |
| 804 | + (point)) |
| 805 | + (point)))) |
| 806 | + (beginning-of-line) |
| 807 | + (cond |
| 808 | + ;; are we inside a string or comment? |
| 809 | + ((or (nth 3 pps) (nth 4 pps)) |
| 810 | + (save-excursion |
| 811 | + (if (not py-align-multiline-strings-p) 0 |
| 812 | + ;; skip back over blank & non-indenting comment lines |
| 813 | + ;; note: will skip a blank or non-indenting comment line |
| 814 | + ;; that happens to be a continuation line too |
| 815 | + (re-search-backward "^[ \t]*\\([^ \t\n#]\\|#[ \t\n]\\)" nil 'move) |
825 | 816 | (back-to-indentation) |
826 | | - (setq startpos (point)) |
827 | | - ;; look at all "=" from left to right, stopping at first |
828 | | - ;; one not nested in a list or string |
829 | | - (while searching |
830 | | - (skip-chars-forward "^=" endpos) |
831 | | - (if (= (point) endpos) |
832 | | - (setq searching nil) |
833 | | - (forward-char 1) |
834 | | - (setq state (parse-partial-sexp startpos (point))) |
835 | | - (if (and (zerop (car state)) ; not in a bracket |
836 | | - (null (nth 3 state))) ; & not in a string |
837 | | - (progn |
838 | | - (setq searching nil) ; done searching in any case |
839 | | - (setq found |
840 | | - (not (or |
841 | | - (eq (following-char) ?=) |
842 | | - (memq (char-after (- (point) 2)) |
843 | | - '(?< ?> ?!))))))))) |
844 | | - (if (or (not found) ; not an assignment |
845 | | - (looking-at "[ \t]*\\\\")) ; <=><spaces><backslash> |
846 | | - (progn |
847 | | - (goto-char startpos) |
848 | | - (skip-chars-forward "^ \t\n"))) |
849 | | - (1+ (current-column)))))) |
850 | | - |
851 | | - ;; not on a continuation line |
852 | | - |
853 | | - ;; if at start of restriction, or on a non-indenting comment line, |
854 | | - ;; assume they intended whatever's there |
855 | | - ((or (bobp) (looking-at "[ \t]*#[^ \t\n]")) |
856 | | - (current-indentation)) |
857 | | - |
858 | | - ;; else indentation based on that of the statement that precedes |
859 | | - ;; us; use the first line of that statement to establish the base, |
860 | | - ;; in case the user forced a non-std indentation for the |
861 | | - ;; continuation lines (if any) |
862 | | - (t |
863 | | - ;; skip back over blank & non-indenting comment lines |
864 | | - ;; note: will skip a blank or non-indenting comment line that |
865 | | - ;; happens to be a continuation line too |
866 | | - (re-search-backward "^[ \t]*\\([^ \t\n#]\\|#[ \t\n]\\)" |
867 | | - nil 'move) |
868 | | - ;; if we landed inside a string, go to the beginning of that |
869 | | - ;; string. this handles triple quoted, multi-line spanning |
870 | | - ;; strings. |
871 | | - (let ((state (parse-partial-sexp |
872 | | - (save-excursion (beginning-of-python-def-or-class) |
873 | | - (point)) |
874 | | - (point)))) |
875 | | - (if (nth 3 state) |
876 | | - (goto-char (nth 2 state)))) |
877 | | - (py-goto-initial-line) |
878 | | - (if (py-statement-opens-block-p) |
879 | | - (+ (current-indentation) py-indent-offset) |
880 | | - (current-indentation)))))) |
| 817 | + (current-column)))) |
| 818 | + ;; are we on a continuation line? |
| 819 | + ((py-continuation-line-p) |
| 820 | + (let ((startpos (point)) |
| 821 | + (open-bracket-pos (py-nesting-level)) |
| 822 | + endpos searching found) |
| 823 | + (if open-bracket-pos |
| 824 | + (progn |
| 825 | + ;; align with first item in list; else a normal |
| 826 | + ;; indent beyond the line with the open bracket |
| 827 | + (goto-char (1+ open-bracket-pos)) ; just beyond bracket |
| 828 | + ;; is the first list item on the same line? |
| 829 | + (skip-chars-forward " \t") |
| 830 | + (if (null (memq (following-char) '(?\n ?# ?\\))) |
| 831 | + ; yes, so line up with it |
| 832 | + (current-column) |
| 833 | + ;; first list item on another line, or doesn't exist yet |
| 834 | + (forward-line 1) |
| 835 | + (while (and (< (point) startpos) |
| 836 | + (looking-at "[ \t]*[#\n\\\\]")) ; skip noise |
| 837 | + (forward-line 1)) |
| 838 | + (if (< (point) startpos) |
| 839 | + ;; again mimic the first list item |
| 840 | + (current-indentation) |
| 841 | + ;; else they're about to enter the first item |
| 842 | + (goto-char open-bracket-pos) |
| 843 | + (+ (current-indentation) py-indent-offset)))) |
| 844 | + |
| 845 | + ;; else on backslash continuation line |
| 846 | + (forward-line -1) |
| 847 | + (if (py-continuation-line-p) ; on at least 3rd line in block |
| 848 | + (current-indentation) ; so just continue the pattern |
| 849 | + ;; else started on 2nd line in block, so indent more. |
| 850 | + ;; if base line is an assignment with a start on a RHS, |
| 851 | + ;; indent to 2 beyond the leftmost "="; else skip first |
| 852 | + ;; chunk of non-whitespace characters on base line, + 1 more |
| 853 | + ;; column |
| 854 | + (end-of-line) |
| 855 | + (setq endpos (point) searching t) |
| 856 | + (back-to-indentation) |
| 857 | + (setq startpos (point)) |
| 858 | + ;; look at all "=" from left to right, stopping at first |
| 859 | + ;; one not nested in a list or string |
| 860 | + (while searching |
| 861 | + (skip-chars-forward "^=" endpos) |
| 862 | + (if (= (point) endpos) |
| 863 | + (setq searching nil) |
| 864 | + (forward-char 1) |
| 865 | + (setq state (parse-partial-sexp startpos (point))) |
| 866 | + (if (and (zerop (car state)) ; not in a bracket |
| 867 | + (null (nth 3 state))) ; & not in a string |
| 868 | + (progn |
| 869 | + (setq searching nil) ; done searching in any case |
| 870 | + (setq found |
| 871 | + (not (or |
| 872 | + (eq (following-char) ?=) |
| 873 | + (memq (char-after (- (point) 2)) |
| 874 | + '(?< ?> ?!))))))))) |
| 875 | + (if (or (not found) ; not an assignment |
| 876 | + (looking-at "[ \t]*\\\\")) ; <=><spaces><backslash> |
| 877 | + (progn |
| 878 | + (goto-char startpos) |
| 879 | + (skip-chars-forward "^ \t\n"))) |
| 880 | + (1+ (current-column)))))) |
| 881 | + |
| 882 | + ;; not on a continuation line |
| 883 | + |
| 884 | + ;; if at start of restriction, or on a non-indenting comment |
| 885 | + ;; line, assume they intended whatever's there |
| 886 | + ((or (bobp) (looking-at "[ \t]*#[^ \t\n]")) |
| 887 | + (current-indentation)) |
| 888 | + |
| 889 | + ;; else indentation based on that of the statement that |
| 890 | + ;; precedes us; use the first line of that statement to |
| 891 | + ;; establish the base, in case the user forced a non-std |
| 892 | + ;; indentation for the continuation lines (if any) |
| 893 | + (t |
| 894 | + ;; skip back over blank & non-indenting comment lines note: |
| 895 | + ;; will skip a blank or non-indenting comment line that |
| 896 | + ;; happens to be a continuation line too |
| 897 | + (re-search-backward "^[ \t]*\\([^ \t\n#]\\|#[ \t\n]\\)" nil 'move) |
| 898 | + ;; if we landed inside a string, go to the beginning of that |
| 899 | + ;; string. this handles triple quoted, multi-line spanning |
| 900 | + ;; strings. |
| 901 | + (py-goto-initial-line) |
| 902 | + (if (py-statement-opens-block-p) |
| 903 | + (+ (current-indentation) py-indent-offset) |
| 904 | + (current-indentation))))))) |
881 | 905 |
|
882 | 906 | (defun py-guess-indent-offset (&optional global) |
883 | 907 | "Guess a good value for, and change, `py-indent-offset'. |
@@ -1964,7 +1988,7 @@ local bindings to py-newline-and-indent.")) |
1964 | 1988 | (setq zmacs-region-stays t))) |
1965 | 1989 |
|
1966 | 1990 |
|
1967 | | -(defconst py-version "2.26" |
| 1991 | +(defconst py-version "2.30" |
1968 | 1992 | "`python-mode' version number.") |
1969 | 1993 | ( defconst py-help-address "[email protected]" |
1970 | 1994 | "Address accepting submission of bug reports.") |
|
0 commit comments