diff options
| author | Stefan Monnier | 2007-09-10 20:02:31 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2007-09-10 20:02:31 +0000 |
| commit | 308114ef9f06dd70ad50983a0c2504e064dadd52 (patch) | |
| tree | 9d1124adc5a839903f1771e5d0554306777b7f88 | |
| parent | b4f92cff9a60f70b0de780fe637a40583140944f (diff) | |
| download | emacs-308114ef9f06dd70ad50983a0c2504e064dadd52.tar.gz emacs-308114ef9f06dd70ad50983a0c2504e064dadd52.zip | |
Merge changes from Dave Love's v2007-Sep-10.
(python-font-lock-keywords): Update to the 2.5 version of the language.
(python-quote-syntax): Let-bind font-lock-syntactic-keywords to nil.
(python-backspace): Only behave funny in code.
(python-compilation-regexp-alist): Add PDB stack trace regexp.
(inferior-python-mode): Add PDB prompt regexp.
(python-fill-paragraph): Refine the fenced-string regexp.
(python-find-imports): Handle imports spanning several lines.
(python-mode): Add `class' to hideshow support.
| -rw-r--r-- | lisp/ChangeLog | 12 | ||||
| -rw-r--r-- | lisp/progmodes/python.el | 111 |
2 files changed, 78 insertions, 45 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 055cdc75af3..c3d8fd8b92d 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,15 @@ | |||
| 1 | 2007-09-10 Dave Love <fx@gnu.org> | ||
| 2 | |||
| 3 | * progmodes/python.el: Merge changes from Dave Love's v2007-Sep-10. | ||
| 4 | (python-font-lock-keywords): Update to the 2.5 version of the language. | ||
| 5 | (python-quote-syntax): Let-bind font-lock-syntactic-keywords to nil. | ||
| 6 | (python-backspace): Only behave funny in code. | ||
| 7 | (python-compilation-regexp-alist): Add PDB stack trace regexp. | ||
| 8 | (inferior-python-mode): Add PDB prompt regexp. | ||
| 9 | (python-fill-paragraph): Refine the fenced-string regexp. | ||
| 10 | (python-find-imports): Handle imports spanning several lines. | ||
| 11 | (python-mode): Add `class' to hideshow support. | ||
| 12 | |||
| 1 | 2007-09-08 Stefan Monnier <monnier@iro.umontreal.ca> | 13 | 2007-09-08 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 14 | ||
| 3 | * pcvs.el (cvs-mode-add-change-log-entry-other-window): Use | 15 | * pcvs.el (cvs-mode-add-change-log-entry-other-window): Use |
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 7c1abaf223d..2d386e109d9 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; python.el --- silly walks for Python | 1 | ;;; python.el --- silly walks for Python -*- coding: iso-8859-1 -*- |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. |
| 4 | 4 | ||
| @@ -89,17 +89,17 @@ | |||
| 89 | 89 | ||
| 90 | (defvar python-font-lock-keywords | 90 | (defvar python-font-lock-keywords |
| 91 | `(,(rx symbol-start | 91 | `(,(rx symbol-start |
| 92 | ;; From v 2.4 reference. | 92 | ;; From v 2.5 reference, § keywords. |
| 93 | ;; def and class dealt with separately below | 93 | ;; def and class dealt with separately below |
| 94 | (or "and" "assert" "break" "continue" "del" "elif" "else" | 94 | (or "and" "as" "assert" "break" "continue" "del" "elif" "else" |
| 95 | "except" "exec" "finally" "for" "from" "global" "if" | 95 | "except" "exec" "finally" "for" "from" "global" "if" |
| 96 | "import" "in" "is" "lambda" "not" "or" "pass" "print" | 96 | "import" "in" "is" "lambda" "not" "or" "pass" "print" |
| 97 | "raise" "return" "try" "while" "yield" | 97 | "raise" "return" "try" "while" "with" "yield" |
| 98 | ;; Future keywords | ||
| 99 | "as" "None" "with" | ||
| 100 | ;; Not real keywords, but close enough to be fontified as such | 98 | ;; Not real keywords, but close enough to be fontified as such |
| 101 | "self" "True" "False") | 99 | "self" "True" "False") |
| 102 | symbol-end) | 100 | symbol-end) |
| 101 | (,(rx symbol-start "None" symbol-end) ; See § Keywords in 2.5 manual. | ||
| 102 | . font-lock-constant-face) | ||
| 103 | ;; Definitions | 103 | ;; Definitions |
| 104 | (,(rx symbol-start (group "class") (1+ space) (group (1+ (or word ?_)))) | 104 | (,(rx symbol-start (group "class") (1+ space) (group (1+ (or word ?_)))) |
| 105 | (1 font-lock-keyword-face) (2 font-lock-type-face)) | 105 | (1 font-lock-keyword-face) (2 font-lock-type-face)) |
| @@ -151,7 +151,8 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)." | |||
| 151 | (cond | 151 | (cond |
| 152 | ;; Consider property for the last char if in a fenced string. | 152 | ;; Consider property for the last char if in a fenced string. |
| 153 | ((= n 3) | 153 | ((= n 3) |
| 154 | (let ((syntax (syntax-ppss))) | 154 | (let* ((font-lock-syntactic-keywords nil) |
| 155 | (syntax (syntax-ppss))) | ||
| 155 | (when (eq t (nth 3 syntax)) ; after unclosed fence | 156 | (when (eq t (nth 3 syntax)) ; after unclosed fence |
| 156 | (goto-char (nth 8 syntax)) ; fence position | 157 | (goto-char (nth 8 syntax)) ; fence position |
| 157 | (skip-chars-forward "uUrR") ; skip any prefix | 158 | (skip-chars-forward "uUrR") ; skip any prefix |
| @@ -163,8 +164,9 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)." | |||
| 163 | (= (match-beginning 1) (match-end 1))) ; prefix is null | 164 | (= (match-beginning 1) (match-end 1))) ; prefix is null |
| 164 | (and (= n 1) ; prefix | 165 | (and (= n 1) ; prefix |
| 165 | (/= (match-beginning 1) (match-end 1)))) ; non-empty | 166 | (/= (match-beginning 1) (match-end 1)))) ; non-empty |
| 166 | (unless (nth 3 (syntax-ppss)) | 167 | (let ((font-lock-syntactic-keywords nil)) |
| 167 | (eval-when-compile (string-to-syntax "|")))) | 168 | (unless (nth 3 (syntax-ppss)) |
| 169 | (eval-when-compile (string-to-syntax "|"))))) | ||
| 168 | ;; Otherwise (we're in a non-matching string) the property is | 170 | ;; Otherwise (we're in a non-matching string) the property is |
| 169 | ;; nil, which is OK. | 171 | ;; nil, which is OK. |
| 170 | ))) | 172 | ))) |
| @@ -348,7 +350,7 @@ comments and strings, or that point is within brackets/parens." | |||
| 348 | (error nil)))))))) | 350 | (error nil)))))))) |
| 349 | 351 | ||
| 350 | (defun python-comment-line-p () | 352 | (defun python-comment-line-p () |
| 351 | "Return non-nil if current line has only a comment." | 353 | "Return non-nil iff current line has only a comment." |
| 352 | (save-excursion | 354 | (save-excursion |
| 353 | (end-of-line) | 355 | (end-of-line) |
| 354 | (when (eq 'comment (syntax-ppss-context (syntax-ppss))) | 356 | (when (eq 'comment (syntax-ppss-context (syntax-ppss))) |
| @@ -356,7 +358,7 @@ comments and strings, or that point is within brackets/parens." | |||
| 356 | (looking-at (rx (or (syntax comment-start) line-end)))))) | 358 | (looking-at (rx (or (syntax comment-start) line-end)))))) |
| 357 | 359 | ||
| 358 | (defun python-blank-line-p () | 360 | (defun python-blank-line-p () |
| 359 | "Return non-nil if current line is blank." | 361 | "Return non-nil iff current line is blank." |
| 360 | (save-excursion | 362 | (save-excursion |
| 361 | (beginning-of-line) | 363 | (beginning-of-line) |
| 362 | (looking-at "\\s-*$"))) | 364 | (looking-at "\\s-*$"))) |
| @@ -850,7 +852,7 @@ multi-line bracketed expressions." | |||
| 850 | "Skip out of any nested brackets. | 852 | "Skip out of any nested brackets. |
| 851 | Skip forward if FORWARD is non-nil, else backward. | 853 | Skip forward if FORWARD is non-nil, else backward. |
| 852 | If SYNTAX is non-nil it is the state returned by `syntax-ppss' at point. | 854 | If SYNTAX is non-nil it is the state returned by `syntax-ppss' at point. |
| 853 | Return non-nil if skipping was done." | 855 | Return non-nil iff skipping was done." |
| 854 | (let ((depth (syntax-ppss-depth (or syntax (syntax-ppss)))) | 856 | (let ((depth (syntax-ppss-depth (or syntax (syntax-ppss)))) |
| 855 | (forward (if forward -1 1))) | 857 | (forward (if forward -1 1))) |
| 856 | (unless (zerop depth) | 858 | (unless (zerop depth) |
| @@ -1075,13 +1077,15 @@ just insert a single colon." | |||
| 1075 | 1077 | ||
| 1076 | (defun python-backspace (arg) | 1078 | (defun python-backspace (arg) |
| 1077 | "Maybe delete a level of indentation on the current line. | 1079 | "Maybe delete a level of indentation on the current line. |
| 1078 | Do so if point is at the end of the line's indentation. | 1080 | Do so if point is at the end of the line's indentation outside |
| 1081 | strings and comments. | ||
| 1079 | Otherwise just call `backward-delete-char-untabify'. | 1082 | Otherwise just call `backward-delete-char-untabify'. |
| 1080 | Repeat ARG times." | 1083 | Repeat ARG times." |
| 1081 | (interactive "*p") | 1084 | (interactive "*p") |
| 1082 | (if (or (/= (current-indentation) (current-column)) | 1085 | (if (or (/= (current-indentation) (current-column)) |
| 1083 | (bolp) | 1086 | (bolp) |
| 1084 | (python-continuation-line-p)) | 1087 | (python-continuation-line-p) |
| 1088 | (python-in-string/comment)) | ||
| 1085 | (backward-delete-char-untabify arg) | 1089 | (backward-delete-char-untabify arg) |
| 1086 | ;; Look for the largest valid indentation which is smaller than | 1090 | ;; Look for the largest valid indentation which is smaller than |
| 1087 | ;; the current indentation. | 1091 | ;; the current indentation. |
| @@ -1182,6 +1186,10 @@ local value.") | |||
| 1182 | 1 2) | 1186 | 1 2) |
| 1183 | (,(rx " in file " (group (1+ not-newline)) " on line " | 1187 | (,(rx " in file " (group (1+ not-newline)) " on line " |
| 1184 | (group (1+ digit))) | 1188 | (group (1+ digit))) |
| 1189 | 1 2) | ||
| 1190 | ;; pdb stack trace | ||
| 1191 | (,(rx line-start "> " (group (1+ (not (any "(\"<")))) | ||
| 1192 | "(" (group (1+ digit)) ")" (1+ (not (any "("))) "()") | ||
| 1185 | 1 2)) | 1193 | 1 2)) |
| 1186 | "`compilation-error-regexp-alist' for inferior Python.") | 1194 | "`compilation-error-regexp-alist' for inferior Python.") |
| 1187 | 1195 | ||
| @@ -1191,7 +1199,7 @@ local value.") | |||
| 1191 | (define-key map "\C-c\C-l" 'python-load-file) | 1199 | (define-key map "\C-c\C-l" 'python-load-file) |
| 1192 | (define-key map "\C-c\C-v" 'python-check) | 1200 | (define-key map "\C-c\C-v" 'python-check) |
| 1193 | ;; Note that we _can_ still use these commands which send to the | 1201 | ;; Note that we _can_ still use these commands which send to the |
| 1194 | ;; Python process even at the prompt provided we have a normal prompt, | 1202 | ;; Python process even at the prompt iff we have a normal prompt, |
| 1195 | ;; i.e. '>>> ' and not '... '. See the comment before | 1203 | ;; i.e. '>>> ' and not '... '. See the comment before |
| 1196 | ;; python-send-region. Fixme: uncomment these if we address that. | 1204 | ;; python-send-region. Fixme: uncomment these if we address that. |
| 1197 | 1205 | ||
| @@ -1237,7 +1245,7 @@ For running multiple processes in multiple buffers, see `run-python' and | |||
| 1237 | ;; Still required by `comint-redirect-send-command', for instance | 1245 | ;; Still required by `comint-redirect-send-command', for instance |
| 1238 | ;; (and we need to match things like `>>> ... >>> '): | 1246 | ;; (and we need to match things like `>>> ... >>> '): |
| 1239 | (set (make-local-variable 'comint-prompt-regexp) | 1247 | (set (make-local-variable 'comint-prompt-regexp) |
| 1240 | (rx line-start (1+ (and (repeat 3 (any ">.")) " ")))) | 1248 | (rx line-start (1+ (and (or (repeat 3 (any ">.")) "(Pdb)") " ")))) |
| 1241 | (set (make-local-variable 'compilation-error-regexp-alist) | 1249 | (set (make-local-variable 'compilation-error-regexp-alist) |
| 1242 | python-compilation-regexp-alist) | 1250 | python-compilation-regexp-alist) |
| 1243 | (compilation-shell-minor-mode 1)) | 1251 | (compilation-shell-minor-mode 1)) |
| @@ -1729,47 +1737,57 @@ The criterion is either a match for `jython-mode' via | |||
| 1729 | (jython-mode))))))) | 1737 | (jython-mode))))))) |
| 1730 | 1738 | ||
| 1731 | (defun python-fill-paragraph (&optional justify) | 1739 | (defun python-fill-paragraph (&optional justify) |
| 1732 | "`fill-paragraph-function' handling comments and multi-line strings. | 1740 | "`fill-paragraph-function' handling multi-line strings and possibly comments. |
| 1733 | If any of the current line is a comment, fill the comment or the | 1741 | If any of the current line is in or at the end of a multi-line string, |
| 1734 | paragraph of it that point is in, preserving the comment's | 1742 | fill the string or the paragraph of it that point is in, preserving |
| 1735 | indentation and initial comment characters. Similarly if the end | 1743 | the strings's indentation." |
| 1736 | of the current line is in or at the end of a multi-line string. | ||
| 1737 | Otherwise, do nothing." | ||
| 1738 | (interactive "P") | 1744 | (interactive "P") |
| 1739 | (or (fill-comment-paragraph justify) | 1745 | (or (fill-comment-paragraph justify) |
| 1740 | ;; The `paragraph-start' and `paragraph-separate' variables | ||
| 1741 | ;; don't allow us to delimit the last paragraph in a multi-line | ||
| 1742 | ;; string properly, so narrow to the string and then fill around | ||
| 1743 | ;; (the end of) the current line. | ||
| 1744 | (save-excursion | 1746 | (save-excursion |
| 1745 | (end-of-line) | 1747 | (end-of-line) |
| 1746 | (let* ((syntax (syntax-ppss)) | 1748 | (let* ((syntax (syntax-ppss)) |
| 1747 | (orig (point)) | 1749 | (orig (point)) |
| 1748 | (start (nth 8 syntax)) | 1750 | start end) |
| 1749 | end) | 1751 | (cond ((nth 4 syntax) ; comment. fixme: loses with trailing one |
| 1750 | (cond ((eq t (nth 3 syntax)) ; in fenced string | 1752 | (let (fill-paragraph-function) |
| 1751 | (goto-char (nth 8 syntax)) ; string start | 1753 | (fill-paragraph justify))) |
| 1754 | ;; The `paragraph-start' and `paragraph-separate' | ||
| 1755 | ;; variables don't allow us to delimit the last | ||
| 1756 | ;; paragraph in a multi-line string properly, so narrow | ||
| 1757 | ;; to the string and then fill around (the end of) the | ||
| 1758 | ;; current line. | ||
| 1759 | ((eq t (nth 3 syntax)) ; in fenced string | ||
| 1760 | (goto-char (nth 8 syntax)) ; string start | ||
| 1761 | (setq start (line-beginning-position)) | ||
| 1752 | (setq end (condition-case () ; for unbalanced quotes | 1762 | (setq end (condition-case () ; for unbalanced quotes |
| 1753 | (progn (forward-sexp) (point)) | 1763 | (progn (forward-sexp) |
| 1764 | (- (point) 3)) | ||
| 1754 | (error (point-max))))) | 1765 | (error (point-max))))) |
| 1755 | ((re-search-backward "\\s|\\s-*\\=" nil t) ; end of fenced | 1766 | ((re-search-backward "\\s|\\s-*\\=" nil t) ; end of fenced string |
| 1756 | ; string | ||
| 1757 | (forward-char) | 1767 | (forward-char) |
| 1758 | (setq end (point)) | 1768 | (setq end (point)) |
| 1759 | (condition-case () | 1769 | (condition-case () |
| 1760 | (progn (backward-sexp) | 1770 | (progn (backward-sexp) |
| 1761 | (setq start (point))) | 1771 | (setq start (line-beginning-position))) |
| 1762 | (error (setq end nil))))) | 1772 | (error nil)))) |
| 1763 | (when end | 1773 | (when end |
| 1764 | (save-restriction | 1774 | (save-restriction |
| 1765 | (narrow-to-region start end) | 1775 | (narrow-to-region start end) |
| 1766 | (goto-char orig) | 1776 | (goto-char orig) |
| 1767 | (let ((paragraph-separate | 1777 | ;; Avoid losing leading and trailing newlines in doc |
| 1768 | ;; Make sure that fenced-string delimiters that stand | 1778 | ;; strings written like: |
| 1769 | ;; on their own line stay there. | 1779 | ;; """ |
| 1770 | (concat "[ \t]*['\"]+[ \t]*$\\|" paragraph-separate))) | 1780 | ;; ... |
| 1771 | (fill-paragraph justify)))))) | 1781 | ;; """ |
| 1772 | t)) | 1782 | (let* ((paragraph-separate |
| 1783 | (concat ".*\\s|\"\"$" ; newline after opening quotes | ||
| 1784 | "\\|\\(?:" paragraph-separate "\\)")) | ||
| 1785 | (paragraph-start | ||
| 1786 | (concat ".*\\s|\"\"[ \t]*[^ \t].*" ; not newline after | ||
| 1787 | ; opening quotes | ||
| 1788 | "\\|\\(?:" paragraph-separate "\\)")) | ||
| 1789 | (fill-paragraph-function)) | ||
| 1790 | (fill-paragraph justify))))))) t) | ||
| 1773 | 1791 | ||
| 1774 | (defun python-shift-left (start end &optional count) | 1792 | (defun python-shift-left (start end &optional count) |
| 1775 | "Shift lines in region COUNT (the prefix arg) columns to the left. | 1793 | "Shift lines in region COUNT (the prefix arg) columns to the left. |
| @@ -1866,9 +1884,12 @@ Uses `python-beginning-of-block', `python-end-of-block'." | |||
| 1866 | (goto-char (point-min)) | 1884 | (goto-char (point-min)) |
| 1867 | (while (re-search-forward "^import\\>\\|^from\\>" nil t) | 1885 | (while (re-search-forward "^import\\>\\|^from\\>" nil t) |
| 1868 | (unless (syntax-ppss-context (syntax-ppss)) | 1886 | (unless (syntax-ppss-context (syntax-ppss)) |
| 1869 | (push (buffer-substring (line-beginning-position) | 1887 | (let ((start (line-beginning-position))) |
| 1870 | (line-beginning-position 2)) | 1888 | ;; Skip over continued lines. |
| 1871 | lines))) | 1889 | (while (and (eq ?\\ (char-before (line-end-position))) |
| 1890 | (= 0 (forward-line 1)))) | ||
| 1891 | (push (buffer-substring start (line-beginning-position 2)) | ||
| 1892 | lines)))) | ||
| 1872 | (setq python-imports | 1893 | (setq python-imports |
| 1873 | (if lines | 1894 | (if lines |
| 1874 | (apply #'concat | 1895 | (apply #'concat |
| @@ -2259,7 +2280,7 @@ with skeleton expansions for compound statement templates. | |||
| 2259 | ;; since it isn't (can't be) indentation-based. Also hide-level | 2280 | ;; since it isn't (can't be) indentation-based. Also hide-level |
| 2260 | ;; doesn't seem to work properly. | 2281 | ;; doesn't seem to work properly. |
| 2261 | (add-to-list 'hs-special-modes-alist | 2282 | (add-to-list 'hs-special-modes-alist |
| 2262 | `(python-mode "^\\s-*def\\>" nil "#" | 2283 | `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#" |
| 2263 | ,(lambda (arg) | 2284 | ,(lambda (arg) |
| 2264 | (python-end-of-defun) | 2285 | (python-end-of-defun) |
| 2265 | (skip-chars-backward " \t\n")) | 2286 | (skip-chars-backward " \t\n")) |