diff options
Diffstat (limited to 'lisp/progmodes/python.el')
| -rw-r--r-- | lisp/progmodes/python.el | 643 |
1 files changed, 379 insertions, 264 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 1028e937924..bfa507b851a 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el | |||
| @@ -38,7 +38,7 @@ | |||
| 38 | 38 | ||
| 39 | ;; This doesn't implement all the facilities of python-mode.el. Some | 39 | ;; This doesn't implement all the facilities of python-mode.el. Some |
| 40 | ;; just need doing, e.g. catching exceptions in the inferior Python | 40 | ;; just need doing, e.g. catching exceptions in the inferior Python |
| 41 | ;; buffer (but see M-x pdb for debugging). [Atually, the use of | 41 | ;; buffer (but see M-x pdb for debugging). [Actually, the use of |
| 42 | ;; `compilation-minor-mode' now is probably enough for that.] Others | 42 | ;; `compilation-minor-mode' now is probably enough for that.] Others |
| 43 | ;; don't seem appropriate. For instance, `forward-into-nomenclature' | 43 | ;; don't seem appropriate. For instance, `forward-into-nomenclature' |
| 44 | ;; should be done separately, since it's not specific to Python, and | 44 | ;; should be done separately, since it's not specific to Python, and |
| @@ -56,16 +56,25 @@ | |||
| 56 | ;; bindings are changed to obey Emacs conventions, and things like | 56 | ;; bindings are changed to obey Emacs conventions, and things like |
| 57 | ;; marking blocks and `beginning-of-defun' behave differently. | 57 | ;; marking blocks and `beginning-of-defun' behave differently. |
| 58 | 58 | ||
| 59 | ;; TODO: See various Fixmes below. It should be possible to arrange | ||
| 60 | ;; some sort of completion using the inferior interpreter. | ||
| 61 | |||
| 59 | ;;; Code: | 62 | ;;; Code: |
| 60 | 63 | ||
| 61 | (require 'syntax) ; ensure appropriate version | ||
| 62 | ;; It's messy to autoload the relevant comint functions so that comint | 64 | ;; It's messy to autoload the relevant comint functions so that comint |
| 63 | ;; is only required when inferior Python is used. | 65 | ;; is only required when inferior Python is used. |
| 64 | (require 'comint) | 66 | (require 'comint) |
| 67 | (eval-when-compile | ||
| 68 | (require 'compile) | ||
| 69 | (autoload 'Info-last "info") | ||
| 70 | (autoload 'Info-exit "info") | ||
| 71 | (autoload 'info-lookup-maybe-add-help "info-look")) | ||
| 72 | (autoload 'compilation-start "compile") ; spurious compiler warning anyway | ||
| 65 | 73 | ||
| 66 | (defgroup python nil | 74 | (defgroup python nil |
| 67 | "Silly walks in the Python language" | 75 | "Silly walks in the Python language" |
| 68 | :group 'languages | 76 | :group 'languages |
| 77 | :version "21.4" | ||
| 69 | :link '(emacs-commentary-link "python")) | 78 | :link '(emacs-commentary-link "python")) |
| 70 | 79 | ||
| 71 | ;;;###autoload | 80 | ;;;###autoload |
| @@ -101,7 +110,8 @@ | |||
| 101 | (group (syntax string-quote)) ; maybe gets property | 110 | (group (syntax string-quote)) ; maybe gets property |
| 102 | (backref 2) ; per first quote | 111 | (backref 2) ; per first quote |
| 103 | (group (backref 2)))) ; maybe gets property | 112 | (group (backref 2)))) ; maybe gets property |
| 104 | (1 (python-quote-syntax 1)) (2 (python-quote-syntax 2)) | 113 | (1 (python-quote-syntax 1)) |
| 114 | (2 (python-quote-syntax 2)) | ||
| 105 | (3 (python-quote-syntax 3))) | 115 | (3 (python-quote-syntax 3))) |
| 106 | ;; This doesn't really help. | 116 | ;; This doesn't really help. |
| 107 | ;;; (,(rx (and ?\\ (group ?\n))) (1 " ")) | 117 | ;;; (,(rx (and ?\\ (group ?\n))) (1 " ")) |
| @@ -110,40 +120,43 @@ | |||
| 110 | (defun python-quote-syntax (n) | 120 | (defun python-quote-syntax (n) |
| 111 | "Put `syntax-table' property correctly on triple quote. | 121 | "Put `syntax-table' property correctly on triple quote. |
| 112 | Used for syntactic keywords. N is the match number (1, 2 or 3)." | 122 | Used for syntactic keywords. N is the match number (1, 2 or 3)." |
| 113 | ;; Given a triple quote, we have to look backwards for a previous | 123 | ;; Given a triple quote, we have to check the context to know |
| 114 | ;; occurrence of the sequence to know whether this is an opening or | 124 | ;; whether this is an opening or closing triple or whether it's |
| 115 | ;; closing triple. We also have to sort out a possible prefix -- | 125 | ;; quoted anyhow, and should be ignored. (For that we need to do |
| 116 | ;; well, we don't _have_ to, but I think it should be treated as | 126 | ;; the same job as `syntax-ppss' to be correct and it seems to be OK |
| 117 | ;; part of the string. | 127 | ;; to use it here despite initial worries.) We also have to sort |
| 118 | (let ((tag (save-excursion | 128 | ;; out a possible prefix -- well, we don't _have_ to, but I think it |
| 119 | (goto-char (match-beginning 0)) | 129 | ;; should be treated as part of the string. |
| 120 | (unless (eq ?\\ (char-before)) | 130 | |
| 121 | (cond | 131 | ;; Test cases: |
| 122 | ;; Look for a previous string fence. | 132 | ;; ur"""ar""" x='"' # """ |
| 123 | ((or (zerop (skip-syntax-backward "^|")) | 133 | ;; x = ''' """ ' a |
| 124 | (bobp)) | 134 | ;; ''' |
| 125 | 'start) ; no previous string fence | 135 | ;; x '"""' x |
| 126 | ;; Check fence on a matching quote. | 136 | (save-excursion |
| 127 | ((eq (char-before) (char-after (match-beginning 2))) | 137 | (goto-char (match-beginning 0)) |
| 128 | (if (eq (char-before) (char-after)) | 138 | (unless (eq ?\\ (char-before)) |
| 129 | 'end ; fence ended string | 139 | (cond |
| 130 | 'start)) ; began string | 140 | ;; Consider property for the last char if in a fenced string. |
| 131 | ;; Check for matching prefixed string. | 141 | ((= n 3) |
| 132 | ((and (memq (char-before) '(?u ?U ?r ?R)) | 142 | (let ((syntax (syntax-ppss))) |
| 133 | (skip-chars-forward "rR")) | 143 | (when (eq t (nth 3 syntax)) ; after unclosed fence |
| 134 | (if (eq (char-after) (char-after (match-beginning 2))) | 144 | (goto-char (nth 8 syntax)) ; fence position |
| 135 | 'end)) ; else non-matching: return nil | 145 | ;; Skip any prefix. |
| 136 | ;; For non-matching quote, start new string. | 146 | (if (memq (char-after) '(?u ?U ?R ?r)) |
| 137 | ((/= (char-before) (char-after)) | 147 | (skip-chars-forward "uUrR")) |
| 138 | 'start)))))) | 148 | ;; Is it a matching sequence? |
| 139 | (if (if (eq tag 'start) ; Maybe starts a new string. | 149 | (if (eq (char-after) (char-after (match-beginning 2))) |
| 140 | ;; Initial property if this is the prefix (empty or not) or | 150 | (eval-when-compile (string-to-syntax "|")))))) |
| 141 | ;; isn't the prefix and the prefix is empty. | 151 | ;; Consider property for initial char, accounting for prefixes. |
| 142 | (or (= n 1) (and (= n 2) (= (match-beginning 1) (match-end 1)))) | 152 | ((or (and (= n 2) ; not prefix |
| 143 | (and (eq tag 'end) ; Maybe ends existing string. | 153 | (= (match-beginning 1) (match-end 1))) ; prefix is null |
| 144 | (= n 3))) ; Match is at end. | 154 | (and (= n 1) ; prefix |
| 145 | (eval-when-compile (string-to-syntax "|")) | 155 | (/= (match-beginning 1) (match-end 1)))) ; non-empty |
| 146 | ;; Otherwise the property is nil, which is OK. | 156 | (unless (eq 'string (syntax-ppss-context (syntax-ppss))) |
| 157 | (eval-when-compile (string-to-syntax "|"))))) | ||
| 158 | ;; Otherwise (we're in a non-matching string) the property is | ||
| 159 | ;; nil, which is OK. | ||
| 147 | ))) | 160 | ))) |
| 148 | 161 | ||
| 149 | ;; This isn't currently in `font-lock-defaults' as probably not worth | 162 | ;; This isn't currently in `font-lock-defaults' as probably not worth |
| @@ -386,27 +399,29 @@ Continuation lines follow a backslash-terminated line starting a statement." | |||
| 386 | Set `python-indent' locally to the value guessed." | 399 | Set `python-indent' locally to the value guessed." |
| 387 | (interactive) | 400 | (interactive) |
| 388 | (save-excursion | 401 | (save-excursion |
| 389 | (goto-char (point-min)) | 402 | (save-restriction |
| 390 | (let (done indent) | 403 | (widen) |
| 391 | (while (and (not done) (not (eobp))) | 404 | (goto-char (point-min)) |
| 392 | (when (and (re-search-forward (rx (and ?: (0+ space) | 405 | (let (done indent) |
| 393 | (or (syntax comment-start) | 406 | (while (and (not done) (not (eobp))) |
| 394 | line-end))) | 407 | (when (and (re-search-forward (rx (and ?: (0+ space) |
| 395 | nil 'move) | 408 | (or (syntax comment-start) |
| 396 | (python-open-block-statement-p)) | 409 | line-end))) |
| 397 | (save-excursion | 410 | nil 'move) |
| 398 | (python-beginning-of-statement) | 411 | (python-open-block-statement-p)) |
| 399 | (let ((initial (current-indentation))) | 412 | (save-excursion |
| 400 | (if (zerop (python-next-statement)) | 413 | (python-beginning-of-statement) |
| 401 | (setq indent (- (current-indentation) initial))) | 414 | (let ((initial (current-indentation))) |
| 402 | (if (and (>= indent 2) (<= indent 8)) ; sanity check | 415 | (if (zerop (python-next-statement)) |
| 403 | (setq done t)))))) | 416 | (setq indent (- (current-indentation) initial))) |
| 404 | (when done | 417 | (if (and (>= indent 2) (<= indent 8)) ; sanity check |
| 405 | (when (/= indent (default-value 'python-indent)) | 418 | (setq done t)))))) |
| 406 | (set (make-local-variable 'python-indent) indent) | 419 | (when done |
| 407 | (unless (= tab-width python-indent) | 420 | (when (/= indent (default-value 'python-indent)) |
| 408 | (setq indent-tabs-mode nil))) | 421 | (set (make-local-variable 'python-indent) indent) |
| 409 | indent)))) | 422 | (unless (= tab-width python-indent) |
| 423 | (setq indent-tabs-mode nil))) | ||
| 424 | indent))))) | ||
| 410 | 425 | ||
| 411 | (defun python-calculate-indentation () | 426 | (defun python-calculate-indentation () |
| 412 | "Calculate Python indentation for line at point." | 427 | "Calculate Python indentation for line at point." |
| @@ -590,7 +605,7 @@ start of buffer." | |||
| 590 | (def-re (rx (and line-start (0+ space) (or "def" "class") | 605 | (def-re (rx (and line-start (0+ space) (or "def" "class") |
| 591 | (1+ space) | 606 | (1+ space) |
| 592 | (group (1+ (or word (syntax symbol))))))) | 607 | (group (1+ (or word (syntax symbol))))))) |
| 593 | point found lep def-line) | 608 | found lep def-line) |
| 594 | (if (python-comment-line-p) | 609 | (if (python-comment-line-p) |
| 595 | (setq ci most-positive-fixnum)) | 610 | (setq ci most-positive-fixnum)) |
| 596 | (while (and (not (bobp)) (not found)) | 611 | (while (and (not (bobp)) (not found)) |
| @@ -807,6 +822,7 @@ move and return nil. Otherwise return t." | |||
| 807 | 822 | ||
| 808 | ;;;; Imenu. | 823 | ;;;; Imenu. |
| 809 | 824 | ||
| 825 | (defvar python-recursing) | ||
| 810 | (defun python-imenu-create-index () | 826 | (defun python-imenu-create-index () |
| 811 | "`imenu-create-index-function' for Python. | 827 | "`imenu-create-index-function' for Python. |
| 812 | 828 | ||
| @@ -814,10 +830,10 @@ Makes nested Imenu menus from nested `class' and `def' statements. | |||
| 814 | The nested menus are headed by an item referencing the outer | 830 | The nested menus are headed by an item referencing the outer |
| 815 | definition; it has a space prepended to the name so that it sorts | 831 | definition; it has a space prepended to the name so that it sorts |
| 816 | first with `imenu--sort-by-name'." | 832 | first with `imenu--sort-by-name'." |
| 817 | (unless (boundp 'recursing) ; dynamically bound below | 833 | (unless (boundp 'python-recursing) ; dynamically bound below |
| 818 | (goto-char (point-min))) ; normal call from Imenu | 834 | (goto-char (point-min))) ; normal call from Imenu |
| 819 | (let (index-alist ; accumulated value to return | 835 | (let (index-alist ; accumulated value to return |
| 820 | name is-class pos) | 836 | name) |
| 821 | (while (re-search-forward | 837 | (while (re-search-forward |
| 822 | (rx (and line-start (0+ space) ; leading space | 838 | (rx (and line-start (0+ space) ; leading space |
| 823 | (or (group "def") (group "class")) ; type | 839 | (or (group "def") (group "class")) ; type |
| @@ -830,7 +846,7 @@ first with `imenu--sort-by-name'." | |||
| 830 | (setq name (concat "class " name))) | 846 | (setq name (concat "class " name))) |
| 831 | (save-restriction | 847 | (save-restriction |
| 832 | (narrow-to-defun) | 848 | (narrow-to-defun) |
| 833 | (let* ((recursing t) | 849 | (let* ((python-recursing t) |
| 834 | (sublist (python-imenu-create-index))) | 850 | (sublist (python-imenu-create-index))) |
| 835 | (if sublist | 851 | (if sublist |
| 836 | (progn (push (cons (concat " " name) pos) sublist) | 852 | (progn (push (cons (concat " " name) pos) sublist) |
| @@ -884,8 +900,6 @@ If not at the end of line's indentation, or on a comment line, just call | |||
| 884 | (defvar python-saved-check-command nil | 900 | (defvar python-saved-check-command nil |
| 885 | "Internal use.") | 901 | "Internal use.") |
| 886 | 902 | ||
| 887 | (autoload 'compilation-start "compile") | ||
| 888 | |||
| 889 | ;; After `sgml-validate-command'. | 903 | ;; After `sgml-validate-command'. |
| 890 | (defun python-check (command) | 904 | (defun python-check (command) |
| 891 | "Check a Python file (default current buffer's file). | 905 | "Check a Python file (default current buffer's file). |
| @@ -950,6 +964,13 @@ to be the new process's buffer. If you only run one process, this will | |||
| 950 | do the right thing. If you run multiple processes, you can change | 964 | do the right thing. If you run multiple processes, you can change |
| 951 | `python-buffer' to another process buffer with \\[set-variable].") | 965 | `python-buffer' to another process buffer with \\[set-variable].") |
| 952 | 966 | ||
| 967 | (defconst python-compilation-regexp-alist | ||
| 968 | `((,(rx (and line-start (1+ (any " \t")) "File \"" | ||
| 969 | (group (1+ (not (any "\"<")))) ; avoid `<stdin>' &c | ||
| 970 | "\", line " (group (1+ digit)))) | ||
| 971 | 1 python-compilation-line-number)) | ||
| 972 | "`compilation-error-regexp-alist' for inferior Python.") | ||
| 973 | |||
| 953 | (define-derived-mode inferior-python-mode comint-mode "Inferior Python" | 974 | (define-derived-mode inferior-python-mode comint-mode "Inferior Python" |
| 954 | "Major mode for interacting with an inferior Python process. | 975 | "Major mode for interacting with an inferior Python process. |
| 955 | A Python process can be started with \\[run-python]. | 976 | A Python process can be started with \\[run-python]. |
| @@ -973,7 +994,14 @@ For running multiple processes in multiple buffers, see `python-buffer'. | |||
| 973 | ;; Fixme: Maybe install some python-mode bindings too. | 994 | ;; Fixme: Maybe install some python-mode bindings too. |
| 974 | (define-key inferior-python-mode-map "\C-c\C-l" 'python-load-file) | 995 | (define-key inferior-python-mode-map "\C-c\C-l" 'python-load-file) |
| 975 | (define-key inferior-python-mode-map "\C-c\C-z" 'python-switch-to-python) | 996 | (define-key inferior-python-mode-map "\C-c\C-z" 'python-switch-to-python) |
| 976 | (setq comint-input-filter #'python-input-filter)) | 997 | (add-hook 'comint-input-filter-functions 'python-input-filter nil t) |
| 998 | (add-hook 'comint-preoutput-filter-functions #'python-preoutput-filter | ||
| 999 | nil t) | ||
| 1000 | ;; Still required by `comint-redirect-send-command', for instance: | ||
| 1001 | (set (make-local-variable 'comint-prompt-regexp) "^\\([>.]\\{3\\} \\)+") | ||
| 1002 | (set (make-local-variable 'compilation-error-regexp-alist) | ||
| 1003 | python-compilation-regexp-alist) | ||
| 1004 | (compilation-shell-minor-mode 1)) | ||
| 977 | 1005 | ||
| 978 | (defcustom inferior-python-filter-regexp "\\`\\s-*\\S-?\\S-?\\s-*\\'" | 1006 | (defcustom inferior-python-filter-regexp "\\`\\s-*\\S-?\\S-?\\s-*\\'" |
| 979 | "*Input matching this regexp is not saved on the history list. | 1007 | "*Input matching this regexp is not saved on the history list. |
| @@ -981,18 +1009,15 @@ Default ignores all inputs of 0, 1, or 2 non-blank characters." | |||
| 981 | :type 'regexp | 1009 | :type 'regexp |
| 982 | :group 'python) | 1010 | :group 'python) |
| 983 | 1011 | ||
| 984 | (defvar python-orig-start-line nil | 1012 | (defvar python-orig-start nil |
| 985 | "Line number at start of region sent to inferior Python.") | 1013 | "Marker to the start of the region passed to the inferior Python. |
| 986 | 1014 | It can also be a filename.") | |
| 987 | (defvar python-orig-file nil | ||
| 988 | "File name to associate with errors found in inferior Python.") | ||
| 989 | 1015 | ||
| 990 | (defun python-input-filter (str) | 1016 | (defun python-input-filter (str) |
| 991 | "`comint-input-filter' function for inferior Python. | 1017 | "`comint-input-filter' function for inferior Python. |
| 992 | Don't save anything matching `inferior-python-filter-regexp'. | 1018 | Don't save anything for STR matching `inferior-python-filter-regexp'. |
| 993 | Also resets variables for adjusting error messages." | 1019 | Also resets variables for adjusting error messages." |
| 994 | (setq python-orig-file nil | 1020 | (setq python-orig-start nil) |
| 995 | python-orig-start-line 1) | ||
| 996 | (not (string-match inferior-python-filter-regexp str))) | 1021 | (not (string-match inferior-python-filter-regexp str))) |
| 997 | 1022 | ||
| 998 | ;; Fixme: Loses with quoted whitespace. | 1023 | ;; Fixme: Loses with quoted whitespace. |
| @@ -1005,108 +1030,103 @@ Also resets variables for adjusting error messages." | |||
| 1005 | (t (let ((pos (string-match "[^ \t]" string))) | 1030 | (t (let ((pos (string-match "[^ \t]" string))) |
| 1006 | (if pos (python-args-to-list (substring string pos)))))))) | 1031 | (if pos (python-args-to-list (substring string pos)))))))) |
| 1007 | 1032 | ||
| 1008 | (defvar compilation-minor-mode-map) | ||
| 1009 | (defvar compilation-error-list) | ||
| 1010 | (defvar compilation-parsing-end) | ||
| 1011 | |||
| 1012 | (defconst python-compilation-regexp-alist | ||
| 1013 | `((,(rx (and line-start (1+ (any " \t")) "File \"" | ||
| 1014 | (group (1+ (not (any "\"<")))) ; avoid `<stdin>' &c | ||
| 1015 | "\", line " (group (1+ digit)))) | ||
| 1016 | 1 python-compilation-line-number)) | ||
| 1017 | "`compilation-error-regexp-alist' for inferior Python.") | ||
| 1018 | |||
| 1019 | (defun python-compilation-line-number (file col) | 1033 | (defun python-compilation-line-number (file col) |
| 1020 | "Return error descriptor of error found for FILE, column COL. | 1034 | "Return error descriptor of error found for FILE, column COL. |
| 1021 | Used as line-number hook function in `python-compilation-regexp-alist'." | 1035 | Used as line-number hook function in `python-compilation-regexp-alist'." |
| 1022 | (let ((line (save-excursion | 1036 | (let ((line (string-to-number (match-string 2)))) |
| 1023 | (goto-char (match-beginning 2)) | 1037 | (cons (point-marker) |
| 1024 | (read (current-buffer))))) | 1038 | (if (and (markerp python-orig-start) |
| 1025 | (list (point-marker) (if python-orig-file | 1039 | (marker-buffer python-orig-start)) |
| 1026 | (list python-orig-file default-directory) | 1040 | (with-current-buffer (marker-buffer python-orig-start) |
| 1027 | file) | 1041 | (goto-char python-orig-start) |
| 1028 | (+ line (1- python-orig-start-line)) | 1042 | (forward-line (1- line))) |
| 1029 | nil))) | 1043 | (list (if (stringp python-orig-start) python-orig-start file) |
| 1044 | line nil))))) | ||
| 1045 | |||
| 1046 | (defvar python-preoutput-result nil | ||
| 1047 | "Data from output line last `_emacs_out' line seen by the preoutput filter.") | ||
| 1048 | |||
| 1049 | (defvar python-preoutput-continuation nil | ||
| 1050 | "If non-nil, funcall this when `python-preoutput-filter' sees `_emacs_ok'.") | ||
| 1051 | |||
| 1052 | ;; Using this stops us getting lines in the buffer like | ||
| 1053 | ;; >>> ... ... >>> | ||
| 1054 | ;; Also look for (and delete) an `_emacs_ok' string and call | ||
| 1055 | ;; `python-preoutput-continuation' if we get it. | ||
| 1056 | (defun python-preoutput-filter (s) | ||
| 1057 | "`comint-preoutput-filter-functions' function: ignore prompts not at bol." | ||
| 1058 | (cond ((and (string-match "\\`[.>]\\{3\\} \\'" s) | ||
| 1059 | (/= (let ((inhibit-field-text-motion t)) | ||
| 1060 | (line-beginning-position)) | ||
| 1061 | (point))) | ||
| 1062 | "") | ||
| 1063 | ((string= s "_emacs_ok\n") | ||
| 1064 | (when python-preoutput-continuation | ||
| 1065 | (funcall python-preoutput-continuation) | ||
| 1066 | (setq python-preoutput-continuation nil)) | ||
| 1067 | "") | ||
| 1068 | ((string-match "_emacs_out \\(.*\\)\n" s) | ||
| 1069 | (setq python-preoutput-result (match-string 1 s)) | ||
| 1070 | "") | ||
| 1071 | (t s))) | ||
| 1030 | 1072 | ||
| 1031 | ;;;###autoload | 1073 | ;;;###autoload |
| 1032 | (defun run-python (cmd) | 1074 | (defun run-python (&optional cmd noshow) |
| 1033 | "Run an inferior Python process, input and output via buffer *Python*. | 1075 | "Run an inferior Python process, input and output via buffer *Python*. |
| 1034 | CMD is the Python command to run. | 1076 | CMD is the Python command to run. NOSHOW non-nil means don't show the |
| 1077 | buffer automatically. | ||
| 1035 | If there is a process already running in `*Python*', switch to | 1078 | If there is a process already running in `*Python*', switch to |
| 1036 | that buffer. With argument, allows you to edit the initial | 1079 | that buffer. Interactively a prefix arg, allows you to edit the initial |
| 1037 | command line (default is the value of `python-command'); `-i' and | 1080 | command line (default is the value of `python-command'); `-i' etc. args |
| 1038 | `-c' args will be added to this to support evaluations in the | 1081 | will be added to this as appropriate. Runs the hooks |
| 1039 | REPL. Runs the hooks `inferior-python-mode-hook' \(after the | 1082 | `inferior-python-mode-hook' (after the `comint-mode-hook' is run). |
| 1040 | `comint-mode-hook' is run). \(Type \\[describe-mode] in the | 1083 | \(Type \\[describe-mode] in the process buffer for a list of commands.)" |
| 1041 | process buffer for a list of commands.)" | ||
| 1042 | (interactive (list (if current-prefix-arg | 1084 | (interactive (list (if current-prefix-arg |
| 1043 | (read-string "Run Python: " python-command) | 1085 | (read-string "Run Python: " python-command) |
| 1044 | python-command))) | 1086 | python-command))) |
| 1087 | (unless cmd (setq cmd python-python-command)) | ||
| 1088 | (setq python-command cmd) | ||
| 1045 | ;; Fixme: Consider making `python-buffer' buffer-local as a buffer | 1089 | ;; Fixme: Consider making `python-buffer' buffer-local as a buffer |
| 1046 | ;; (not a name) in Python buffers from which `run-python' &c is | 1090 | ;; (not a name) in Python buffers from which `run-python' &c is |
| 1047 | ;; invoked. Would support multiple processes better. | 1091 | ;; invoked. Would support multiple processes better. |
| 1048 | (if (not (comint-check-proc "*Python*")) | 1092 | (unless (comint-check-proc "*Python*") |
| 1049 | (let ((cmdlist (append (python-args-to-list cmd) | 1093 | (let ((cmdlist (append (python-args-to-list cmd) '("-i")))) |
| 1050 | '("-i" "-c" "\ | 1094 | (set-buffer (apply 'make-comint "Python" (car cmdlist) nil |
| 1051 | from os import remove as _emacs_rem | 1095 | (cdr cmdlist)))) |
| 1052 | def _emacs_execfile (file): | 1096 | (inferior-python-mode) |
| 1053 | try: | 1097 | ;; Load function defintions we need. |
| 1054 | execfile (file) | 1098 | ;; Before the preoutput function was used, this was done via -c in |
| 1055 | finally: | 1099 | ;; cmdlist, but that loses the banner and doesn't run the startup |
| 1056 | _emacs_rem (file) | 1100 | ;; file. |
| 1057 | ")))) | 1101 | (python-send-string "\ |
| 1058 | (set-buffer (apply 'make-comint "Python" (car cmdlist) nil | 1102 | def _emacs_execfile (file): # execute file and remove it |
| 1059 | (cdr cmdlist))) | 1103 | from os import remove |
| 1060 | (inferior-python-mode) | 1104 | try: execfile (file, globals (), globals ()) |
| 1061 | (setq comint-output-filter-functions nil))) | 1105 | finally: remove (file) |
| 1062 | (setq python-command cmd) | 1106 | |
| 1063 | (setq python-buffer "*Python*") | 1107 | def _emacs_args (name): # get arglist of name for eldoc &c |
| 1064 | (pop-to-buffer "*Python*") | 1108 | import inspect |
| 1065 | (compilation-minor-mode 1) | 1109 | parts = name.split ('.') |
| 1066 | (add-hook 'comint-input-filter-functions 'python-input-filter nil t) | 1110 | if len (parts) > 1: |
| 1067 | ;; Avoid clobbering comint bindings. | 1111 | try: exec 'import ' + parts[0] |
| 1068 | (set (make-local-variable 'minor-mode-overriding-map-alist) | 1112 | except: return None |
| 1069 | `((compilation-minor-mode | 1113 | try: exec 'func='+name # lose if name is keyword or undefined |
| 1070 | . ,(let ((map (make-sparse-keymap))) | 1114 | except: return None |
| 1071 | ;; It would be useful to put keymap properties on the | 1115 | if inspect.isbuiltin (func): |
| 1072 | ;; error lines so that we could use RET and mouse-2 on | 1116 | doc = func.__doc__ |
| 1073 | ;; them directly. These bindings will only DTRT with | 1117 | if doc.find (' ->') != -1: |
| 1074 | ;; the font-lock-style compilation mode. | 1118 | print '_emacs_out', doc.split (' ->')[0] |
| 1075 | (define-key map [mouse-2] #'python-mouse-2-command) | 1119 | elif doc.find ('\\n') != -1: |
| 1076 | (define-key map "\C-m" #'python-RET-command) | 1120 | print '_emacs_out', doc.split ('\\n')[0] |
| 1077 | (if (boundp 'compilation-menu-map) | 1121 | return None |
| 1078 | (define-key map [menu-bar compilation] | 1122 | if inspect.ismethod (func): func = func.im_func |
| 1079 | (cons "Errors" compilation-menu-map))) | 1123 | if not inspect.isfunction (func): |
| 1080 | map)))) | 1124 | return None |
| 1081 | (set (make-local-variable 'compilation-error-regexp-alist) | 1125 | (args, varargs, varkw, defaults) = inspect.getargspec (func) |
| 1082 | python-compilation-regexp-alist)) | 1126 | print '_emacs_out', func.__name__+inspect.formatargspec (args, varargs, varkw, defaults) |
| 1083 | 1127 | ||
| 1084 | (defun python-mouse-2-command (event) | 1128 | print '_emacs_ok'")) |
| 1085 | "Command bound to `mouse-2' in inferior Python buffer. | 1129 | (unless noshow (pop-to-buffer (setq python-buffer "*Python*")))) |
| 1086 | Selects Comint or Compilation mode command as appropriate." | ||
| 1087 | (interactive "e") | ||
| 1088 | ;; This only works with the font-lock-based compilation mode. | ||
| 1089 | (call-interactively | ||
| 1090 | (lookup-key (if (save-window-excursion | ||
| 1091 | (save-excursion | ||
| 1092 | (mouse-set-point event) | ||
| 1093 | (consp (get-text-property (line-beginning-position) | ||
| 1094 | 'message)))) | ||
| 1095 | compilation-mode-map | ||
| 1096 | comint-mode-map) | ||
| 1097 | [mouse-2]))) | ||
| 1098 | |||
| 1099 | (defun python-RET-command () | ||
| 1100 | "Command bound to `RET' in inferior Python buffer. | ||
| 1101 | Selects Comint or Compilation mode command as appropriate." | ||
| 1102 | (interactive) | ||
| 1103 | ;; This only works with the font-lock-based compilation mode. | ||
| 1104 | (call-interactively | ||
| 1105 | (lookup-key (if (consp (get-text-property (line-beginning-position) | ||
| 1106 | 'message)) | ||
| 1107 | compilation-mode-map | ||
| 1108 | comint-mode-map) | ||
| 1109 | "\C-m"))) | ||
| 1110 | 1130 | ||
| 1111 | (defun python-send-region (start end) | 1131 | (defun python-send-region (start end) |
| 1112 | "Send the region to the inferior Python process." | 1132 | "Send the region to the inferior Python process." |
| @@ -1128,11 +1148,8 @@ Selects Comint or Compilation mode command as appropriate." | |||
| 1128 | ;; comint-filter the first two lines of the traceback? | 1148 | ;; comint-filter the first two lines of the traceback? |
| 1129 | (interactive "r") | 1149 | (interactive "r") |
| 1130 | (let* ((f (make-temp-file "py")) | 1150 | (let* ((f (make-temp-file "py")) |
| 1131 | (command (format "_emacs_execfile(%S)\n" f)) | 1151 | (command (format "_emacs_execfile(%S)" f)) |
| 1132 | (orig-file (buffer-file-name)) | 1152 | (orig-start (copy-marker start))) |
| 1133 | (orig-line (save-restriction | ||
| 1134 | (widen) | ||
| 1135 | (line-number-at-pos start)))) | ||
| 1136 | (if (save-excursion | 1153 | (if (save-excursion |
| 1137 | (goto-char start) | 1154 | (goto-char start) |
| 1138 | (/= 0 (current-indentation))) ; need dummy block | 1155 | (/= 0 (current-indentation))) ; need dummy block |
| @@ -1140,22 +1157,20 @@ Selects Comint or Compilation mode command as appropriate." | |||
| 1140 | (write-region start end f t 'nomsg) | 1157 | (write-region start end f t 'nomsg) |
| 1141 | (when python-buffer | 1158 | (when python-buffer |
| 1142 | (with-current-buffer python-buffer | 1159 | (with-current-buffer python-buffer |
| 1143 | (let ((end (marker-position (process-mark | 1160 | (let ((end (marker-position (process-mark (python-proc))))) |
| 1144 | (get-buffer-process python-buffer))))) | 1161 | (set (make-local-variable 'python-orig-start) orig-start) |
| 1145 | (set (make-local-variable 'python-orig-file) orig-file) | ||
| 1146 | (set (make-local-variable 'python-orig-start-line) orig-line) | ||
| 1147 | (set (make-local-variable 'compilation-error-list) nil) | 1162 | (set (make-local-variable 'compilation-error-list) nil) |
| 1148 | ;; (set (make-local-variable 'compilation-old-error-list) nil) | ||
| 1149 | (let ((comint-input-filter-functions | 1163 | (let ((comint-input-filter-functions |
| 1150 | (delete 'python-input-filter comint-input-filter-functions))) | 1164 | (delete 'python-input-filter comint-input-filter-functions))) |
| 1151 | (comint-send-string (python-proc) command)) | 1165 | (python-send-string command)) |
| 1152 | (set-marker compilation-parsing-end end) | 1166 | (set-marker compilation-parsing-end end) |
| 1153 | (setq compilation-last-buffer (current-buffer))))))) | 1167 | (setq compilation-last-buffer (current-buffer))))))) |
| 1154 | 1168 | ||
| 1155 | (defun python-send-string (string) | 1169 | (defun python-send-string (string) |
| 1156 | "Evaluate STRING in inferior Python process." | 1170 | "Evaluate STRING in inferior Python process." |
| 1157 | (interactive "sPython command: ") | 1171 | (interactive "sPython command: ") |
| 1158 | (comint-send-string (python-proc) string)) | 1172 | (comint-send-string (python-proc) string) |
| 1173 | (comint-send-string (python-proc) "\n\n")) | ||
| 1159 | 1174 | ||
| 1160 | (defun python-send-buffer () | 1175 | (defun python-send-buffer () |
| 1161 | "Send the current buffer to the inferior Python process." | 1176 | "Send the current buffer to the inferior Python process." |
| @@ -1212,19 +1227,27 @@ module-qualified names." | |||
| 1212 | (comint-check-source file-name) ; Check to see if buffer needs saved. | 1227 | (comint-check-source file-name) ; Check to see if buffer needs saved. |
| 1213 | (setq python-prev-dir/file (cons (file-name-directory file-name) | 1228 | (setq python-prev-dir/file (cons (file-name-directory file-name) |
| 1214 | (file-name-nondirectory file-name))) | 1229 | (file-name-nondirectory file-name))) |
| 1215 | (comint-send-string | 1230 | (when python-buffer |
| 1216 | (python-proc) | 1231 | (with-current-buffer python-buffer |
| 1217 | (if (string-match "\\.py\\'" file-name) | 1232 | (let ((end (marker-position (process-mark (python-proc))))) |
| 1218 | ;; Fixme: make sure the directory is in the path list | 1233 | (set (make-local-variable 'compilation-error-list) nil) |
| 1219 | (let ((module (file-name-sans-extension | 1234 | ;; (set (make-local-variable 'compilation-old-error-list) nil) |
| 1220 | (file-name-nondirectory file-name)))) | 1235 | (let ((comint-input-filter-functions |
| 1221 | (format "\ | 1236 | (delete 'python-input-filter comint-input-filter-functions))) |
| 1222 | if globals().has_key('%s'): | 1237 | (python-send-string |
| 1223 | reload(%s) | 1238 | (if (string-match "\\.py\\'" file-name) |
| 1224 | else: | 1239 | ;; Fixme: make sure the directory is in the path list |
| 1225 | import %s | 1240 | (let ((module (file-name-sans-extension |
| 1241 | (file-name-nondirectory file-name)))) | ||
| 1242 | (set (make-local-variable 'python-orig-start) nil) | ||
| 1243 | (format "\ | ||
| 1244 | if globals().has_key(%S): reload(%s) | ||
| 1245 | else: import %s | ||
| 1226 | " module module module)) | 1246 | " module module module)) |
| 1227 | (format "execfile('%s')\n" filename)))) | 1247 | (set (make-local-variable 'python-orig-start) file-name) |
| 1248 | (format "execfile('%s')" file-name)))) | ||
| 1249 | (set-marker compilation-parsing-end end) | ||
| 1250 | (setq compilation-last-buffer (current-buffer)))))) | ||
| 1228 | 1251 | ||
| 1229 | ;; Fixme: Should this start a process if there isn't one? (Unlike cmuscheme.) | 1252 | ;; Fixme: Should this start a process if there isn't one? (Unlike cmuscheme.) |
| 1230 | (defun python-proc () | 1253 | (defun python-proc () |
| @@ -1236,74 +1259,115 @@ else: | |||
| 1236 | 1259 | ||
| 1237 | ;;;; Context-sensitive help. | 1260 | ;;;; Context-sensitive help. |
| 1238 | 1261 | ||
| 1239 | ;; Fixme: Investigate adapting this to eldoc. | 1262 | (defconst python-dotty-syntax-table |
| 1263 | (let ((table (make-syntax-table))) | ||
| 1264 | (set-char-table-parent table python-mode-syntax-table) | ||
| 1265 | (modify-syntax-entry ?. "_" table) | ||
| 1266 | table) | ||
| 1267 | "Syntax table giving `.' symbol syntax. | ||
| 1268 | Otherwise inherits from `python-mode-syntax-table'.") | ||
| 1240 | 1269 | ||
| 1270 | ;; Fixme: Should this actually be used instead of info-look, i.e. be | ||
| 1271 | ;; bound to C-h S? | ||
| 1241 | (defun python-describe-symbol (symbol) | 1272 | (defun python-describe-symbol (symbol) |
| 1242 | "Get help on SYMBOL using `pydoc'. | 1273 | "Get help on SYMBOL using `pydoc'. |
| 1243 | Interactively, prompt for symbol." | 1274 | Interactively, prompt for symbol." |
| 1275 | ;; Note that we do this in the inferior process, not a separate one to | ||
| 1276 | ;; ensure the environment is appropriate. | ||
| 1244 | (interactive | 1277 | (interactive |
| 1245 | (let ((symbol (current-word)) | 1278 | (let ((symbol (with-syntax-table python-dotty-syntax-table |
| 1279 | (current-word))) | ||
| 1246 | (enable-recursive-minibuffers t) | 1280 | (enable-recursive-minibuffers t) |
| 1247 | val) | 1281 | val) |
| 1248 | (setq val (read-string (if symbol | 1282 | (setq val (read-string (if symbol |
| 1249 | (format "Describe variable (default %s): " | 1283 | (format "Describe symbol (default %s): " |
| 1250 | symbol) | 1284 | symbol) |
| 1251 | "Describe variable: ") | 1285 | "Describe symbol: ") |
| 1252 | nil nil symbol)) | 1286 | nil nil symbol)) |
| 1253 | (list (or val symbol)))) | 1287 | (list (or val symbol)))) |
| 1254 | (if (equal symbol "") (error "No symbol")) | 1288 | (if (equal symbol "") (error "No symbol")) |
| 1255 | (let* ((mod (if (string-match "\\(\\.[^.]+\\)\\'" symbol) | 1289 | (let* ((func `(lambda () |
| 1256 | (substring symbol 0 (match-beginning 1)))) | 1290 | (comint-redirect-send-command (format "help(%S)\n" ,symbol) |
| 1257 | (import (when mod (concat "import " mod "\n")))) | 1291 | "*Help*" nil)))) |
| 1258 | (with-output-to-temp-buffer "*Python Output*" | 1292 | ;; Ensure we have a suitable help buffer. |
| 1259 | (princ (shell-command-to-string | 1293 | (let (temp-buffer-show-hook) ; avoid xref stuff |
| 1260 | (format "%s -c 'import pydoc %s | 1294 | (with-output-to-temp-buffer "*Help*" |
| 1261 | try: pydoc.help(%S) | 1295 | (with-current-buffer standard-output |
| 1262 | except: print \"No help available on:\", %S'" | 1296 | (set (make-local-variable 'comint-redirect-subvert-readonly) t)))) |
| 1263 | ;; Fixme: Is this necessarily right? | 1297 | (if (and python-buffer (get-buffer python-buffer)) |
| 1264 | (car (split-string python-command)) | 1298 | (with-current-buffer python-buffer |
| 1265 | (or import "") symbol symbol)))))) | 1299 | (funcall func)) |
| 1300 | (setq python-preoutput-continuation func) | ||
| 1301 | (run-python nil t)))) | ||
| 1266 | 1302 | ||
| 1267 | (add-to-list 'debug-ignored-errors "^No symbol") | 1303 | (add-to-list 'debug-ignored-errors "^No symbol") |
| 1304 | |||
| 1305 | ;; Fixme: try to make it work with point in the arglist. Also, is | ||
| 1306 | ;; there anything reasonable we can do with random methods? | ||
| 1307 | ;; (Currently only works with functions.) | ||
| 1308 | (defun python-eldoc-function () | ||
| 1309 | "`eldoc-print-current-symbol-info' for Python. | ||
| 1310 | Only works when point is in a function name, not its arglist, for instance. | ||
| 1311 | Assumes an inferior Python is running." | ||
| 1312 | (let ((symbol (with-syntax-table python-dotty-syntax-table | ||
| 1313 | (current-word))) | ||
| 1314 | (proc (and python-buffer (python-proc)))) | ||
| 1315 | (when (and proc symbol) | ||
| 1316 | (python-send-string | ||
| 1317 | (format "_emacs_args(%S)" symbol)) | ||
| 1318 | (setq python-preoutput-result nil) | ||
| 1319 | (accept-process-output proc 1) | ||
| 1320 | python-preoutput-result))) | ||
| 1268 | 1321 | ||
| 1269 | ;;;; Info-look functionality. | 1322 | ;;;; Info-look functionality. |
| 1270 | 1323 | ||
| 1271 | (require 'info-look) | 1324 | (defun python-after-info-look () |
| 1272 | ;; We should be able to add info-lookup specs without loading the file first. | 1325 | "Set up info-look for Python. |
| 1273 | ;; E.g. by setting a buffer-local var or something like that. --Stef | 1326 | Used with `eval-after-load'." |
| 1274 | (let ((version (let ((s (shell-command-to-string (concat python-command | 1327 | (let* ((version (let ((s (shell-command-to-string (concat python-command |
| 1275 | " -V")))) | 1328 | " -V")))) |
| 1276 | (string-match "^Python \\([0-9]+\\.[0-9]+\\>\\)" s) | 1329 | (string-match "^Python \\([0-9]+\\.[0-9]+\\>\\)" s) |
| 1277 | (match-string 1 s))) | 1330 | (match-string 1 s))) |
| 1278 | ;; Whether info files have a Python version suffix, e.g. in Debian. | 1331 | ;; Whether info files have a Python version suffix, e.g. in Debian. |
| 1279 | (versioned (save-window-excursion | 1332 | (versioned |
| 1280 | (condition-case () | 1333 | (with-temp-buffer |
| 1281 | ;; The call to `info' might create a new frame if | 1334 | (Info-mode) |
| 1282 | ;; pop-up-frames or special-display-buffers are used. | 1335 | (condition-case () |
| 1283 | ;; So I disabled it until we find a better way | 1336 | ;; Don't use `info' because it would pop-up a *info* buffer. |
| 1284 | ;; to handle this situation. Maybe Debian should just | 1337 | (Info-goto-node (format "(python%s-lib)Miscellaneous Index" |
| 1285 | ;; fix their install somehow. --Stef | 1338 | version)) |
| 1286 | ;; (progn (info "(python2.3-lib)Miscellaneous Index") | 1339 | (error nil))))) |
| 1287 | ;; (Info-last) | 1340 | (info-lookup-maybe-add-help |
| 1288 | ;; (Info-exit) | 1341 | :mode 'python-mode |
| 1289 | ;; t) | 1342 | :regexp "[[:alnum:]_]+" |
| 1290 | nil | 1343 | :doc-spec |
| 1291 | (error nil))))) | 1344 | ;; Fixme: Can this reasonably be made specific to indices with |
| 1292 | (info-lookup-maybe-add-help | 1345 | ;; different rules? Is the order of indices optimal? |
| 1293 | :mode 'python-mode | 1346 | ;; (Miscellaneous in -ref first prefers lookup of keywords, for |
| 1294 | :regexp "[[:alnum:]_]+" | 1347 | ;; instance.) |
| 1295 | :doc-spec | 1348 | (if versioned |
| 1296 | ;; Fixme: Add python-ref? Can this reasonably be made specific | 1349 | ;; The empty prefix just gets us highlighted terms. |
| 1297 | ;; to indices with different rules? | 1350 | `((,(concat "(python" version "-ref)Miscellaneous Index") nil "") |
| 1298 | (if versioned | 1351 | (,(concat "(python" version "-ref)Module Index" nil "")) |
| 1299 | '((,(concat "(python" version "-lib)Module Index")) | 1352 | (,(concat "(python" version "-ref)Function-Method-Variable Index" |
| 1300 | (,(concat "(python" version "-lib)Class-Exception-Object Index")) | 1353 | nil "")) |
| 1301 | (,(concat "(python" version "-lib)Function-Method-Variable Index")) | 1354 | (,(concat "(python" version "-ref)Class-Exception-Object Index" |
| 1302 | (,(concat "(python" version "-lib)Miscellaneous Index"))) | 1355 | nil "")) |
| 1303 | '(("(python-lib)Module Index") | 1356 | (,(concat "(python" version "-lib)Module Index" nil "")) |
| 1304 | ("(python-lib)Class-Exception-Object Index") | 1357 | (,(concat "(python" version "-lib)Class-Exception-Object Index" |
| 1305 | ("(python-lib)Function-Method-Variable Index") | 1358 | nil "")) |
| 1306 | ("(python-lib)Miscellaneous Index"))))) | 1359 | (,(concat "(python" version "-lib)Function-Method-Variable Index" |
| 1360 | nil "")) | ||
| 1361 | (,(concat "(python" version "-lib)Miscellaneous Index" nil ""))) | ||
| 1362 | '(("(python-ref)Miscellaneous Index" nil "") | ||
| 1363 | ("(python-ref)Module Index" nil "") | ||
| 1364 | ("(python-ref)Function-Method-Variable Index" nil "") | ||
| 1365 | ("(python-ref)Class-Exception-Object Index" nil "") | ||
| 1366 | ("(python-lib)Module Index" nil "") | ||
| 1367 | ("(python-lib)Class-Exception-Object Index" nil "") | ||
| 1368 | ("(python-lib)Function-Method-Variable Index" nil "") | ||
| 1369 | ("(python-lib)Miscellaneous Index" nil "")))))) | ||
| 1370 | (eval-after-load "info-look" '(python-after-info-look)) | ||
| 1307 | 1371 | ||
| 1308 | ;;;; Miscellancy. | 1372 | ;;;; Miscellancy. |
| 1309 | 1373 | ||
| @@ -1323,34 +1387,65 @@ The criterion is either a match for `jython-mode' via | |||
| 1323 | `python-jython-packages'." | 1387 | `python-jython-packages'." |
| 1324 | ;; The logic is taken from python-mode.el. | 1388 | ;; The logic is taken from python-mode.el. |
| 1325 | (save-excursion | 1389 | (save-excursion |
| 1326 | (goto-char (point-min)) | 1390 | (save-restriction |
| 1327 | (let ((interpreter (if (looking-at auto-mode-interpreter-regexp) | 1391 | (widen) |
| 1328 | (match-string 2)))) | 1392 | (goto-char (point-min)) |
| 1329 | (if (and interpreter (eq 'jython-mode | 1393 | (let ((interpreter (if (looking-at auto-mode-interpreter-regexp) |
| 1330 | (cdr (assoc (file-name-nondirectory interpreter) | 1394 | (match-string 2)))) |
| 1331 | interpreter-mode-alist)))) | 1395 | (if (and interpreter (eq 'jython-mode |
| 1332 | (jython-mode) | 1396 | (cdr (assoc (file-name-nondirectory |
| 1333 | (if (catch 'done | 1397 | interpreter) |
| 1334 | (while (re-search-forward | 1398 | interpreter-mode-alist)))) |
| 1335 | (rx (and line-start (or "import" "from") (1+ space) | 1399 | (jython-mode) |
| 1336 | (group (1+ (not (any " \t\n.")))))) | 1400 | (if (catch 'done |
| 1337 | (+ (point) 10000) ; Probably not worth customizing. | 1401 | (while (re-search-forward |
| 1338 | t) | 1402 | (rx (and line-start (or "import" "from") (1+ space) |
| 1339 | (if (member (match-string 1) python-jython-packages) | 1403 | (group (1+ (not (any " \t\n.")))))) |
| 1340 | (throw 'done t)))) | 1404 | 10000 ; Probably not worth customizing. |
| 1341 | (jython-mode)))))) | 1405 | t) |
| 1406 | (if (member (match-string 1) python-jython-packages) | ||
| 1407 | (throw 'done t)))) | ||
| 1408 | (jython-mode))))))) | ||
| 1342 | 1409 | ||
| 1343 | (defun python-fill-paragraph (&optional justify) | 1410 | (defun python-fill-paragraph (&optional justify) |
| 1344 | "Like \\[fill-paragraph], but handle comments and multi-line strings. | 1411 | "`fill-paragraph-function' handling comments and multi-line strings. |
| 1345 | If any of the current line is a comment, fill the comment or the | 1412 | If any of the current line is a comment, fill the comment or the |
| 1346 | paragraph of it that point is in, preserving the comment's indentation | 1413 | paragraph of it that point is in, preserving the comment's |
| 1347 | and initial comment characters." | 1414 | indentation and initial comment characters. Similarly if the end |
| 1415 | of the current line is in or at the end of a multi-line string. | ||
| 1416 | Otherwise, do nothing." | ||
| 1348 | (interactive "P") | 1417 | (interactive "P") |
| 1349 | (or (fill-comment-paragraph justify) | 1418 | (or (fill-comment-paragraph justify) |
| 1350 | (let ((paragraph-start (concat paragraph-start | 1419 | ;; The `paragraph-start' and `paragraph-separate' variables |
| 1351 | "\\|\\s-*\\(:?#\\s\"\\|\\s|\\|#"))) | 1420 | ;; don't allow us to delimit the last paragraph in a multi-line |
| 1352 | (fill-paragraph justify)) | 1421 | ;; string properly, so narrow to the string and then fill around |
| 1353 | t)) | 1422 | ;; (the end of) the current line. |
| 1423 | (save-excursion | ||
| 1424 | (end-of-line) | ||
| 1425 | (let* ((syntax (syntax-ppss)) | ||
| 1426 | (orig (point)) | ||
| 1427 | (start (nth 8 syntax)) | ||
| 1428 | end) | ||
| 1429 | (cond ((eq t (nth 3 syntax)) ; in fenced string | ||
| 1430 | (goto-char (nth 8 syntax)) ; string start | ||
| 1431 | (condition-case () ; for unbalanced quotes | ||
| 1432 | (progn (forward-sexp) | ||
| 1433 | (setq end (point))) | ||
| 1434 | (error (setq end (point-max))))) | ||
| 1435 | ((re-search-backward "\\s|\\s-*\\=" nil t) ; end of fenced | ||
| 1436 | ; string | ||
| 1437 | (forward-char) | ||
| 1438 | (setq end (point)) | ||
| 1439 | (condition-case () | ||
| 1440 | (progn (backward-sexp) | ||
| 1441 | (setq start (point))) | ||
| 1442 | (error nil)))) | ||
| 1443 | (when end | ||
| 1444 | (save-restriction | ||
| 1445 | (narrow-to-region start end) | ||
| 1446 | (goto-char orig) | ||
| 1447 | (fill-paragraph justify)))))) | ||
| 1448 | t) | ||
| 1354 | 1449 | ||
| 1355 | (defun python-shift-left (start end &optional count) | 1450 | (defun python-shift-left (start end &optional count) |
| 1356 | "Shift lines in region COUNT (the prefix arg) columns to the left. | 1451 | "Shift lines in region COUNT (the prefix arg) columns to the left. |
| @@ -1391,7 +1486,8 @@ END lie." | |||
| 1391 | 1486 | ||
| 1392 | (defun python-outline-level () | 1487 | (defun python-outline-level () |
| 1393 | "`outline-level' function for Python mode. | 1488 | "`outline-level' function for Python mode. |
| 1394 | The level is the number of `python-indent' steps of indentation." | 1489 | The level is the number of `python-indent' steps of indentation |
| 1490 | of current line." | ||
| 1395 | (/ (current-indentation) python-indent)) | 1491 | (/ (current-indentation) python-indent)) |
| 1396 | 1492 | ||
| 1397 | ;; Fixme: Consider top-level assignments, imports, &c. | 1493 | ;; Fixme: Consider top-level assignments, imports, &c. |
| @@ -1425,17 +1521,23 @@ Uses `python-beginning-of-block', `python-end-of-block'." | |||
| 1425 | 1521 | ||
| 1426 | ;;;; Modes. | 1522 | ;;;; Modes. |
| 1427 | 1523 | ||
| 1524 | (defvar outline-heading-end-regexp) | ||
| 1525 | (defvar eldoc-print-current-symbol-info-function) | ||
| 1526 | (defvar python-mode-running) | ||
| 1428 | ;;;###autoload | 1527 | ;;;###autoload |
| 1429 | (define-derived-mode python-mode fundamental-mode "Python" | 1528 | (define-derived-mode python-mode fundamental-mode "Python" |
| 1430 | "Major mode for editing Python files. | 1529 | "Major mode for editing Python files. |
| 1431 | Turns on Font Lock mode unconditionally since it is required for correct | 1530 | Turns on Font Lock mode unconditionally since it is required for correct |
| 1432 | parsing of the source. | 1531 | parsing of the source. |
| 1433 | See also `jython-mode', which is actually invoked if the buffer appears to | 1532 | See also `jython-mode', which is actually invoked if the buffer appears to |
| 1434 | contain Jython code. | 1533 | contain Jython code. See also `run-python' and associated Python mode |
| 1534 | commands for running Python under Emacs. | ||
| 1435 | 1535 | ||
| 1436 | The Emacs commands which work with `defun's, e.g. \\[beginning-of-defun], deal | 1536 | The Emacs commands which work with `defun's, e.g. \\[beginning-of-defun], deal |
| 1437 | with nested `def' and `class' blocks. They take the innermost one as | 1537 | with nested `def' and `class' blocks. They take the innermost one as |
| 1438 | current without distinguishing method and class definitions. | 1538 | current without distinguishing method and class definitions. Used multiple |
| 1539 | times, they move over others at the same indentation level until they reach | ||
| 1540 | the end of definitions at that level, when they move up a level. | ||
| 1439 | \\<python-mode-map> | 1541 | \\<python-mode-map> |
| 1440 | Colon is electric: it outdents the line if appropriate, e.g. for | 1542 | Colon is electric: it outdents the line if appropriate, e.g. for |
| 1441 | an else statement. \\[python-backspace] at the beginning of an indented statement | 1543 | an else statement. \\[python-backspace] at the beginning of an indented statement |
| @@ -1444,6 +1546,13 @@ deletes a charcter backward. TAB indents the current line relative to | |||
| 1444 | the preceding code. Successive TABs, with no intervening command, cycle | 1546 | the preceding code. Successive TABs, with no intervening command, cycle |
| 1445 | through the possibilities for indentation on the basis of enclosing blocks. | 1547 | through the possibilities for indentation on the basis of enclosing blocks. |
| 1446 | 1548 | ||
| 1549 | \\[fill-paragraph] fills comments and multiline strings appropriately, but has no | ||
| 1550 | effect outside them. | ||
| 1551 | |||
| 1552 | Supports Eldoc mode (only for functions, using a Python process), | ||
| 1553 | Info-Look and Imenu. In Outline minor mode, `class' and `def' | ||
| 1554 | lines count as headers. | ||
| 1555 | |||
| 1447 | \\{python-mode-map}" | 1556 | \\{python-mode-map}" |
| 1448 | :group 'python | 1557 | :group 'python |
| 1449 | (set (make-local-variable 'font-lock-defaults) | 1558 | (set (make-local-variable 'font-lock-defaults) |
| @@ -1465,7 +1574,8 @@ through the possibilities for indentation on the basis of enclosing blocks. | |||
| 1465 | (set (make-local-variable 'add-log-current-defun-function) | 1574 | (set (make-local-variable 'add-log-current-defun-function) |
| 1466 | #'python-current-defun) | 1575 | #'python-current-defun) |
| 1467 | ;; Fixme: Generalize to do all blocks? | 1576 | ;; Fixme: Generalize to do all blocks? |
| 1468 | (set (make-local-variable 'outline-regexp) "\\s-+\\(def\\|class\\)\\>") | 1577 | (set (make-local-variable 'outline-regexp) "\\s-*\\(def\\|class\\)\\>") |
| 1578 | (set (make-local-variable 'outline-heading-end-regexp) ":\\s-*\n") | ||
| 1469 | (set (make-local-variable 'outline-level) #'python-outline-level) | 1579 | (set (make-local-variable 'outline-level) #'python-outline-level) |
| 1470 | (set (make-local-variable 'open-paren-in-column-0-is-defun-start) nil) | 1580 | (set (make-local-variable 'open-paren-in-column-0-is-defun-start) nil) |
| 1471 | (make-local-variable 'python-saved-check-command) | 1581 | (make-local-variable 'python-saved-check-command) |
| @@ -1473,6 +1583,10 @@ through the possibilities for indentation on the basis of enclosing blocks. | |||
| 1473 | 'python-beginning-of-defun) | 1583 | 'python-beginning-of-defun) |
| 1474 | (set (make-local-variable 'end-of-defun-function) 'python-end-of-defun) | 1584 | (set (make-local-variable 'end-of-defun-function) 'python-end-of-defun) |
| 1475 | (setq imenu-create-index-function #'python-imenu-create-index) | 1585 | (setq imenu-create-index-function #'python-imenu-create-index) |
| 1586 | (set (make-local-variable 'eldoc-print-current-symbol-info-function) | ||
| 1587 | #'python-eldoc-function) | ||
| 1588 | (add-hook 'eldoc-mode-hook | ||
| 1589 | '(lambda () (run-python 0 t)) nil t) ; need it running | ||
| 1476 | (unless font-lock-mode (font-lock-mode 1)) | 1590 | (unless font-lock-mode (font-lock-mode 1)) |
| 1477 | (when python-guess-indent (python-guess-indent)) | 1591 | (when python-guess-indent (python-guess-indent)) |
| 1478 | (set (make-local-variable 'python-command) python-python-command) | 1592 | (set (make-local-variable 'python-command) python-python-command) |
| @@ -1485,6 +1599,7 @@ through the possibilities for indentation on the basis of enclosing blocks. | |||
| 1485 | '(lambda () | 1599 | '(lambda () |
| 1486 | "Turn on Indent Tabs mode." | 1600 | "Turn on Indent Tabs mode." |
| 1487 | (set (make-local-variable 'indent-tabs-mode) t))) | 1601 | (set (make-local-variable 'indent-tabs-mode) t))) |
| 1602 | (custom-add-option 'python-mode-hook 'turn-on-eldoc-mode) | ||
| 1488 | 1603 | ||
| 1489 | ;;;###autoload | 1604 | ;;;###autoload |
| 1490 | (define-derived-mode jython-mode python-mode "Jython" | 1605 | (define-derived-mode jython-mode python-mode "Jython" |