diff options
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 592 |
1 files changed, 355 insertions, 237 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 11662c8e46a..9057e51e439 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -62,6 +62,8 @@ | |||
| 62 | 62 | ||
| 63 | ;; TODO: See various Fixmes below. | 63 | ;; TODO: See various Fixmes below. |
| 64 | 64 | ||
| 65 | ;; Fixme: This doesn't support (the nascent) Python 3 . | ||
| 66 | |||
| 65 | ;;; Code: | 67 | ;;; Code: |
| 66 | 68 | ||
| 67 | (require 'comint) | 69 | (require 'comint) |
| @@ -70,6 +72,7 @@ | |||
| 70 | (require 'compile) | 72 | (require 'compile) |
| 71 | (require 'hippie-exp)) | 73 | (require 'hippie-exp)) |
| 72 | 74 | ||
| 75 | (require 'sym-comp) | ||
| 73 | (autoload 'comint-mode "comint") | 76 | (autoload 'comint-mode "comint") |
| 74 | 77 | ||
| 75 | (defgroup python nil | 78 | (defgroup python nil |
| @@ -84,6 +87,7 @@ | |||
| 84 | (add-to-list 'interpreter-mode-alist '("python" . python-mode)) | 87 | (add-to-list 'interpreter-mode-alist '("python" . python-mode)) |
| 85 | ;;;###autoload | 88 | ;;;###autoload |
| 86 | (add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode)) | 89 | (add-to-list 'auto-mode-alist '("\\.py\\'" . python-mode)) |
| 90 | (add-to-list 'same-window-buffer-names "*Python*") | ||
| 87 | 91 | ||
| 88 | ;;;; Font lock | 92 | ;;;; Font lock |
| 89 | 93 | ||
| @@ -98,7 +102,7 @@ | |||
| 98 | ;; Not real keywords, but close enough to be fontified as such | 102 | ;; Not real keywords, but close enough to be fontified as such |
| 99 | "self" "True" "False") | 103 | "self" "True" "False") |
| 100 | symbol-end) | 104 | symbol-end) |
| 101 | (,(rx symbol-start "None" symbol-end) ; See § Keywords in 2.5 manual. | 105 | (,(rx symbol-start "None" symbol-end) ; see § Keywords in 2.5 manual |
| 102 | . font-lock-constant-face) | 106 | . font-lock-constant-face) |
| 103 | ;; Definitions | 107 | ;; Definitions |
| 104 | (,(rx symbol-start (group "class") (1+ space) (group (1+ (or word ?_)))) | 108 | (,(rx symbol-start (group "class") (1+ space) (group (1+ (or word ?_)))) |
| @@ -108,15 +112,63 @@ | |||
| 108 | ;; Top-level assignments are worth highlighting. | 112 | ;; Top-level assignments are worth highlighting. |
| 109 | (,(rx line-start (group (1+ (or word ?_))) (0+ space) "=") | 113 | (,(rx line-start (group (1+ (or word ?_))) (0+ space) "=") |
| 110 | (1 font-lock-variable-name-face)) | 114 | (1 font-lock-variable-name-face)) |
| 111 | (,(rx "@" (1+ (or word ?_))) ; decorators | 115 | (,(rx line-start (* (any " \t")) (group "@" (1+ (or word ?_)))) ; decorators |
| 112 | (0 font-lock-preprocessor-face)))) | 116 | (1 font-lock-type-face)) |
| 117 | ;; Built-ins. (The next three blocks are from | ||
| 118 | ;; `__builtin__.__dict__.keys()' in Python 2.5.1.) These patterns | ||
| 119 | ;; are debateable, but they at least help to spot possible | ||
| 120 | ;; shadowing of builtins. | ||
| 121 | (,(rx symbol-start (or | ||
| 122 | ;; exceptions | ||
| 123 | "ArithmeticError" "AssertionError" "AttributeError" | ||
| 124 | "BaseException" "DeprecationWarning" "EOFError" | ||
| 125 | "EnvironmentError" "Exception" "FloatingPointError" | ||
| 126 | "FutureWarning" "GeneratorExit" "IOError" "ImportError" | ||
| 127 | "ImportWarning" "IndentationError" "IndexError" "KeyError" | ||
| 128 | "KeyboardInterrupt" "LookupError" "MemoryError" "NameError" | ||
| 129 | "NotImplemented" "NotImplementedError" "OSError" | ||
| 130 | "OverflowError" "PendingDeprecationWarning" "ReferenceError" | ||
| 131 | "RuntimeError" "RuntimeWarning" "StandardError" | ||
| 132 | "StopIteration" "SyntaxError" "SyntaxWarning" "SystemError" | ||
| 133 | "SystemExit" "TabError" "TypeError" "UnboundLocalError" | ||
| 134 | "UnicodeDecodeError" "UnicodeEncodeError" "UnicodeError" | ||
| 135 | "UnicodeTranslateError" "UnicodeWarning" "UserWarning" | ||
| 136 | "ValueError" "Warning" "ZeroDivisionError") symbol-end) | ||
| 137 | . font-lock-type-face) | ||
| 138 | (,(rx (or line-start (not (any ". \t"))) (* (any " \t")) symbol-start | ||
| 139 | (group (or | ||
| 140 | ;; callable built-ins, fontified when not appearing as | ||
| 141 | ;; object attributes | ||
| 142 | "abs" "all" "any" "apply" "basestring" "bool" "buffer" "callable" | ||
| 143 | "chr" "classmethod" "cmp" "coerce" "compile" "complex" | ||
| 144 | "copyright" "credits" "delattr" "dict" "dir" "divmod" | ||
| 145 | "enumerate" "eval" "execfile" "exit" "file" "filter" "float" | ||
| 146 | "frozenset" "getattr" "globals" "hasattr" "hash" "help" | ||
| 147 | "hex" "id" "input" "int" "intern" "isinstance" "issubclass" | ||
| 148 | "iter" "len" "license" "list" "locals" "long" "map" "max" | ||
| 149 | "min" "object" "oct" "open" "ord" "pow" "property" "quit" | ||
| 150 | "range" "raw_input" "reduce" "reload" "repr" "reversed" | ||
| 151 | "round" "set" "setattr" "slice" "sorted" "staticmethod" | ||
| 152 | "str" "sum" "super" "tuple" "type" "unichr" "unicode" "vars" | ||
| 153 | "xrange" "zip")) symbol-end) | ||
| 154 | (1 font-lock-builtin-face)) | ||
| 155 | (,(rx symbol-start (or | ||
| 156 | ;; other built-ins | ||
| 157 | "True" "False" "None" "Ellipsis" | ||
| 158 | "_" "__debug__" "__doc__" "__import__" "__name__") symbol-end) | ||
| 159 | . font-lock-builtin-face))) | ||
| 113 | 160 | ||
| 114 | (defconst python-font-lock-syntactic-keywords | 161 | (defconst python-font-lock-syntactic-keywords |
| 115 | ;; Make outer chars of matching triple-quote sequences into generic | 162 | ;; Make outer chars of matching triple-quote sequences into generic |
| 116 | ;; string delimiters. Fixme: Is there a better way? | 163 | ;; string delimiters. Fixme: Is there a better way? |
| 117 | `((,(rx (or line-start buffer-start | 164 | ;; First avoid a sequence preceded by an odd number of backslashes. |
| 118 | (not (syntax escape))) ; avoid escaped leading quote | 165 | `((,(rx (not (any ?\\)) |
| 119 | (group (optional (any "uUrR"))) ; prefix gets syntax property | 166 | ?\\ (* (and ?\\ ?\\)) |
| 167 | (group (syntax string-quote)) | ||
| 168 | (backref 1) | ||
| 169 | (group (backref 1))) | ||
| 170 | (2 ,(string-to-syntax "\""))) ; dummy | ||
| 171 | (,(rx (group (optional (any "uUrR"))) ; prefix gets syntax property | ||
| 120 | (optional (any "rR")) ; possible second prefix | 172 | (optional (any "rR")) ; possible second prefix |
| 121 | (group (syntax string-quote)) ; maybe gets property | 173 | (group (syntax string-quote)) ; maybe gets property |
| 122 | (backref 2) ; per first quote | 174 | (backref 2) ; per first quote |
| @@ -144,8 +196,6 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)." | |||
| 144 | ;; x = ''' """ ' a | 196 | ;; x = ''' """ ' a |
| 145 | ;; ''' | 197 | ;; ''' |
| 146 | ;; x '"""' x """ \"""" x | 198 | ;; x '"""' x """ \"""" x |
| 147 | ;; Fixme: """""" goes wrong (due to syntax-ppss not getting the string | ||
| 148 | ;; fence context). | ||
| 149 | (save-excursion | 199 | (save-excursion |
| 150 | (goto-char (match-beginning 0)) | 200 | (goto-char (match-beginning 0)) |
| 151 | (cond | 201 | (cond |
| @@ -165,8 +215,8 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)." | |||
| 165 | (and (= n 1) ; prefix | 215 | (and (= n 1) ; prefix |
| 166 | (/= (match-beginning 1) (match-end 1)))) ; non-empty | 216 | (/= (match-beginning 1) (match-end 1)))) ; non-empty |
| 167 | (let ((font-lock-syntactic-keywords nil)) | 217 | (let ((font-lock-syntactic-keywords nil)) |
| 168 | (unless (nth 3 (syntax-ppss)) | 218 | (unless (eq 'string (syntax-ppss-context (syntax-ppss))) |
| 169 | (eval-when-compile (string-to-syntax "|"))))) | 219 | (eval-when-compile (string-to-syntax "|"))))) |
| 170 | ;; Otherwise (we're in a non-matching string) the property is | 220 | ;; Otherwise (we're in a non-matching string) the property is |
| 171 | ;; nil, which is OK. | 221 | ;; nil, which is OK. |
| 172 | ))) | 222 | ))) |
| @@ -217,7 +267,7 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)." | |||
| 217 | (define-key map "\C-c\C-z" 'python-switch-to-python) | 267 | (define-key map "\C-c\C-z" 'python-switch-to-python) |
| 218 | (define-key map "\C-c\C-m" 'python-load-file) | 268 | (define-key map "\C-c\C-m" 'python-load-file) |
| 219 | (define-key map "\C-c\C-l" 'python-load-file) ; a la cmuscheme | 269 | (define-key map "\C-c\C-l" 'python-load-file) ; a la cmuscheme |
| 220 | (substitute-key-definition 'complete-symbol 'python-complete-symbol | 270 | (substitute-key-definition 'complete-symbol 'symbol-complete |
| 221 | map global-map) | 271 | map global-map) |
| 222 | (define-key map "\C-c\C-i" 'python-find-imports) | 272 | (define-key map "\C-c\C-i" 'python-find-imports) |
| 223 | (define-key map "\C-c\C-t" 'python-expand-template) | 273 | (define-key map "\C-c\C-t" 'python-expand-template) |
| @@ -270,8 +320,10 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)." | |||
| 270 | "-" | 320 | "-" |
| 271 | ["Help on symbol" python-describe-symbol | 321 | ["Help on symbol" python-describe-symbol |
| 272 | :help "Use pydoc on symbol at point"] | 322 | :help "Use pydoc on symbol at point"] |
| 273 | ["Complete symbol" python-complete-symbol | 323 | ["Complete symbol" symbol-complete |
| 274 | :help "Complete (qualified) symbol before point"] | 324 | :help "Complete (qualified) symbol before point"] |
| 325 | ["Find function" python-find-function | ||
| 326 | :help "Try to find source definition of function at point"] | ||
| 275 | ["Update imports" python-find-imports | 327 | ["Update imports" python-find-imports |
| 276 | :help "Update list of top-level imports for completion"])) | 328 | :help "Update list of top-level imports for completion"])) |
| 277 | map)) | 329 | map)) |
| @@ -630,39 +682,38 @@ Set `python-indent' locally to the value guessed." | |||
| 630 | ((looking-at (rx (0+ space) (syntax comment-start) | 682 | ((looking-at (rx (0+ space) (syntax comment-start) |
| 631 | (not (any " \t\n")))) ; non-indentable comment | 683 | (not (any " \t\n")))) ; non-indentable comment |
| 632 | (current-indentation)) | 684 | (current-indentation)) |
| 633 | (t (if python-honour-comment-indentation | 685 | ((and python-honour-comment-indentation |
| 634 | ;; Back over whitespace, newlines, non-indentable comments. | 686 | ;; Back over whitespace, newlines, non-indentable comments. |
| 635 | (catch 'done | 687 | (catch 'done |
| 636 | (while t | 688 | (while (cond ((bobp) nil) |
| 637 | (if (cond ((bobp)) | 689 | ((not (forward-comment -1)) |
| 638 | ;; not at comment start | 690 | nil) ; not at comment start |
| 639 | ((not (forward-comment -1)) | 691 | ;; Now at start of comment -- trailing one? |
| 640 | (python-beginning-of-statement) | 692 | ((/= (current-column) (current-indentation)) |
| 641 | t) | 693 | nil) |
| 642 | ;; trailing comment | 694 | ;; Indentable comment, like python-mode.el? |
| 643 | ((/= (current-column) (current-indentation)) | 695 | ((and (looking-at (rx (syntax comment-start) |
| 644 | (python-beginning-of-statement) | 696 | (or space line-end))) |
| 645 | t) | 697 | (/= 0 (current-column))) |
| 646 | ;; indentable comment like python-mode.el | 698 | (throw 'done (current-column))) |
| 647 | ((and (looking-at (rx (syntax comment-start) | 699 | ;; Else skip it (loop). |
| 648 | (or space line-end))) | 700 | (t)))))) |
| 649 | (/= 0 (current-column))))) | 701 | (t |
| 650 | (throw 'done t))))) | 702 | (python-indentation-levels) |
| 651 | (python-indentation-levels) | 703 | ;; Prefer to indent comments with an immediately-following |
| 652 | ;; Prefer to indent comments with an immediately-following | 704 | ;; statement, e.g. |
| 653 | ;; statement, e.g. | 705 | ;; ... |
| 654 | ;; ... | 706 | ;; # ... |
| 655 | ;; # ... | 707 | ;; def ... |
| 656 | ;; def ... | 708 | (when (and (> python-indent-list-length 1) |
| 657 | (when (and (> python-indent-list-length 1) | 709 | (python-comment-line-p)) |
| 658 | (python-comment-line-p)) | 710 | (forward-line) |
| 659 | (forward-line) | 711 | (unless (python-comment-line-p) |
| 660 | (unless (python-comment-line-p) | 712 | (let ((elt (assq (current-indentation) python-indent-list))) |
| 661 | (let ((elt (assq (current-indentation) python-indent-list))) | 713 | (setq python-indent-list |
| 662 | (setq python-indent-list | 714 | (nconc (delete elt python-indent-list) |
| 663 | (nconc (delete elt python-indent-list) | 715 | (list elt)))))) |
| 664 | (list elt)))))) | 716 | (caar (last python-indent-list))))))) |
| 665 | (caar (last python-indent-list))))))) | ||
| 666 | 717 | ||
| 667 | ;;;; Cycling through the possible indentations with successive TABs. | 718 | ;;;; Cycling through the possible indentations with successive TABs. |
| 668 | 719 | ||
| @@ -855,11 +906,12 @@ reached start of buffer." | |||
| 855 | ;; Not sure why it was like this -- fails in case of | 906 | ;; Not sure why it was like this -- fails in case of |
| 856 | ;; last internal function followed by first | 907 | ;; last internal function followed by first |
| 857 | ;; non-def statement of the main body. | 908 | ;; non-def statement of the main body. |
| 858 | ;;(and def-line (= in ci)) | 909 | ;; (and def-line (= in ci)) |
| 859 | (= in ci) | 910 | (= in ci) |
| 860 | (< in ci))) | 911 | (< in ci))) |
| 861 | (not (python-in-string/comment))) | 912 | (not (python-in-string/comment))) |
| 862 | (setq found t))))) | 913 | (setq found t))) |
| 914 | found)) | ||
| 863 | 915 | ||
| 864 | (defun python-end-of-defun () | 916 | (defun python-end-of-defun () |
| 865 | "`end-of-defun-function' for Python. | 917 | "`end-of-defun-function' for Python. |
| @@ -913,15 +965,17 @@ Accounts for continuation lines, multi-line strings, and | |||
| 913 | multi-line bracketed expressions." | 965 | multi-line bracketed expressions." |
| 914 | (beginning-of-line) | 966 | (beginning-of-line) |
| 915 | (python-beginning-of-string) | 967 | (python-beginning-of-string) |
| 916 | (while (python-continuation-line-p) | 968 | (let ((point (point))) |
| 917 | (beginning-of-line) | 969 | (while (and (python-continuation-line-p) |
| 918 | (if (python-backslash-continuation-line-p) | 970 | (> point (setq point (point)))) |
| 919 | (progn | 971 | (beginning-of-line) |
| 920 | (forward-line -1) | 972 | (if (python-backslash-continuation-line-p) |
| 921 | (while (python-backslash-continuation-line-p) | 973 | (progn |
| 922 | (forward-line -1))) | 974 | (forward-line -1) |
| 923 | (python-beginning-of-string) | 975 | (while (python-backslash-continuation-line-p) |
| 924 | (python-skip-out))) | 976 | (forward-line -1))) |
| 977 | (python-beginning-of-string) | ||
| 978 | (python-skip-out)))) | ||
| 925 | (back-to-indentation)) | 979 | (back-to-indentation)) |
| 926 | 980 | ||
| 927 | (defun python-skip-out (&optional forward syntax) | 981 | (defun python-skip-out (&optional forward syntax) |
| @@ -999,11 +1053,14 @@ Return count of statements left to move." | |||
| 999 | (if (< count 0) | 1053 | (if (< count 0) |
| 1000 | (python-previous-statement (- count)) | 1054 | (python-previous-statement (- count)) |
| 1001 | (beginning-of-line) | 1055 | (beginning-of-line) |
| 1002 | (while (and (> count 0) (not (eobp))) | 1056 | (let (bogus) |
| 1003 | (python-end-of-statement) | 1057 | (while (and (> count 0) (not (eobp)) (not bogus)) |
| 1004 | (python-skip-comments/blanks) | 1058 | (python-end-of-statement) |
| 1005 | (unless (eobp) | 1059 | (python-skip-comments/blanks) |
| 1006 | (setq count (1- count)))) | 1060 | (if (eq 'string (syntax-ppss-context (syntax-ppss))) |
| 1061 | (setq bogus t) | ||
| 1062 | (unless (eobp) | ||
| 1063 | (setq count (1- count)))))) | ||
| 1007 | count)) | 1064 | count)) |
| 1008 | 1065 | ||
| 1009 | (defun python-beginning-of-block (&optional arg) | 1066 | (defun python-beginning-of-block (&optional arg) |
| @@ -1066,7 +1123,7 @@ don't move and return nil. Otherwise return t." | |||
| 1066 | (if (and (zerop ci) (not open)) | 1123 | (if (and (zerop ci) (not open)) |
| 1067 | (not (goto-char point)) | 1124 | (not (goto-char point)) |
| 1068 | (catch 'done | 1125 | (catch 'done |
| 1069 | (while (zerop (python-next-statement)) | 1126 | (while (zerop (python-next-statement)) |
| 1070 | (when (or (and open (<= (current-indentation) ci)) | 1127 | (when (or (and open (<= (current-indentation) ci)) |
| 1071 | (< (current-indentation) ci)) | 1128 | (< (current-indentation) ci)) |
| 1072 | (python-skip-comments/blanks t) | 1129 | (python-skip-comments/blanks t) |
| @@ -1083,9 +1140,21 @@ don't move and return nil. Otherwise return t." | |||
| 1083 | (set-text-properties 0 (length function-name) nil function-name) | 1140 | (set-text-properties 0 (length function-name) nil function-name) |
| 1084 | function-name)) | 1141 | function-name)) |
| 1085 | 1142 | ||
| 1086 | 1143 | ||
| 1087 | ;;;; Imenu. | 1144 | ;;;; Imenu. |
| 1088 | 1145 | ||
| 1146 | ;; For possibily speeding this up, here's the top of the ELP profile | ||
| 1147 | ;; for rescanning pydoc.py (2.2k lines, 90kb): | ||
| 1148 | ;; Function Name Call Count Elapsed Time Average Time | ||
| 1149 | ;; ==================================== ========== ============= ============ | ||
| 1150 | ;; python-imenu-create-index 156 2.430906 0.0155827307 | ||
| 1151 | ;; python-end-of-defun 155 1.2718260000 0.0082053290 | ||
| 1152 | ;; python-end-of-block 155 1.1898689999 0.0076765741 | ||
| 1153 | ;; python-next-statement 2970 1.024717 0.0003450225 | ||
| 1154 | ;; python-end-of-statement 2970 0.4332190000 0.0001458649 | ||
| 1155 | ;; python-beginning-of-defun 265 0.0918479999 0.0003465962 | ||
| 1156 | ;; python-skip-comments/blanks 3125 0.0753319999 2.410...e-05 | ||
| 1157 | |||
| 1089 | (defvar python-recursing) | 1158 | (defvar python-recursing) |
| 1090 | (defun python-imenu-create-index () | 1159 | (defun python-imenu-create-index () |
| 1091 | "`imenu-create-index-function' for Python. | 1160 | "`imenu-create-index-function' for Python. |
| @@ -1361,11 +1430,16 @@ Don't save anything for STR matching `inferior-python-filter-regexp'." | |||
| 1361 | (defvar python-preoutput-result nil | 1430 | (defvar python-preoutput-result nil |
| 1362 | "Data from last `_emacs_out' line seen by the preoutput filter.") | 1431 | "Data from last `_emacs_out' line seen by the preoutput filter.") |
| 1363 | 1432 | ||
| 1433 | (defvar python-preoutput-continuation nil | ||
| 1434 | "If non-nil, funcall this when `python-preoutput-filter' sees `_emacs_ok'.") | ||
| 1435 | |||
| 1364 | (defvar python-preoutput-leftover nil) | 1436 | (defvar python-preoutput-leftover nil) |
| 1365 | (defvar python-preoutput-skip-next-prompt nil) | 1437 | (defvar python-preoutput-skip-next-prompt nil) |
| 1366 | 1438 | ||
| 1367 | ;; Using this stops us getting lines in the buffer like | 1439 | ;; Using this stops us getting lines in the buffer like |
| 1368 | ;; >>> ... ... >>> | 1440 | ;; >>> ... ... >>> |
| 1441 | ;; Also look for (and delete) an `_emacs_ok' string and call | ||
| 1442 | ;; `python-preoutput-continuation' if we get it. | ||
| 1369 | (defun python-preoutput-filter (s) | 1443 | (defun python-preoutput-filter (s) |
| 1370 | "`comint-preoutput-filter-functions' function: ignore prompts not at bol." | 1444 | "`comint-preoutput-filter-functions' function: ignore prompts not at bol." |
| 1371 | (when python-preoutput-leftover | 1445 | (when python-preoutput-leftover |
| @@ -1415,6 +1489,23 @@ Don't save anything for STR matching `inferior-python-filter-regexp'." | |||
| 1415 | 1489 | ||
| 1416 | (autoload 'comint-check-proc "comint") | 1490 | (autoload 'comint-check-proc "comint") |
| 1417 | 1491 | ||
| 1492 | (defvar python-version-checked nil) | ||
| 1493 | (defun python-check-version (cmd) | ||
| 1494 | "Check that CMD runs a suitable version of Python." | ||
| 1495 | ;; Fixme: Check on Jython. | ||
| 1496 | (unless (or python-version-checked | ||
| 1497 | (equal 0 (string-match (regexp-quote python-python-command) | ||
| 1498 | cmd))) | ||
| 1499 | (unless (shell-command-to-string cmd) | ||
| 1500 | (error "Can't run Python command `%s'" cmd)) | ||
| 1501 | (let* ((res (shell-command-to-string (concat cmd " --version")))) | ||
| 1502 | (string-match "Python \\([0-9]\\)\\.\\([0-9]\\)" res) | ||
| 1503 | (unless (and (equal "2" (match-string 1 res)) | ||
| 1504 | (match-beginning 2) | ||
| 1505 | (>= (string-to-number (match-string 2 res)) 2)) | ||
| 1506 | (error "Only Python versions >= 2.2 and < 3.0 supported"))) | ||
| 1507 | (setq python-version-checked t))) | ||
| 1508 | |||
| 1418 | ;;;###autoload | 1509 | ;;;###autoload |
| 1419 | (defun run-python (&optional cmd noshow new) | 1510 | (defun run-python (&optional cmd noshow new) |
| 1420 | "Run an inferior Python process, input and output via buffer *Python*. | 1511 | "Run an inferior Python process, input and output via buffer *Python*. |
| @@ -1435,22 +1526,26 @@ buffer for a list of commands.)" | |||
| 1435 | (interactive (if current-prefix-arg | 1526 | (interactive (if current-prefix-arg |
| 1436 | (list (read-string "Run Python: " python-command) nil t) | 1527 | (list (read-string "Run Python: " python-command) nil t) |
| 1437 | (list python-command))) | 1528 | (list python-command))) |
| 1438 | (unless cmd (setq cmd python-python-command)) | 1529 | (unless cmd (setq cmd python-command)) |
| 1530 | (python-check-version cmd) | ||
| 1439 | (setq python-command cmd) | 1531 | (setq python-command cmd) |
| 1440 | ;; Fixme: Consider making `python-buffer' buffer-local as a buffer | 1532 | ;; Fixme: Consider making `python-buffer' buffer-local as a buffer |
| 1441 | ;; (not a name) in Python buffers from which `run-python' &c is | 1533 | ;; (not a name) in Python buffers from which `run-python' &c is |
| 1442 | ;; invoked. Would support multiple processes better. | 1534 | ;; invoked. Would support multiple processes better. |
| 1443 | (when (or new (not (comint-check-proc python-buffer))) | 1535 | (when (or new (not (comint-check-proc python-buffer))) |
| 1444 | (with-current-buffer | 1536 | (with-current-buffer |
| 1445 | (let* ((cmdlist (append (python-args-to-list cmd) '("-i"))) | 1537 | (let* ((cmdlist (append (python-args-to-list cmd) '("-i"))) |
| 1446 | (path (getenv "PYTHONPATH")) | 1538 | (path (getenv "PYTHONPATH")) |
| 1447 | (process-environment ; to import emacs.py | 1539 | (process-environment ; to import emacs.py |
| 1448 | (cons (concat "PYTHONPATH=" data-directory | 1540 | (cons (concat "PYTHONPATH=" |
| 1449 | (if path (concat path-separator path))) | 1541 | (if path (concat path path-separator)) |
| 1450 | process-environment))) | 1542 | data-directory) |
| 1451 | (apply 'make-comint-in-buffer "Python" | 1543 | process-environment)) |
| 1452 | (if new (generate-new-buffer "*Python*") "*Python*") | 1544 | ;; Suppress use of pager for help output: |
| 1453 | (car cmdlist) nil (cdr cmdlist))) | 1545 | (process-connection-type nil)) |
| 1546 | (apply 'make-comint-in-buffer "Python" | ||
| 1547 | (generate-new-buffer "*Python*") | ||
| 1548 | (car cmdlist) nil (cdr cmdlist))) | ||
| 1454 | (setq-default python-buffer (current-buffer)) | 1549 | (setq-default python-buffer (current-buffer)) |
| 1455 | (setq python-buffer (current-buffer)) | 1550 | (setq python-buffer (current-buffer)) |
| 1456 | (accept-process-output (get-buffer-process python-buffer) 5) | 1551 | (accept-process-output (get-buffer-process python-buffer) 5) |
| @@ -1462,7 +1557,13 @@ buffer for a list of commands.)" | |||
| 1462 | ;; seems worth putting in a separate file, and it's probably cleaner | 1557 | ;; seems worth putting in a separate file, and it's probably cleaner |
| 1463 | ;; to put it in a module. | 1558 | ;; to put it in a module. |
| 1464 | ;; Ensure we're at a prompt before doing anything else. | 1559 | ;; Ensure we're at a prompt before doing anything else. |
| 1465 | (python-send-string "import emacs"))) | 1560 | (python-send-string "import emacs") |
| 1561 | ;; The following line was meant to ensure that we're at a prompt | ||
| 1562 | ;; before doing anything else. However, this can cause Emacs to | ||
| 1563 | ;; hang waiting for a response, if that Python function fails | ||
| 1564 | ;; (i.e. raises an exception). | ||
| 1565 | ;; (python-send-receive "print '_emacs_out ()'") | ||
| 1566 | )) | ||
| 1466 | (if (derived-mode-p 'python-mode) | 1567 | (if (derived-mode-p 'python-mode) |
| 1467 | (setq python-buffer (default-value 'python-buffer))) ; buffer-local | 1568 | (setq python-buffer (default-value 'python-buffer))) ; buffer-local |
| 1468 | ;; Without this, help output goes into the inferior python buffer if | 1569 | ;; Without this, help output goes into the inferior python buffer if |
| @@ -1470,30 +1571,14 @@ buffer for a list of commands.)" | |||
| 1470 | (sit-for 1 t) ;Should we use accept-process-output instead? --Stef | 1571 | (sit-for 1 t) ;Should we use accept-process-output instead? --Stef |
| 1471 | (unless noshow (pop-to-buffer python-buffer t))) | 1572 | (unless noshow (pop-to-buffer python-buffer t))) |
| 1472 | 1573 | ||
| 1473 | ;; Fixme: We typically lose if the inferior isn't in the normal REPL, | ||
| 1474 | ;; e.g. prompt is `help> '. Probably raise an error if the form of | ||
| 1475 | ;; the prompt is unexpected. Actually, it needs to be `>>> ', not | ||
| 1476 | ;; `... ', i.e. we're not inputting a block &c. However, this may not | ||
| 1477 | ;; be the place to check it, e.g. we might actually want to send | ||
| 1478 | ;; commands having set up such a state. | ||
| 1479 | |||
| 1480 | (defun python-send-command (command) | 1574 | (defun python-send-command (command) |
| 1481 | "Like `python-send-string' but resets `compilation-shell-minor-mode'. | 1575 | "Like `python-send-string' but resets `compilation-shell-minor-mode'." |
| 1482 | COMMAND should be a single statement." | 1576 | (when (python-check-comint-prompt) |
| 1483 | ;; (assert (not (string-match "\n" command))) | 1577 | (with-current-buffer (process-buffer (python-proc)) |
| 1484 | ;; (let ((end (marker-position (process-mark (python-proc))))) | 1578 | (goto-char (point-max)) |
| 1485 | (with-current-buffer (process-buffer (python-proc)) | 1579 | (compilation-forget-errors) |
| 1486 | (goto-char (point-max)) | 1580 | (python-send-string command) |
| 1487 | (compilation-forget-errors) | 1581 | (setq compilation-last-buffer (current-buffer))))) |
| 1488 | (python-send-string command) | ||
| 1489 | (setq compilation-last-buffer (current-buffer))) | ||
| 1490 | ;; No idea what this is for but it breaks the call to | ||
| 1491 | ;; compilation-fake-loc in python-send-region. -- Stef | ||
| 1492 | ;; Must wait until this has completed before re-setting variables below. | ||
| 1493 | ;; (python-send-receive "print '_emacs_out ()'") | ||
| 1494 | ;; (with-current-buffer python-buffer | ||
| 1495 | ;; (set-marker compilation-parsing-end end)) | ||
| 1496 | ) ;;) | ||
| 1497 | 1582 | ||
| 1498 | (defun python-send-region (start end) | 1583 | (defun python-send-region (start end) |
| 1499 | "Send the region to the inferior Python process." | 1584 | "Send the region to the inferior Python process." |
| @@ -1617,8 +1702,8 @@ See variable `python-buffer'. Starts a new process if necessary." | |||
| 1617 | (unless (comint-check-proc python-buffer) | 1702 | (unless (comint-check-proc python-buffer) |
| 1618 | (run-python nil t)) | 1703 | (run-python nil t)) |
| 1619 | (get-buffer-process (if (derived-mode-p 'inferior-python-mode) | 1704 | (get-buffer-process (if (derived-mode-p 'inferior-python-mode) |
| 1620 | (current-buffer) | 1705 | (current-buffer) |
| 1621 | python-buffer))) | 1706 | python-buffer))) |
| 1622 | 1707 | ||
| 1623 | (defun python-set-proc () | 1708 | (defun python-set-proc () |
| 1624 | "Set the default value of `python-buffer' to correspond to this buffer. | 1709 | "Set the default value of `python-buffer' to correspond to this buffer. |
| @@ -1693,16 +1778,27 @@ will." | |||
| 1693 | 1778 | ||
| 1694 | (defun python-send-receive (string) | 1779 | (defun python-send-receive (string) |
| 1695 | "Send STRING to inferior Python (if any) and return result. | 1780 | "Send STRING to inferior Python (if any) and return result. |
| 1696 | The result is what follows `_emacs_out' in the output." | 1781 | The result is what follows `_emacs_out' in the output. |
| 1782 | This is a no-op if `python-check-comint-prompt' returns nil." | ||
| 1697 | (python-send-string string) | 1783 | (python-send-string string) |
| 1698 | (let ((proc (python-proc))) | 1784 | (let ((proc (python-proc))) |
| 1699 | (with-current-buffer (process-buffer proc) | 1785 | (with-current-buffer (process-buffer proc) |
| 1700 | (set (make-local-variable 'python-preoutput-result) nil) | 1786 | (when (python-check-comint-prompt proc) |
| 1701 | (while (progn | 1787 | (set (make-local-variable 'python-preoutput-result) nil) |
| 1702 | (accept-process-output proc 5) | 1788 | (while (progn |
| 1703 | (null python-preoutput-result))) | 1789 | (accept-process-output proc 5) |
| 1704 | (prog1 python-preoutput-result | 1790 | (null python-preoutput-result))) |
| 1705 | (kill-local-variable 'python-preoutput-result))))) | 1791 | (prog1 python-preoutput-result |
| 1792 | (kill-local-variable 'python-preoutput-result)))))) | ||
| 1793 | |||
| 1794 | (defun python-check-comint-prompt (&optional proc) | ||
| 1795 | "Return non-nil iff there's a normal prompt in the inferior buffer. | ||
| 1796 | If there isn't, it's probably not appropriate to send input to return | ||
| 1797 | Eldoc information etc. If PROC is non-nil, check the buffer for that | ||
| 1798 | process." | ||
| 1799 | (with-current-buffer (process-buffer (or proc (python-proc))) | ||
| 1800 | (save-excursion | ||
| 1801 | (save-match-data (re-search-backward ">>> \\=" nil t))))) | ||
| 1706 | 1802 | ||
| 1707 | ;; Fixme: Is there anything reasonable we can do with random methods? | 1803 | ;; Fixme: Is there anything reasonable we can do with random methods? |
| 1708 | ;; (Currently only works with functions.) | 1804 | ;; (Currently only works with functions.) |
| @@ -1716,22 +1812,22 @@ instance. Assumes an inferior Python is running." | |||
| 1716 | (with-local-quit | 1812 | (with-local-quit |
| 1717 | ;; First try the symbol we're on. | 1813 | ;; First try the symbol we're on. |
| 1718 | (or (and symbol | 1814 | (or (and symbol |
| 1719 | (python-send-receive (format "emacs.eargs(%S, %s)" | 1815 | (python-send-receive (format "emacs.eargs(%S, %s)" |
| 1720 | symbol python-imports))) | 1816 | symbol python-imports))) |
| 1721 | ;; Try moving to symbol before enclosing parens. | 1817 | ;; Try moving to symbol before enclosing parens. |
| 1722 | (let ((s (syntax-ppss))) | 1818 | (let ((s (syntax-ppss))) |
| 1723 | (unless (zerop (car s)) | 1819 | (unless (zerop (car s)) |
| 1724 | (when (eq ?\( (char-after (nth 1 s))) | 1820 | (when (eq ?\( (char-after (nth 1 s))) |
| 1725 | (save-excursion | 1821 | (save-excursion |
| 1726 | (goto-char (nth 1 s)) | 1822 | (goto-char (nth 1 s)) |
| 1727 | (skip-syntax-backward "-") | 1823 | (skip-syntax-backward "-") |
| 1728 | (let ((point (point))) | 1824 | (let ((point (point))) |
| 1729 | (skip-chars-backward "a-zA-Z._") | 1825 | (skip-chars-backward "a-zA-Z._") |
| 1730 | (if (< (point) point) | 1826 | (if (< (point) point) |
| 1731 | (python-send-receive | 1827 | (python-send-receive |
| 1732 | (format "emacs.eargs(%S, %s)" | 1828 | (format "emacs.eargs(%S, %s)" |
| 1733 | (buffer-substring-no-properties (point) point) | 1829 | (buffer-substring-no-properties (point) point) |
| 1734 | python-imports)))))))))))) | 1830 | python-imports)))))))))))) |
| 1735 | 1831 | ||
| 1736 | ;;;; Info-look functionality. | 1832 | ;;;; Info-look functionality. |
| 1737 | 1833 | ||
| @@ -1751,9 +1847,9 @@ Used with `eval-after-load'." | |||
| 1751 | (condition-case () | 1847 | (condition-case () |
| 1752 | ;; Don't use `info' because it would pop-up a *info* buffer. | 1848 | ;; Don't use `info' because it would pop-up a *info* buffer. |
| 1753 | (with-no-warnings | 1849 | (with-no-warnings |
| 1754 | (Info-goto-node (format "(python%s-lib)Miscellaneous Index" | 1850 | (Info-goto-node (format "(python%s-lib)Miscellaneous Index" |
| 1755 | version)) | 1851 | version)) |
| 1756 | t) | 1852 | t) |
| 1757 | (error nil))))) | 1853 | (error nil))))) |
| 1758 | (info-lookup-maybe-add-help | 1854 | (info-lookup-maybe-add-help |
| 1759 | :mode 'python-mode | 1855 | :mode 'python-mode |
| @@ -1829,7 +1925,7 @@ The criterion is either a match for `jython-mode' via | |||
| 1829 | "`fill-paragraph-function' handling multi-line strings and possibly comments. | 1925 | "`fill-paragraph-function' handling multi-line strings and possibly comments. |
| 1830 | If any of the current line is in or at the end of a multi-line string, | 1926 | If any of the current line is in or at the end of a multi-line string, |
| 1831 | fill the string or the paragraph of it that point is in, preserving | 1927 | fill the string or the paragraph of it that point is in, preserving |
| 1832 | the strings's indentation." | 1928 | the string's indentation." |
| 1833 | (interactive "P") | 1929 | (interactive "P") |
| 1834 | (or (fill-comment-paragraph justify) | 1930 | (or (fill-comment-paragraph justify) |
| 1835 | (save-excursion | 1931 | (save-excursion |
| @@ -1845,7 +1941,7 @@ the strings's indentation." | |||
| 1845 | ;; paragraph in a multi-line string properly, so narrow | 1941 | ;; paragraph in a multi-line string properly, so narrow |
| 1846 | ;; to the string and then fill around (the end of) the | 1942 | ;; to the string and then fill around (the end of) the |
| 1847 | ;; current line. | 1943 | ;; current line. |
| 1848 | ((eq t (nth 3 syntax)) ; in fenced string | 1944 | ((eq t (nth 3 syntax)) ; in fenced string |
| 1849 | (goto-char (nth 8 syntax)) ; string start | 1945 | (goto-char (nth 8 syntax)) ; string start |
| 1850 | (setq start (line-beginning-position)) | 1946 | (setq start (line-beginning-position)) |
| 1851 | (setq end (condition-case () ; for unbalanced quotes | 1947 | (setq end (condition-case () ; for unbalanced quotes |
| @@ -1868,14 +1964,25 @@ the strings's indentation." | |||
| 1868 | ;; """ | 1964 | ;; """ |
| 1869 | ;; ... | 1965 | ;; ... |
| 1870 | ;; """ | 1966 | ;; """ |
| 1871 | (let* ((paragraph-separate | 1967 | (let ((paragraph-separate |
| 1872 | (concat ".*\\s|\"\"$" ; newline after opening quotes | 1968 | ;; Note that the string could be part of an |
| 1873 | "\\|\\(?:" paragraph-separate "\\)")) | 1969 | ;; expression, so it can have preceding and |
| 1874 | (paragraph-start | 1970 | ;; trailing non-whitespace. |
| 1875 | (concat ".*\\s|\"\"[ \t]*[^ \t].*" ; not newline after | 1971 | (concat |
| 1876 | ; opening quotes | 1972 | (rx (or |
| 1877 | "\\|\\(?:" paragraph-separate "\\)")) | 1973 | ;; Opening triple quote without following text. |
| 1878 | (fill-paragraph-function)) | 1974 | (and (* nonl) |
| 1975 | (group (syntax string-delimiter)) | ||
| 1976 | (repeat 2 (backref 1)) | ||
| 1977 | ;; Fixme: Not sure about including | ||
| 1978 | ;; trailing whitespace. | ||
| 1979 | (* (any " \t")) | ||
| 1980 | eol) | ||
| 1981 | ;; Closing trailing quote without preceding text. | ||
| 1982 | (and (group (any ?\" ?')) (backref 2) | ||
| 1983 | (syntax string-delimiter)))) | ||
| 1984 | "\\(?:" paragraph-separate "\\)")) | ||
| 1985 | fill-paragraph-function) | ||
| 1879 | (fill-paragraph justify))))))) t) | 1986 | (fill-paragraph justify))))))) t) |
| 1880 | 1987 | ||
| 1881 | (defun python-shift-left (start end &optional count) | 1988 | (defun python-shift-left (start end &optional count) |
| @@ -1988,7 +2095,8 @@ Uses `python-beginning-of-block', `python-end-of-block'." | |||
| 1988 | (let ((start (line-beginning-position))) | 2095 | (let ((start (line-beginning-position))) |
| 1989 | ;; Skip over continued lines. | 2096 | ;; Skip over continued lines. |
| 1990 | (while (and (eq ?\\ (char-before (line-end-position))) | 2097 | (while (and (eq ?\\ (char-before (line-end-position))) |
| 1991 | (= 0 (forward-line 1)))) | 2098 | (= 0 (forward-line 1))) |
| 2099 | t) | ||
| 1992 | (push (buffer-substring start (line-beginning-position 2)) | 2100 | (push (buffer-substring start (line-beginning-position 2)) |
| 1993 | lines)))) | 2101 | lines)))) |
| 1994 | (setq python-imports | 2102 | (setq python-imports |
| @@ -2041,60 +2149,6 @@ Uses `python-imports' to load modules against which to complete." | |||
| 2041 | nil t) | 2149 | nil t) |
| 2042 | (match-beginning 1))))) | 2150 | (match-beginning 1))))) |
| 2043 | (if start (buffer-substring-no-properties start end)))) | 2151 | (if start (buffer-substring-no-properties start end)))) |
| 2044 | |||
| 2045 | (defun python-complete-symbol () | ||
| 2046 | "Perform completion on the Python symbol preceding point. | ||
| 2047 | Repeating the command scrolls the completion window." | ||
| 2048 | (interactive) | ||
| 2049 | (let ((window (get-buffer-window "*Completions*"))) | ||
| 2050 | (if (and (eq last-command this-command) | ||
| 2051 | (window-live-p window) (window-buffer window) | ||
| 2052 | (buffer-name (window-buffer window))) | ||
| 2053 | (with-current-buffer (window-buffer window) | ||
| 2054 | (if (pos-visible-in-window-p (point-max) window) | ||
| 2055 | (set-window-start window (point-min)) | ||
| 2056 | (save-selected-window | ||
| 2057 | (select-window window) | ||
| 2058 | (scroll-up)))) | ||
| 2059 | ;; Do completion. | ||
| 2060 | (let* ((end (point)) | ||
| 2061 | (symbol (python-partial-symbol)) | ||
| 2062 | (completions (python-symbol-completions symbol)) | ||
| 2063 | (completion (if completions | ||
| 2064 | (try-completion symbol completions)))) | ||
| 2065 | (when symbol | ||
| 2066 | (cond ((eq completion t)) | ||
| 2067 | ((null completion) | ||
| 2068 | (message "Can't find completion for \"%s\"" symbol) | ||
| 2069 | (ding)) | ||
| 2070 | ((not (string= symbol completion)) | ||
| 2071 | (delete-region (- end (length symbol)) end) | ||
| 2072 | (insert completion)) | ||
| 2073 | (t | ||
| 2074 | (message "Making completion list...") | ||
| 2075 | (with-output-to-temp-buffer "*Completions*" | ||
| 2076 | (display-completion-list completions symbol)) | ||
| 2077 | (message "Making completion list...%s" "done")))))))) | ||
| 2078 | |||
| 2079 | (defun python-try-complete (old) | ||
| 2080 | "Completion function for Python for use with `hippie-expand'." | ||
| 2081 | (when (derived-mode-p 'python-mode) ; though we only add it locally | ||
| 2082 | (unless old | ||
| 2083 | (let ((symbol (python-partial-symbol))) | ||
| 2084 | (he-init-string (- (point) (length symbol)) (point)) | ||
| 2085 | (if (not (he-string-member he-search-string he-tried-table)) | ||
| 2086 | (push he-search-string he-tried-table)) | ||
| 2087 | (setq he-expand-list | ||
| 2088 | (and symbol (python-symbol-completions symbol))))) | ||
| 2089 | (while (and he-expand-list | ||
| 2090 | (he-string-member (car he-expand-list) he-tried-table)) | ||
| 2091 | (pop he-expand-list)) | ||
| 2092 | (if he-expand-list | ||
| 2093 | (progn | ||
| 2094 | (he-substitute-string (pop he-expand-list)) | ||
| 2095 | t) | ||
| 2096 | (if old (he-reset-string)) | ||
| 2097 | nil))) | ||
| 2098 | 2152 | ||
| 2099 | ;;;; FFAP support | 2153 | ;;;; FFAP support |
| 2100 | 2154 | ||
| @@ -2105,6 +2159,33 @@ Repeating the command scrolls the completion window." | |||
| 2105 | (eval-after-load "ffap" | 2159 | (eval-after-load "ffap" |
| 2106 | '(push '(python-mode . python-module-path) ffap-alist)) | 2160 | '(push '(python-mode . python-module-path) ffap-alist)) |
| 2107 | 2161 | ||
| 2162 | ;;;; Find-function support | ||
| 2163 | |||
| 2164 | ;; Fixme: key binding? | ||
| 2165 | |||
| 2166 | (defun python-find-function (name) | ||
| 2167 | "Find source of definition of function NAME. | ||
| 2168 | Interactively, prompt for name." | ||
| 2169 | (interactive | ||
| 2170 | (let ((symbol (with-syntax-table python-dotty-syntax-table | ||
| 2171 | (current-word))) | ||
| 2172 | (enable-recursive-minibuffers t)) | ||
| 2173 | (list (read-string (if symbol | ||
| 2174 | (format "Find location of (default %s): " symbol) | ||
| 2175 | "Find location of: ") | ||
| 2176 | nil nil symbol)))) | ||
| 2177 | (unless python-imports | ||
| 2178 | (error "Not called from buffer visiting Python file")) | ||
| 2179 | (let* ((loc (python-send-receive (format "emacs.location_of (%S, %s)" | ||
| 2180 | name python-imports))) | ||
| 2181 | (loc (car (read-from-string loc))) | ||
| 2182 | (file (car loc)) | ||
| 2183 | (line (cdr loc))) | ||
| 2184 | (unless file (error "Don't know where `%s' is defined" name)) | ||
| 2185 | (pop-to-buffer (find-file-noselect file)) | ||
| 2186 | (when (integerp line) | ||
| 2187 | (goto-line line)))) | ||
| 2188 | |||
| 2108 | ;;;; Skeletons | 2189 | ;;;; Skeletons |
| 2109 | 2190 | ||
| 2110 | (defcustom python-use-skeletons nil | 2191 | (defcustom python-use-skeletons nil |
| @@ -2132,24 +2213,31 @@ The default contents correspond to the elements of `python-skeletons'." | |||
| 2132 | (function (intern (concat "python-insert-" name)))) | 2213 | (function (intern (concat "python-insert-" name)))) |
| 2133 | `(progn | 2214 | `(progn |
| 2134 | (add-to-list 'python-skeletons ',(cons name function)) | 2215 | (add-to-list 'python-skeletons ',(cons name function)) |
| 2135 | (define-abbrev python-mode-abbrev-table ,name "" ',function | 2216 | ;; Usual technique for inserting a skeleton, but expand |
| 2136 | :system t :case-fixed t | 2217 | ;; to the original abbrev instead if in a comment or string. |
| 2137 | :enable-function (lambda () python-use-skeletons)) | 2218 | (define-abbrev python-mode-abbrev-table ,name "" |
| 2219 | ;; Quote this to give a readable abbrev table. | ||
| 2220 | '(lambda () | ||
| 2221 | (if (python-in-string/comment) | ||
| 2222 | (insert ,name) | ||
| 2223 | (,function))) | ||
| 2224 | nil t) ; system abbrev | ||
| 2138 | (define-skeleton ,function | 2225 | (define-skeleton ,function |
| 2139 | ,(format "Insert Python \"%s\" template." name) | 2226 | ,(format "Insert Python \"%s\" template." name) |
| 2140 | ,@elements))))) | 2227 | ,@elements))))) |
| 2141 | (put 'def-python-skeleton 'lisp-indent-function 2) | 2228 | (put 'def-python-skeleton 'lisp-indent-function 2) |
| 2142 | 2229 | ||
| 2143 | ;; From `skeleton-further-elements': | 2230 | ;; From `skeleton-further-elements' set below: |
| 2144 | ;; `<': outdent a level; | 2231 | ;; `<': outdent a level; |
| 2145 | ;; `^': delete indentation on current line and also previous newline. | 2232 | ;; `^': delete indentation on current line and also previous newline. |
| 2146 | ;; Not quote like `delete-indentation'. Assumes point is at | 2233 | ;; Not quite like `delete-indentation'. Assumes point is at |
| 2147 | ;; beginning of indentation. | 2234 | ;; beginning of indentation. |
| 2148 | 2235 | ||
| 2149 | (def-python-skeleton if | 2236 | (def-python-skeleton if |
| 2150 | "Condition: " | 2237 | "Condition: " |
| 2151 | "if " str ":" \n | 2238 | "if " str ":" \n |
| 2152 | > _ \n | 2239 | > -1 ; Fixme: I don't understand the spurious space this removes. |
| 2240 | _ \n | ||
| 2153 | ("other condition, %s: " | 2241 | ("other condition, %s: " |
| 2154 | < ; Avoid wrong indentation after block opening. | 2242 | < ; Avoid wrong indentation after block opening. |
| 2155 | "elif " str ":" \n | 2243 | "elif " str ":" \n |
| @@ -2167,19 +2255,19 @@ The default contents correspond to the elements of `python-skeletons'." | |||
| 2167 | (def-python-skeleton while | 2255 | (def-python-skeleton while |
| 2168 | "Condition: " | 2256 | "Condition: " |
| 2169 | "while " str ":" \n | 2257 | "while " str ":" \n |
| 2170 | > _ \n | 2258 | > -1 _ \n |
| 2171 | '(python-else) | ^) | 2259 | '(python-else) | ^) |
| 2172 | 2260 | ||
| 2173 | (def-python-skeleton for | 2261 | (def-python-skeleton for |
| 2174 | "Target, %s: " | 2262 | "Target, %s: " |
| 2175 | "for " str " in " (skeleton-read "Expression, %s: ") ":" \n | 2263 | "for " str " in " (skeleton-read "Expression, %s: ") ":" \n |
| 2176 | > _ \n | 2264 | > -1 _ \n |
| 2177 | '(python-else) | ^) | 2265 | '(python-else) | ^) |
| 2178 | 2266 | ||
| 2179 | (def-python-skeleton try/except | 2267 | (def-python-skeleton try/except |
| 2180 | nil | 2268 | nil |
| 2181 | "try:" \n | 2269 | "try:" \n |
| 2182 | > _ \n | 2270 | > -1 _ \n |
| 2183 | ("Exception, %s: " | 2271 | ("Exception, %s: " |
| 2184 | < "except " str '(python-target) ":" \n | 2272 | < "except " str '(python-target) ":" \n |
| 2185 | > _ \n nil) | 2273 | > _ \n nil) |
| @@ -2194,7 +2282,7 @@ The default contents correspond to the elements of `python-skeletons'." | |||
| 2194 | (def-python-skeleton try/finally | 2282 | (def-python-skeleton try/finally |
| 2195 | nil | 2283 | nil |
| 2196 | "try:" \n | 2284 | "try:" \n |
| 2197 | > _ \n | 2285 | > -1 _ \n |
| 2198 | < "finally:" \n | 2286 | < "finally:" \n |
| 2199 | > _ \n) | 2287 | > _ \n) |
| 2200 | 2288 | ||
| @@ -2202,7 +2290,7 @@ The default contents correspond to the elements of `python-skeletons'." | |||
| 2202 | "Name: " | 2290 | "Name: " |
| 2203 | "def " str " (" ("Parameter, %s: " (unless (equal ?\( (char-before)) ", ") | 2291 | "def " str " (" ("Parameter, %s: " (unless (equal ?\( (char-before)) ", ") |
| 2204 | str) "):" \n | 2292 | str) "):" \n |
| 2205 | "\"\"\"" @ " \"\"\"" \n ; Fixme: syntaxification wrong for """""" | 2293 | "\"\"\"" - "\"\"\"" \n ; Fixme: extra space inserted -- why?). |
| 2206 | > _ \n) | 2294 | > _ \n) |
| 2207 | 2295 | ||
| 2208 | (def-python-skeleton class | 2296 | (def-python-skeleton class |
| @@ -2212,7 +2300,7 @@ The default contents correspond to the elements of `python-skeletons'." | |||
| 2212 | str) | 2300 | str) |
| 2213 | & ")" | -2 ; close list or remove opening | 2301 | & ")" | -2 ; close list or remove opening |
| 2214 | ":" \n | 2302 | ":" \n |
| 2215 | "\"\"\"" @ " \"\"\"" \n | 2303 | "\"\"\"" - "\"\"\"" \n |
| 2216 | > _ \n) | 2304 | > _ \n) |
| 2217 | 2305 | ||
| 2218 | (defvar python-default-template "if" | 2306 | (defvar python-default-template "if" |
| @@ -2255,35 +2343,35 @@ without confirmation." | |||
| 2255 | (pymacs-load "bikeemacs" "brm-") ; first line of normal recipe | 2343 | (pymacs-load "bikeemacs" "brm-") ; first line of normal recipe |
| 2256 | (let ((py-mode-map (make-sparse-keymap)) ; it assumes this | 2344 | (let ((py-mode-map (make-sparse-keymap)) ; it assumes this |
| 2257 | (features (cons 'python-mode features))) ; and requires this | 2345 | (features (cons 'python-mode features))) ; and requires this |
| 2258 | (brm-init)) ; second line of normal recipe | 2346 | (brm-init) ; second line of normal recipe |
| 2259 | (remove-hook 'python-mode-hook ; undo this from `brm-init' | 2347 | (remove-hook 'python-mode-hook ; undo this from `brm-init' |
| 2260 | '(lambda () (easy-menu-add brm-menu))) | 2348 | '(lambda () (easy-menu-add brm-menu))) |
| 2261 | (easy-menu-define | 2349 | (easy-menu-define |
| 2262 | python-brm-menu python-mode-map | 2350 | python-brm-menu python-mode-map |
| 2263 | "Bicycle Repair Man" | 2351 | "Bicycle Repair Man" |
| 2264 | '("BicycleRepairMan" | 2352 | '("BicycleRepairMan" |
| 2265 | :help "Interface to navigation and refactoring tool" | 2353 | :help "Interface to navigation and refactoring tool" |
| 2266 | "Queries" | 2354 | "Queries" |
| 2267 | ["Find References" brm-find-references | 2355 | ["Find References" brm-find-references |
| 2268 | :help "Find references to name at point in compilation buffer"] | 2356 | :help "Find references to name at point in compilation buffer"] |
| 2269 | ["Find Definition" brm-find-definition | 2357 | ["Find Definition" brm-find-definition |
| 2270 | :help "Find definition of name at point"] | 2358 | :help "Find definition of name at point"] |
| 2271 | "-" | 2359 | "-" |
| 2272 | "Refactoring" | 2360 | "Refactoring" |
| 2273 | ["Rename" brm-rename | 2361 | ["Rename" brm-rename |
| 2274 | :help "Replace name at point with a new name everywhere"] | 2362 | :help "Replace name at point with a new name everywhere"] |
| 2275 | ["Extract Method" brm-extract-method | 2363 | ["Extract Method" brm-extract-method |
| 2276 | :active (and mark-active (not buffer-read-only)) | 2364 | :active (and mark-active (not buffer-read-only)) |
| 2277 | :help "Replace statements in region with a method"] | 2365 | :help "Replace statements in region with a method"] |
| 2278 | ["Extract Local Variable" brm-extract-local-variable | 2366 | ["Extract Local Variable" brm-extract-local-variable |
| 2279 | :active (and mark-active (not buffer-read-only)) | 2367 | :active (and mark-active (not buffer-read-only)) |
| 2280 | :help "Replace expression in region with an assignment"] | 2368 | :help "Replace expression in region with an assignment"] |
| 2281 | ["Inline Local Variable" brm-inline-local-variable | 2369 | ["Inline Local Variable" brm-inline-local-variable |
| 2282 | :help | 2370 | :help |
| 2283 | "Substitute uses of variable at point with its definition"] | 2371 | "Substitute uses of variable at point with its definition"] |
| 2284 | ;; Fixme: Should check for anything to revert. | 2372 | ;; Fixme: Should check for anything to revert. |
| 2285 | ["Undo Last Refactoring" brm-undo :help ""]))) | 2373 | ["Undo Last Refactoring" brm-undo :help ""])))) |
| 2286 | (error (error "Bicyclerepairman setup failed: %s" data)))) | 2374 | (error (error "BicycleRepairMan setup failed: %s" data)))) |
| 2287 | 2375 | ||
| 2288 | ;;;; Modes. | 2376 | ;;;; Modes. |
| 2289 | 2377 | ||
| @@ -2291,10 +2379,27 @@ without confirmation." | |||
| 2291 | (defvar eldoc-documentation-function) | 2379 | (defvar eldoc-documentation-function) |
| 2292 | (defvar python-mode-running) ;Dynamically scoped var. | 2380 | (defvar python-mode-running) ;Dynamically scoped var. |
| 2293 | 2381 | ||
| 2382 | ;; Stuff to allow expanding abbrevs with non-word constituents. | ||
| 2383 | (defun python-abbrev-pc-hook () | ||
| 2384 | "Reset the syntax table after possibly expanding abbrevs." | ||
| 2385 | (remove-hook 'post-command-hook 'python-abbrev-pc-hook t) | ||
| 2386 | (set-syntax-table python-mode-syntax-table)) | ||
| 2387 | |||
| 2388 | (defvar python-abbrev-syntax-table | ||
| 2389 | (copy-syntax-table python-mode-syntax-table) | ||
| 2390 | "Syntax table used when expanding abbrevs.") | ||
| 2391 | |||
| 2392 | (defun python-pea-hook () | ||
| 2393 | "Set the syntax table before possibly expanding abbrevs." | ||
| 2394 | (set-syntax-table python-abbrev-syntax-table) | ||
| 2395 | (add-hook 'post-command-hook 'python-abbrev-pc-hook nil t)) | ||
| 2396 | (modify-syntax-entry ?/ "w" python-abbrev-syntax-table) | ||
| 2397 | |||
| 2294 | ;;;###autoload | 2398 | ;;;###autoload |
| 2295 | (define-derived-mode python-mode fundamental-mode "Python" | 2399 | (define-derived-mode python-mode fundamental-mode "Python" |
| 2296 | "Major mode for editing Python files. | 2400 | "Major mode for editing Python files. |
| 2297 | Font Lock mode is currently required for correct parsing of the source. | 2401 | Turns on Font Lock mode unconditionally since it is currently required |
| 2402 | for correct parsing of the source. | ||
| 2298 | See also `jython-mode', which is actually invoked if the buffer appears to | 2403 | See also `jython-mode', which is actually invoked if the buffer appears to |
| 2299 | contain Jython code. See also `run-python' and associated Python mode | 2404 | contain Jython code. See also `run-python' and associated Python mode |
| 2300 | commands for running Python under Emacs. | 2405 | commands for running Python under Emacs. |
| @@ -2363,24 +2468,31 @@ with skeleton expansions for compound statement templates. | |||
| 2363 | (add-hook 'eldoc-mode-hook | 2468 | (add-hook 'eldoc-mode-hook |
| 2364 | (lambda () (run-python nil t)) ; need it running | 2469 | (lambda () (run-python nil t)) ; need it running |
| 2365 | nil t) | 2470 | nil t) |
| 2471 | (set (make-local-variable 'symbol-completion-symbol-function) | ||
| 2472 | 'python-partial-symbol) | ||
| 2473 | (set (make-local-variable 'symbol-completion-completions-function) | ||
| 2474 | 'python-symbol-completions) | ||
| 2366 | ;; Fixme: should be in hideshow. This seems to be of limited use | 2475 | ;; Fixme: should be in hideshow. This seems to be of limited use |
| 2367 | ;; since it isn't (can't be) indentation-based. Also hide-level | 2476 | ;; since it isn't (can't be) indentation-based. Also hide-level |
| 2368 | ;; doesn't seem to work properly. | 2477 | ;; doesn't seem to work properly. |
| 2369 | (add-to-list 'hs-special-modes-alist | 2478 | (add-to-list 'hs-special-modes-alist |
| 2370 | `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#" | 2479 | `(python-mode "^\\s-*\\(?:def\\|class\\)\\>" nil "#" |
| 2371 | ,(lambda (arg) | 2480 | ,(lambda (arg) |
| 2372 | (python-end-of-defun) | 2481 | (python-end-of-defun) |
| 2373 | (skip-chars-backward " \t\n")) | 2482 | (skip-chars-backward " \t\n")) |
| 2374 | nil)) | 2483 | nil)) |
| 2375 | (set (make-local-variable 'skeleton-further-elements) | 2484 | (set (make-local-variable 'skeleton-further-elements) |
| 2376 | '((< '(backward-delete-char-untabify (min python-indent | 2485 | '((< '(backward-delete-char-untabify (min python-indent |
| 2377 | (current-column)))) | 2486 | (current-column)))) |
| 2378 | (^ '(- (1+ (current-indentation)))))) | 2487 | (^ '(- (1+ (current-indentation)))))) |
| 2488 | (add-hook 'pre-abbrev-expand-hook 'python-pea-hook nil t) | ||
| 2379 | (if (featurep 'hippie-exp) | 2489 | (if (featurep 'hippie-exp) |
| 2380 | (set (make-local-variable 'hippie-expand-try-functions-list) | 2490 | (set (make-local-variable 'hippie-expand-try-functions-list) |
| 2381 | (cons 'python-try-complete hippie-expand-try-functions-list))) | 2491 | (cons 'symbol-completion-try-complete |
| 2492 | hippie-expand-try-functions-list))) | ||
| 2382 | ;; Python defines TABs as being 8-char wide. | 2493 | ;; Python defines TABs as being 8-char wide. |
| 2383 | (set (make-local-variable 'tab-width) 8) | 2494 | (set (make-local-variable 'tab-width) 8) |
| 2495 | (unless font-lock-mode (font-lock-mode 1)) | ||
| 2384 | (when python-guess-indent (python-guess-indent)) | 2496 | (when python-guess-indent (python-guess-indent)) |
| 2385 | ;; Let's make it harder for the user to shoot himself in the foot. | 2497 | ;; Let's make it harder for the user to shoot himself in the foot. |
| 2386 | (unless (= tab-width python-indent) | 2498 | (unless (= tab-width python-indent) |
| @@ -2391,11 +2503,16 @@ with skeleton expansions for compound statement templates. | |||
| 2391 | (let ((python-mode-running t)) | 2503 | (let ((python-mode-running t)) |
| 2392 | (python-maybe-jython)))) | 2504 | (python-maybe-jython)))) |
| 2393 | 2505 | ||
| 2506 | ;; Not done automatically in Emacs 21 or 22. | ||
| 2507 | (defcustom python-mode-hook nil | ||
| 2508 | "Hook run when entering Python mode." | ||
| 2509 | :group 'python | ||
| 2510 | :type 'hook) | ||
| 2394 | (custom-add-option 'python-mode-hook 'imenu-add-menubar-index) | 2511 | (custom-add-option 'python-mode-hook 'imenu-add-menubar-index) |
| 2395 | (custom-add-option 'python-mode-hook | 2512 | (custom-add-option 'python-mode-hook |
| 2396 | (lambda () | 2513 | (lambda () |
| 2397 | "Turn off Indent Tabs mode." | 2514 | "Turn off Indent Tabs mode." |
| 2398 | (set (make-local-variable 'indent-tabs-mode) nil))) | 2515 | (setq indent-tabs-mode nil))) |
| 2399 | (custom-add-option 'python-mode-hook 'turn-on-eldoc-mode) | 2516 | (custom-add-option 'python-mode-hook 'turn-on-eldoc-mode) |
| 2400 | (custom-add-option 'python-mode-hook 'abbrev-mode) | 2517 | (custom-add-option 'python-mode-hook 'abbrev-mode) |
| 2401 | (custom-add-option 'python-mode-hook 'python-setup-brm) | 2518 | (custom-add-option 'python-mode-hook 'python-setup-brm) |
| @@ -2776,5 +2893,6 @@ filter." | |||
| 2776 | 2893 | ||
| 2777 | (provide 'python) | 2894 | (provide 'python) |
| 2778 | (provide 'python-21) | 2895 | (provide 'python-21) |
| 2896 | |||
| 2779 | ;; arch-tag: 6fce1d99-a704-4de9-ba19-c6e4912b0554 | 2897 | ;; arch-tag: 6fce1d99-a704-4de9-ba19-c6e4912b0554 |
| 2780 | ;;; python.el ends here | 2898 | ;;; python.el ends here |