aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorStefan Monnier2004-05-06 20:22:32 +0000
committerStefan Monnier2004-05-06 20:22:32 +0000
commit24d5055ceff11f10a900637af1e193f798dfec04 (patch)
treeb395b021d894220d7ee1d7fba2e035e12e3c4603 /lisp/progmodes/python.el
parent70646bb5c52df1a9e1036c568bb372c039eaab26 (diff)
downloademacs-24d5055ceff11f10a900637af1e193f798dfec04.tar.gz
emacs-24d5055ceff11f10a900637af1e193f798dfec04.zip
Changes largely merged in from Dave Love's code. Doc fixes.
(python-mode-map): Add python-complete-symbol. (python-comment-line-p, python-beginning-of-string): Use syntax-ppss. (python-comment-indent, python-complete-symbol) (python-symbol-completions, python-partial-symbol) (python-try-complete): New. (python-indent-line): Remove optional arg. Use python-block-end-p. (python-check): Bind compilation-error-regexp-alist. (inferior-python-mode): Use rx. Move keybindings to top level. Set comint-input-filter. (python-preoutput-filter): Use rx. (python-input-filter): Re-introduce. (python-proc): Start new process if necessary. Check python-buffer non-nil. (view-return-to-alist): Defvar. (python-send-receive): New. (python-eldoc-function): Use it. (python-mode-running): Don't defvar. (python-mode): Set comment-indent-function. Maybe update hippie-expand-try-functions-list. (python-indentation-levels): Initialize differently. (python-block-end-p): New. (python-indent-line): Use it. (python-compilation-regexp-alist): Augment. (run-python): Import `emacs' module to Python rather than loading code directly. Set python-buffer differently. (python-send-region): Use emacs.eexecfile. Fix orig-start calculation. Use python-proc. (python-send-command): Go to end of comint buffer. (python-load-file): Use python-proc, emacs.eimport. (python-describe-symbol): Simplify interactive form. Use emacs.help. Do use temp-buffer-show-hook. Call print-help-return-message. (hippie-exp): Require when compiling. (python-preoutput-continuation): Use rx.
Diffstat (limited to 'lisp/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el422
1 files changed, 293 insertions, 129 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 844bd86174e..0fdaf652e50 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -46,19 +46,18 @@
46;; I've installed a minor mode to do the job properly in Emacs 22. 46;; I've installed a minor mode to do the job properly in Emacs 22.
47;; Other things seem more natural or canonical here, e.g. the 47;; Other things seem more natural or canonical here, e.g. the
48;; {beginning,end}-of-defun implementation dealing with nested 48;; {beginning,end}-of-defun implementation dealing with nested
49;; definitions, and the inferior mode following `cmuscheme'. (The 49;; definitions, and the inferior mode following `cmuscheme'. The
50;; inferior mode should be able to find the source of errors from 50;; inferior mode can find the source of errors from
51;; `python-send-region' & al via `compilation-minor-mode', but I can't 51;; `python-send-region' & al via `compilation-minor-mode'. Successive
52;; make that work with the current (March '04) compile.el.) 52;; TABs cycle between possible indentations for the line. There is
53;; Successive TABs cycle between possible indentations for the line. 53;; symbol completion using lookup in Python.
54 54
55;; Even where it has similar facilities, this is incompatible with 55;; Even where it has similar facilities, this is incompatible with
56;; python-mode.el in various respects. For instance, various key 56;; python-mode.el in various respects. For instance, various key
57;; bindings are changed to obey Emacs conventions, and things like 57;; bindings are changed to obey Emacs conventions, and things like
58;; marking blocks and `beginning-of-defun' behave differently. 58;; marking blocks and `beginning-of-defun' behave differently.
59 59
60;; TODO: See various Fixmes below. It should be possible to arrange 60;; TODO: See various Fixmes below.
61;; some sort of completion using the inferior interpreter.
62 61
63;;; Code: 62;;; Code:
64 63
@@ -203,6 +202,8 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
203 (define-key map "\C-c\C-z" 'python-switch-to-python) 202 (define-key map "\C-c\C-z" 'python-switch-to-python)
204 (define-key map "\C-c\C-m" 'python-load-file) 203 (define-key map "\C-c\C-m" 'python-load-file)
205 (define-key map "\C-c\C-l" 'python-load-file) ; a la cmuscheme 204 (define-key map "\C-c\C-l" 'python-load-file) ; a la cmuscheme
205 (substitute-key-definition 'complete-symbol 'python-complete-symbol
206 map global-map)
206 ;; Fixme: Add :help to menu. 207 ;; Fixme: Add :help to menu.
207 (easy-menu-define python-menu map "Python Mode menu" 208 (easy-menu-define python-menu map "Python Mode menu"
208 '("Python" 209 '("Python"
@@ -261,9 +262,7 @@ Used for syntactic keywords. N is the match number (1, 2 or 3)."
261;;;; Utility stuff 262;;;; Utility stuff
262 263
263(defsubst python-in-string/comment () 264(defsubst python-in-string/comment ()
264 "Return non-nil if point is in a Python literal (a comment or string). 265 "Return non-nil if point is in a Python literal (a comment or string)."
265Optional argument LIM indicates the beginning of the containing form,
266i.e. the limit on how far back to scan."
267 (syntax-ppss-context (syntax-ppss))) 266 (syntax-ppss-context (syntax-ppss)))
268 267
269(defconst python-space-backslash-table 268(defconst python-space-backslash-table
@@ -300,14 +299,17 @@ comments and strings, or that the bracket/paren nesting depth is nonzero."
300(defun python-comment-line-p () 299(defun python-comment-line-p ()
301 "Return non-nil if current line has only a comment or is blank." 300 "Return non-nil if current line has only a comment or is blank."
302 (save-excursion 301 (save-excursion
303 (back-to-indentation) 302 (end-of-line)
304 (looking-at (rx (or (syntax comment-start) line-end))))) 303 ;; FIXME: This looks wrong because it returns nil for empty lines. --Stef
304 (when (eq 'comment (syntax-ppss-context (syntax-ppss)))
305 (back-to-indentation)
306 (looking-at (rx (or (syntax comment-start) line-end))))))
305 307
306(defun python-beginning-of-string () 308(defun python-beginning-of-string ()
307 "Go to beginning of string around point. 309 "Go to beginning of string around point.
308Do nothing if not in string." 310Do nothing if not in string."
309 (let ((state (syntax-ppss))) 311 (let ((state (syntax-ppss)))
310 (when (nth 3 state) 312 (when (eq 'string (syntax-ppss-context state))
311 (goto-char (nth 8 state))))) 313 (goto-char (nth 8 state)))))
312 314
313(defun python-open-block-statement-p (&optional bos) 315(defun python-open-block-statement-p (&optional bos)
@@ -383,7 +385,8 @@ Otherwise indent them to column zero."
383(defcustom python-honour-comment-indentation nil 385(defcustom python-honour-comment-indentation nil
384 "Non-nil means indent relative to preceding comment line. 386 "Non-nil means indent relative to preceding comment line.
385Only do this for comments where the leading comment character is followed 387Only do this for comments where the leading comment character is followed
386by space." 388by space. This doesn't apply to comment lines, which are always indented
389in lines with preceding comments."
387 :type 'boolean 390 :type 'boolean
388 :group 'python) 391 :group 'python)
389 392
@@ -513,6 +516,16 @@ Set `python-indent' locally to the value guessed."
513 (- python-indent))) 516 (- python-indent)))
514 0))))))))) 517 0)))))))))
515 518
519(defun python-comment-indent ()
520 "`comment-indent-function' for Python."
521 ;; If previous non-blank line was a comment, use its indentation.
522 ;; FIXME: This seems unnecessary since the default code delegates to
523 ;; indent-according-to-mode. --Stef
524 (unless (bobp)
525 (save-excursion
526 (forward-comment -1)
527 (if (eq ?# (char-after)) (current-column)))))
528
516;;;; Cycling through the possible indentations with successive TABs. 529;;;; Cycling through the possible indentations with successive TABs.
517 530
518;; These don't need to be buffer-local since they're only relevant 531;; These don't need to be buffer-local since they're only relevant
@@ -537,11 +550,17 @@ Set `python-indent' locally to the value guessed."
537 (point)))) 550 (point))))
538 551
539(defun python-indentation-levels () 552(defun python-indentation-levels ()
540 "Return a list of possible indentations for this statement. 553 "Return a list of possible indentations for this line.
541Includes the default indentation and those which would close all 554Includes the default indentation and those which would close all
542enclosing blocks." 555enclosing blocks. Assumes the line has already been indented per
556`python-indent-line'. Elements of the list are actually pairs:
557\(INDENTATION . TEXT), where TEXT is the initial text of the
558corresponding block opening (or nil)."
543 (save-excursion 559 (save-excursion
544 (let ((levels (list (cons (current-indentation) nil)))) 560 (let ((levels (list (cons (current-indentation)
561 (save-excursion
562 (if (python-beginning-of-block)
563 (python-initial-text)))))))
545 ;; Only one possibility if we immediately follow a block open or 564 ;; Only one possibility if we immediately follow a block open or
546 ;; are in a continuation line. 565 ;; are in a continuation line.
547 (unless (or (python-continuation-line-p) 566 (unless (or (python-continuation-line-p)
@@ -567,8 +586,7 @@ enclosing blocks."
567 (if (> (- (point-max) pos) (point)) 586 (if (> (- (point-max) pos) (point))
568 (goto-char (- (point-max) pos)))))) 587 (goto-char (- (point-max) pos))))))
569 588
570;; Fixme: Is the arg necessary? 589(defun python-indent-line ()
571(defun python-indent-line (&optional arg)
572 "Indent current line as Python code. 590 "Indent current line as Python code.
573When invoked via `indent-for-tab-command', cycle through possible 591When invoked via `indent-for-tab-command', cycle through possible
574indentations for current line. The cycle is broken by a command different 592indentations for current line. The cycle is broken by a command different
@@ -585,13 +603,30 @@ from `indent-for-tab-command', i.e. successive TABs do the cycling."
585 (beginning-of-line) 603 (beginning-of-line)
586 (delete-horizontal-space) 604 (delete-horizontal-space)
587 (indent-to (car (nth python-indent-index python-indent-list))) 605 (indent-to (car (nth python-indent-index python-indent-list)))
588 (let ((text (cdr (nth python-indent-index 606 (if (python-block-end-p)
589 python-indent-list)))) 607 (let ((text (cdr (nth python-indent-index
590 (if text (message "Closes: %s" text))))) 608 python-indent-list))))
609 (if text
610 (message "Closes: %s" text))))))
591 (python-indent-line-1) 611 (python-indent-line-1)
592 (setq python-indent-list (python-indentation-levels) 612 (setq python-indent-list (python-indentation-levels)
593 python-indent-list-length (length python-indent-list) 613 python-indent-list-length (length python-indent-list)
594 python-indent-index (1- python-indent-list-length))))) 614 python-indent-index (1- python-indent-list-length)))))
615
616(defun python-block-end-p ()
617 "Non-nil if this is a line in a statement closing a block,
618or a blank line indented to where it would close a block."
619 (and (not (python-comment-line-p))
620 (or (python-close-block-statement-p t)
621 (< (current-indentation)
622 (save-excursion
623 (python-previous-statement)
624 (current-indentation))))))
625
626;; Fixme: Define an indent-region-function. It should probably leave
627;; lines alone if the indentation is already at one of the allowed
628;; levels. Otherwise, M-C-\ typically keeps indenting more deeply
629;; down a function.
595 630
596;;;; Movement. 631;;;; Movement.
597 632
@@ -628,8 +663,7 @@ start of buffer."
628 "`end-of-defun-function' for Python. 663 "`end-of-defun-function' for Python.
629Finds end of innermost nested class or method definition." 664Finds end of innermost nested class or method definition."
630 (let ((orig (point)) 665 (let ((orig (point))
631 (pattern (rx (and line-start (0+ space) 666 (pattern (rx (and line-start (0+ space) (or "def" "class") space))))
632 (or "def" "class") space))))
633 ;; Go to start of current block and check whether it's at top 667 ;; Go to start of current block and check whether it's at top
634 ;; level. If it is, and not a block start, look forward for 668 ;; level. If it is, and not a block start, look forward for
635 ;; definition statement. 669 ;; definition statement.
@@ -914,13 +948,20 @@ See `python-check-command' for the default."
914 (file-name-nondirectory name)))))))) 948 (file-name-nondirectory name))))))))
915 (setq python-saved-check-command command) 949 (setq python-saved-check-command command)
916 (save-some-buffers (not compilation-ask-about-save) nil) 950 (save-some-buffers (not compilation-ask-about-save) nil)
917 (compilation-start command)) 951 (let ((compilation-error-regexp-alist
952 (cons '("(\\([^,]+\\), line \\([0-9]+\\))" 1 2)
953 compilation-error-regexp-alist)))
954 (compilation-start command)))
918 955
919;;;; Inferior mode stuff (following cmuscheme). 956;;;; Inferior mode stuff (following cmuscheme).
920 957
958;; Fixme: Make sure we can work with IPython.
959
921(defcustom python-python-command "python" 960(defcustom python-python-command "python"
922 "*Shell command to run Python interpreter. 961 "*Shell command to run Python interpreter.
923Any arguments can't contain whitespace." 962Any arguments can't contain whitespace.
963Note that IPython may not work properly; it must at least be used with the
964`-cl' flag, i.e. use `ipython -cl'."
924 :group 'python 965 :group 'python
925 :type 'string) 966 :type 'string)
926 967
@@ -970,13 +1011,31 @@ et al.")
970 ) 1011 )
971 1012
972(defconst python-compilation-regexp-alist 1013(defconst python-compilation-regexp-alist
973 ;; FIXME: maybe this should be moved to compilation-error-regexp-alist-alist. 1014 ;; FIXME: maybe these should move to compilation-error-regexp-alist-alist.
974 `((,(rx (and line-start (1+ (any " \t")) "File \"" 1015 `((,(rx (and line-start (1+ (any " \t")) "File \""
975 (group (1+ (not (any "\"<")))) ; avoid `<stdin>' &c 1016 (group (1+ (not (any "\"<")))) ; avoid `<stdin>' &c
976 "\", line " (group (1+ digit)))) 1017 "\", line " (group (1+ digit))))
1018 1 2)
1019 (,(rx (and " in file " (group (1+ not-newline)) " on line "
1020 (group (1+ digit))))
977 1 2)) 1021 1 2))
978 "`compilation-error-regexp-alist' for inferior Python.") 1022 "`compilation-error-regexp-alist' for inferior Python.")
979 1023
1024(defvar inferior-python-mode-map
1025 (let ((map (make-sparse-keymap)))
1026 ;; This will inherit from comint-mode-map.
1027 (define-key map "\C-c\C-l" 'python-load-file)
1028 (define-key map "\C-c\C-z" 'python-switch-to-python) ;What for? --Stef
1029 (define-key map "\C-c\C-v" 'python-check)
1030 ;; Note that we _can_ still use these commands which send to the
1031 ;; Python process even at the prompt iff we have a normal prompt,
1032 ;; i.e. '>>> ' and not '... '. See the comment before
1033 ;; python-send-region. Fixme: uncomment these if we address that.
1034
1035 ;; (define-key map [(meta ?\t)] 'python-complete-symbol)
1036 ;; (define-key map "\C-c\C-f" 'python-describe-symbol)
1037 map))
1038
980;; Fixme: This should inherit some stuff from python-mode, but I'm not 1039;; Fixme: This should inherit some stuff from python-mode, but I'm not
981;; sure how much: at least some keybindings, like C-c C-f; syntax?; 1040;; sure how much: at least some keybindings, like C-c C-f; syntax?;
982;; font-locking, e.g. for triple-quoted strings? 1041;; font-locking, e.g. for triple-quoted strings?
@@ -1000,14 +1059,13 @@ For running multiple processes in multiple buffers, see `python-buffer'.
1000 :group 'python 1059 :group 'python
1001 (set-syntax-table python-mode-syntax-table) 1060 (set-syntax-table python-mode-syntax-table)
1002 (setq mode-line-process '(":%s")) 1061 (setq mode-line-process '(":%s"))
1003 ;; Fixme: Maybe install some python-mode bindings too. 1062 (set (make-local-variable 'comint-input-filter) 'python-input-filter)
1004 (define-key inferior-python-mode-map "\C-c\C-l" 'python-load-file)
1005 (define-key inferior-python-mode-map "\C-c\C-z" 'python-switch-to-python)
1006 (add-hook 'comint-preoutput-filter-functions #'python-preoutput-filter 1063 (add-hook 'comint-preoutput-filter-functions #'python-preoutput-filter
1007 nil t) 1064 nil t)
1008 ;; Still required by `comint-redirect-send-command', for instance 1065 ;; Still required by `comint-redirect-send-command', for instance
1009 ;; (and we need to match things like `>>> ... >>> '): 1066 ;; (and we need to match things like `>>> ... >>> '):
1010 (set (make-local-variable 'comint-prompt-regexp) "^\\([>.]\\{3\\} \\)+") 1067 (set (make-local-variable 'comint-prompt-regexp)
1068 (rx (and line-start (1+ (and (repeat 3 (any ">.")) ?\ )))))
1011 (set (make-local-variable 'compilation-error-regexp-alist) 1069 (set (make-local-variable 'compilation-error-regexp-alist)
1012 python-compilation-regexp-alist) 1070 python-compilation-regexp-alist)
1013 (compilation-shell-minor-mode 1)) 1071 (compilation-shell-minor-mode 1))
@@ -1018,6 +1076,11 @@ Default ignores all inputs of 0, 1, or 2 non-blank characters."
1018 :type 'regexp 1076 :type 'regexp
1019 :group 'python) 1077 :group 'python)
1020 1078
1079(defun python-input-filter (str)
1080 "`comint-input-filter' function for inferior Python.
1081Don't save anything for STR matching `inferior-python-filter-regexp'."
1082 (not (string-match inferior-python-filter-regexp str)))
1083
1021;; Fixme: Loses with quoted whitespace. 1084;; Fixme: Loses with quoted whitespace.
1022(defun python-args-to-list (string) 1085(defun python-args-to-list (string)
1023 (let ((where (string-match "[ \t]" string))) 1086 (let ((where (string-match "[ \t]" string)))
@@ -1029,7 +1092,7 @@ Default ignores all inputs of 0, 1, or 2 non-blank characters."
1029 (if pos (python-args-to-list (substring string pos)))))))) 1092 (if pos (python-args-to-list (substring string pos))))))))
1030 1093
1031(defvar python-preoutput-result nil 1094(defvar python-preoutput-result nil
1032 "Data from output line last `_emacs_out' line seen by the preoutput filter.") 1095 "Data from last `_emacs_out' line seen by the preoutput filter.")
1033 1096
1034(defvar python-preoutput-continuation nil 1097(defvar python-preoutput-continuation nil
1035 "If non-nil, funcall this when `python-preoutput-filter' sees `_emacs_ok'.") 1098 "If non-nil, funcall this when `python-preoutput-filter' sees `_emacs_ok'.")
@@ -1040,7 +1103,9 @@ Default ignores all inputs of 0, 1, or 2 non-blank characters."
1040;; `python-preoutput-continuation' if we get it. 1103;; `python-preoutput-continuation' if we get it.
1041(defun python-preoutput-filter (s) 1104(defun python-preoutput-filter (s)
1042 "`comint-preoutput-filter-functions' function: ignore prompts not at bol." 1105 "`comint-preoutput-filter-functions' function: ignore prompts not at bol."
1043 (cond ((and (string-match "\\`[.>]\\{3\\} \\'" s) 1106 (cond ((and (string-match (rx (and string-start (repeat 3 (any ".>"))
1107 " " string-end))
1108 s)
1044 (/= (let ((inhibit-field-text-motion t)) 1109 (/= (let ((inhibit-field-text-motion t))
1045 (line-beginning-position)) 1110 (line-beginning-position))
1046 (point))) 1111 (point)))
@@ -1061,10 +1126,10 @@ Default ignores all inputs of 0, 1, or 2 non-blank characters."
1061CMD is the Python command to run. NOSHOW non-nil means don't show the 1126CMD is the Python command to run. NOSHOW non-nil means don't show the
1062buffer automatically. 1127buffer automatically.
1063If there is a process already running in `*Python*', switch to 1128If there is a process already running in `*Python*', switch to
1064that buffer. Interactively a prefix arg, allows you to edit the initial 1129that buffer. Interactively, a prefix arg allows you to edit the initial
1065command line (default is the value of `python-command'); `-i' etc. args 1130command line (default is `python-command'); `-i' etc. args will be added
1066will be added to this as appropriate. Runs the hooks 1131to this as appropriate. Runs the hook `inferior-python-mode-hook'
1067`inferior-python-mode-hook' (after the `comint-mode-hook' is run). 1132\(after the `comint-mode-hook' is run).
1068\(Type \\[describe-mode] in the process buffer for a list of commands.)" 1133\(Type \\[describe-mode] in the process buffer for a list of commands.)"
1069 (interactive (list (if current-prefix-arg 1134 (interactive (list (if current-prefix-arg
1070 (read-string "Run Python: " python-command) 1135 (read-string "Run Python: " python-command)
@@ -1074,47 +1139,34 @@ will be added to this as appropriate. Runs the hooks
1074 ;; Fixme: Consider making `python-buffer' buffer-local as a buffer 1139 ;; Fixme: Consider making `python-buffer' buffer-local as a buffer
1075 ;; (not a name) in Python buffers from which `run-python' &c is 1140 ;; (not a name) in Python buffers from which `run-python' &c is
1076 ;; invoked. Would support multiple processes better. 1141 ;; invoked. Would support multiple processes better.
1077 (unless (comint-check-proc "*Python*") 1142 (unless (comint-check-proc python-buffer)
1078 (let ((cmdlist (append (python-args-to-list cmd) '("-i")))) 1143 (let ((cmdlist (append (python-args-to-list cmd) '("-i")))
1144 (process-environment ; to import emacs.py
1145 (push (concat "PYTHONPATH=" data-directory)
1146 process-environment)))
1079 (set-buffer (apply 'make-comint "Python" (car cmdlist) nil 1147 (set-buffer (apply 'make-comint "Python" (car cmdlist) nil
1080 (cdr cmdlist)))) 1148 (cdr cmdlist)))
1149 (setq python-buffer "*Python*"))
1081 (inferior-python-mode) 1150 (inferior-python-mode)
1082 ;; Load function defintions we need. 1151 ;; Load function defintions we need.
1083 ;; Before the preoutput function was used, this was done via -c in 1152 ;; Before the preoutput function was used, this was done via -c in
1084 ;; cmdlist, but that loses the banner and doesn't run the startup 1153 ;; cmdlist, but that loses the banner and doesn't run the startup
1085 ;; file. 1154 ;; file. The code might be inline here, but there's enough that it
1086 (python-send-string "\ 1155 ;; seems worth putting in a separate file, and it's probably cleaner
1087def _emacs_execfile (file): # execute file and remove it 1156 ;; to put it in a module.
1088 from os import remove 1157 (python-send-string "import emacs"))
1089 try: execfile (file, globals (), globals ()) 1158 (unless noshow (pop-to-buffer python-buffer)))
1090 finally: remove (file) 1159
1091 1160;; Fixme: We typically lose if the inferior isn't in the normal REPL,
1092def _emacs_args (name): # get arglist of name for eldoc &c 1161;; e.g. prompt is `help> '. Probably raise an error if the form of
1093 import inspect 1162;; the prompt is unexpected; actually, it needs to be `>>> ', not
1094 parts = name.split ('.') 1163;; `... ', i.e. we're not inputting a block &c. However, this may not
1095 if len (parts) > 1: 1164;; be the place to do it, e.g. we might actually want to send commands
1096 try: exec 'import ' + parts[0] 1165;; having set up such a state.
1097 except: return None
1098 try: exec 'func='+name # lose if name is keyword or undefined
1099 except: return None
1100 if inspect.isbuiltin (func):
1101 doc = func.__doc__
1102 if doc.find (' ->') != -1:
1103 print '_emacs_out', doc.split (' ->')[0]
1104 elif doc.find ('\\n') != -1:
1105 print '_emacs_out', doc.split ('\\n')[0]
1106 return None
1107 if inspect.ismethod (func): func = func.im_func
1108 if not inspect.isfunction (func):
1109 return None
1110 (args, varargs, varkw, defaults) = inspect.getargspec (func)
1111 print '_emacs_out', func.__name__+inspect.formatargspec (args, varargs, varkw, defaults)
1112
1113print '_emacs_ok'"))
1114 (unless noshow (pop-to-buffer (setq python-buffer "*Python*"))))
1115 1166
1116(defun python-send-command (command) 1167(defun python-send-command (command)
1117 "Like `python-send-string' but resets `compilation-minor-mode'." 1168 "Like `python-send-string' but resets `compilation-minor-mode'."
1169 (goto-char (point-max))
1118 (let ((end (marker-position (process-mark (python-proc))))) 1170 (let ((end (marker-position (process-mark (python-proc)))))
1119 (compilation-forget-errors) 1171 (compilation-forget-errors)
1120 (python-send-string command) 1172 (python-send-string command)
@@ -1126,29 +1178,31 @@ print '_emacs_ok'"))
1126 ;; The region is evaluated from a temporary file. This avoids 1178 ;; The region is evaluated from a temporary file. This avoids
1127 ;; problems with blank lines, which have different semantics 1179 ;; problems with blank lines, which have different semantics
1128 ;; interactively and in files. It also saves the inferior process 1180 ;; interactively and in files. It also saves the inferior process
1129 ;; buffer filling up with interpreter prompts. We need a function 1181 ;; buffer filling up with interpreter prompts. We need a Python
1130 ;; to remove the temporary file when it has been evaluated, which 1182 ;; function to remove the temporary file when it has been evaluated
1131 ;; unfortunately means using a not-quite pristine interpreter 1183 ;; (though we could probably do it in Lisp with a Comint output
1132 ;; initially. Unfortunately we also get tracebacks which look like: 1184 ;; filter). This function also catches exceptions and truncates
1133 ;; 1185 ;; tracebacks not to mention the frame of the function itself.
1134 ;; >>> Traceback (most recent call last):
1135 ;; File "<stdin>", line 1, in ?
1136 ;; File "<string>", line 4, in _emacs_execfile
1137 ;; File "/tmp/py7734RSB", line 11
1138 ;; 1186 ;;
1139 ;; The compilation-minor-mode parsing takes care of relating the 1187 ;; The compilation-minor-mode parsing takes care of relating the
1140 ;; reference to the temporary file to the source. Fixme: 1188 ;; reference to the temporary file to the source.
1141 ;; comint-filter the first two lines of the traceback? 1189 ;;
1190 ;; Fixme: Write a `coding' header to the temp file if the region is
1191 ;; non-ASCII.
1142 (interactive "r") 1192 (interactive "r")
1143 (let* ((f (make-temp-file "py")) 1193 (let* ((f (make-temp-file "py"))
1144 (command (format "_emacs_execfile(%S)" f)) 1194 (command (format "emacs.eexecfile(%S)" f))
1145 (orig-start (copy-marker start))) 1195 (orig-start (copy-marker start)))
1146 (if (save-excursion 1196 (when (save-excursion
1147 (goto-char start) 1197 (goto-char start)
1148 (/= 0 (current-indentation))) ; need dummy block 1198 (/= 0 (current-indentation))) ; need dummy block
1149 (write-region "if True:\n" nil f nil 'nomsg)) 1199 (save-excursion
1200 (goto-char orig-start)
1201 ;; Wrong if we had indented code at buffer start.
1202 (set-marker orig-start (line-beginning-position 0)))
1203 (write-region "if True:\n" nil f nil 'nomsg))
1150 (write-region start end f t 'nomsg) 1204 (write-region start end f t 'nomsg)
1151 (when python-buffer 1205 (let ((proc (python-proc))) ;Make sure we're running a process.
1152 (with-current-buffer python-buffer 1206 (with-current-buffer python-buffer
1153 (python-send-command command) 1207 (python-send-command command)
1154 ;; Tell compile.el to redirect error locations in file `f' to 1208 ;; Tell compile.el to redirect error locations in file `f' to
@@ -1167,6 +1221,8 @@ print '_emacs_ok'"))
1167 (interactive) 1221 (interactive)
1168 (python-send-region (point-min) (point-max))) 1222 (python-send-region (point-min) (point-max)))
1169 1223
1224;; Fixme: Try to define the function or class within the relevant
1225;; module, not just at top level.
1170(defun python-send-defun () 1226(defun python-send-defun ()
1171 "Send the current defun (class or method) to the inferior Python process." 1227 "Send the current defun (class or method) to the inferior Python process."
1172 (interactive) 1228 (interactive)
@@ -1213,11 +1269,11 @@ function location information for debugging, and supports users of
1213module-qualified names." 1269module-qualified names."
1214 (interactive (comint-get-source "Load Python file: " python-prev-dir/file 1270 (interactive (comint-get-source "Load Python file: " python-prev-dir/file
1215 python-source-modes 1271 python-source-modes
1216 t)) ; because execfile needs exact name 1272 t)) ; because execfile needs exact name
1217 (comint-check-source file-name) ; Check to see if buffer needs saved. 1273 (comint-check-source file-name) ; Check to see if buffer needs saving.
1218 (setq python-prev-dir/file (cons (file-name-directory file-name) 1274 (setq python-prev-dir/file (cons (file-name-directory file-name)
1219 (file-name-nondirectory file-name))) 1275 (file-name-nondirectory file-name)))
1220 (when python-buffer 1276 (let ((proc (python-proc))) ;Make sure we have a process.
1221 (with-current-buffer python-buffer 1277 (with-current-buffer python-buffer
1222 ;; Fixme: I'm not convinced by this logic from python-mode.el. 1278 ;; Fixme: I'm not convinced by this logic from python-mode.el.
1223 (python-send-command 1279 (python-send-command
@@ -1225,19 +1281,22 @@ module-qualified names."
1225 ;; Fixme: make sure the directory is in the path list 1281 ;; Fixme: make sure the directory is in the path list
1226 (let ((module (file-name-sans-extension 1282 (let ((module (file-name-sans-extension
1227 (file-name-nondirectory file-name)))) 1283 (file-name-nondirectory file-name))))
1228 (format "\ 1284 (format "emacs.eimport(%S,%S)"
1229if globals().has_key(%S): reload(%s) 1285 module (file-name-directory file-name)))
1230else: import %s 1286 (format "execfile(%S)" file-name)))
1231" module module module)) 1287 (message "%s loaded" file-name))))
1232 (format "execfile('%s')" file-name))))))
1233 1288
1234;; Fixme: Should this start a process if there isn't one? (Unlike cmuscheme.) 1289;; Fixme: If we need to start the process, wait until we've got the OK
1290;; from the startup.
1235(defun python-proc () 1291(defun python-proc ()
1236 "Return the current Python process. See variable `python-buffer'." 1292 "Return the current Python process.
1237 (let ((proc (get-buffer-process (if (eq major-mode 'inferior-python-mode) 1293See variable `python-buffer'. Starts a new process if necessary."
1238 (current-buffer) 1294 (or (if python-buffer
1239 python-buffer)))) 1295 (get-buffer-process (if (eq major-mode 'inferior-python-mode)
1240 (or proc (error "No current process. See variable `python-buffer'")))) 1296 (current-buffer)
1297 python-buffer)))
1298 (progn (run-python nil t)
1299 (python-proc))))
1241 1300
1242;;;; Context-sensitive help. 1301;;;; Context-sensitive help.
1243 1302
@@ -1249,33 +1308,46 @@ else: import %s
1249 "Syntax table giving `.' symbol syntax. 1308 "Syntax table giving `.' symbol syntax.
1250Otherwise inherits from `python-mode-syntax-table'.") 1309Otherwise inherits from `python-mode-syntax-table'.")
1251 1310
1311(defvar view-return-to-alist)
1312
1252;; Fixme: Should this actually be used instead of info-look, i.e. be 1313;; Fixme: Should this actually be used instead of info-look, i.e. be
1253;; bound to C-h S? 1314;; bound to C-h S? Can we use other pydoc stuff before python 2.2?
1254(defun python-describe-symbol (symbol) 1315(defun python-describe-symbol (symbol)
1255 "Get help on SYMBOL using `pydoc'. 1316 "Get help on SYMBOL using `help'.
1256Interactively, prompt for symbol." 1317Interactively, prompt for symbol.
1257 ;; Note that we do this in the inferior process, not a separate one to 1318
1319Symbol may be anything recognized by the interpreter's `help' command --
1320e.g. `CALLS' -- not just variables in scope.
1321This only works for Python version 2.2 or newer since earlier interpreters
1322don't support `help'."
1323 ;; Note that we do this in the inferior process, not a separate one, to
1258 ;; ensure the environment is appropriate. 1324 ;; ensure the environment is appropriate.
1259 (interactive 1325 (interactive
1260 (let ((symbol (with-syntax-table python-dotty-syntax-table 1326 (let ((symbol (with-syntax-table python-dotty-syntax-table
1261 (current-word))) 1327 (current-word)))
1262 (enable-recursive-minibuffers t) 1328 (enable-recursive-minibuffers t))
1263 val) 1329 (list (read-string (if symbol
1264 (setq val (read-string (if symbol 1330 (format "Describe symbol (default %s): " symbol)
1265 (format "Describe symbol (default %s): " 1331 "Describe symbol: ")
1266 symbol) 1332 nil nil symbol))))
1267 "Describe symbol: ")
1268 nil nil symbol))
1269 (list (or val symbol))))
1270 (if (equal symbol "") (error "No symbol")) 1333 (if (equal symbol "") (error "No symbol"))
1271 (let* ((func `(lambda () 1334 (let* ((func `(lambda ()
1272 (comint-redirect-send-command (format "help(%S)\n" ,symbol) 1335 (comint-redirect-send-command (format "emacs.ehelp(%S)\n"
1336 ,symbol)
1273 "*Help*" nil)))) 1337 "*Help*" nil))))
1274 ;; Ensure we have a suitable help buffer. 1338 ;; Ensure we have a suitable help buffer.
1275 (let (temp-buffer-show-hook) ; avoid xref stuff 1339 ;; Fixme: Maybe process `Related help topics' a la help xrefs and
1276 (with-output-to-temp-buffer "*Help*" 1340 ;; allow C-c C-f in help buffer.
1341 (let ((temp-buffer-show-hook ; avoid xref stuff
1342 (lambda ()
1343 (toggle-read-only 1)
1344 (setq view-return-to-alist
1345 (list (cons (selected-window) help-return-method))))))
1346 (help-setup-xref (list 'python-describe-symbol symbol))
1347 (with-output-to-temp-buffer (help-buffer)
1277 (with-current-buffer standard-output 1348 (with-current-buffer standard-output
1278 (set (make-local-variable 'comint-redirect-subvert-readonly) t)))) 1349 (set (make-local-variable 'comint-redirect-subvert-readonly) t)
1350 (print-help-return-message))))
1279 (if (and python-buffer (get-buffer python-buffer)) 1351 (if (and python-buffer (get-buffer python-buffer))
1280 (with-current-buffer python-buffer 1352 (with-current-buffer python-buffer
1281 (funcall func)) 1353 (funcall func))
@@ -1284,6 +1356,15 @@ Interactively, prompt for symbol."
1284 1356
1285(add-to-list 'debug-ignored-errors "^No symbol") 1357(add-to-list 'debug-ignored-errors "^No symbol")
1286 1358
1359(defun python-send-receive (string)
1360 "Send STRING to inferior Python (if any) and return result.
1361The result is what follows `_emacs_out' in the output (or nil)."
1362 (let ((proc (python-proc)))
1363 (python-send-string string)
1364 (setq python-preoutput-result nil)
1365 (accept-process-output proc 5)
1366 python-preoutput-result))
1367
1287;; Fixme: try to make it work with point in the arglist. Also, is 1368;; Fixme: try to make it work with point in the arglist. Also, is
1288;; there anything reasonable we can do with random methods? 1369;; there anything reasonable we can do with random methods?
1289;; (Currently only works with functions.) 1370;; (Currently only works with functions.)
@@ -1292,14 +1373,9 @@ Interactively, prompt for symbol."
1292Only works when point is in a function name, not its arglist, for instance. 1373Only works when point is in a function name, not its arglist, for instance.
1293Assumes an inferior Python is running." 1374Assumes an inferior Python is running."
1294 (let ((symbol (with-syntax-table python-dotty-syntax-table 1375 (let ((symbol (with-syntax-table python-dotty-syntax-table
1295 (current-word))) 1376 (current-word))))
1296 (proc (and python-buffer (python-proc)))) 1377 (when symbol
1297 (when (and proc symbol) 1378 (python-send-receive (format "emacs.eargs(%S)" symbol)))))
1298 (python-send-string
1299 (format "_emacs_args(%S)" symbol))
1300 (setq python-preoutput-result nil)
1301 (accept-process-output proc 1)
1302 python-preoutput-result)))
1303 1379
1304;;;; Info-look functionality. 1380;;;; Info-look functionality.
1305 1381
@@ -1502,11 +1578,97 @@ Uses `python-beginning-of-block', `python-end-of-block'."
1502 (python-end-of-block) 1578 (python-end-of-block)
1503 (exchange-point-and-mark)) 1579 (exchange-point-and-mark))
1504 1580
1581;;;; Completion.
1582
1583(defun python-symbol-completions (symbol)
1584 "Return a list of completions of the string SYMBOL from Python process.
1585The list is sorted."
1586 (when symbol
1587 (let ((completions
1588 (condition-case ()
1589 (car (read-from-string (python-send-receive
1590 (format "emacs.complete(%S)" symbol))))
1591 (error nil))))
1592 (sort
1593 ;; We can get duplicates from the above -- don't know why.
1594 (delete-dups completions)
1595 #'string<))))
1596
1597(defun python-partial-symbol ()
1598 "Return the partial symbol before point (for completion)."
1599 (let ((end (point))
1600 (start (save-excursion
1601 (and (re-search-backward
1602 (rx (and (or buffer-start (regexp "[^[:alnum:]._]"))
1603 (group (1+ (regexp "[[:alnum:]._]")))
1604 point))
1605 nil t)
1606 (match-beginning 1)))))
1607 (if start (buffer-substring-no-properties start end))))
1608
1609;; Fixme: We should have an abstraction of this sort of thing in the
1610;; core.
1611(defun python-complete-symbol ()
1612 "Perform completion on the Python symbol preceding point.
1613Repeating the command scrolls the completion window."
1614 (interactive)
1615 (let ((window (get-buffer-window "*Completions*")))
1616 (if (and (eq last-command this-command)
1617 window (window-live-p window) (window-buffer window)
1618 (buffer-name (window-buffer window)))
1619 (with-current-buffer (window-buffer window)
1620 (if (pos-visible-in-window-p (point-max) window)
1621 (set-window-start window (point-min))
1622 (save-selected-window
1623 (select-window window)
1624 (scroll-up))))
1625 ;; Do completion.
1626 (let* ((end (point))
1627 (symbol (python-partial-symbol))
1628 (completions (python-symbol-completions symbol))
1629 (completion (if completions
1630 (try-completion symbol completions))))
1631 (when symbol
1632 (cond ((eq completion t))
1633 ((null completion)
1634 (message "Can't find completion for \"%s\"" symbol)
1635 (ding))
1636 ((not (string= symbol completion))
1637 (delete-region (- end (length symbol)) end)
1638 (insert completion))
1639 (t
1640 (message "Making completion list...")
1641 (with-output-to-temp-buffer "*Completions*"
1642 (display-completion-list completions))
1643 (message "Making completion list...%s" "done"))))))))
1644
1645(eval-when-compile (require 'hippie-exp))
1646
1647(defun python-try-complete (old)
1648 "Completion function for Python for use with `hippie-expand'."
1649 (when (eq major-mode 'python-mode) ; though we only add it locally
1650 (unless old
1651 (let ((symbol (python-partial-symbol)))
1652 (he-init-string (- (point) (length symbol)) (point))
1653 (if (not (he-string-member he-search-string he-tried-table))
1654 (push he-search-string he-tried-table))
1655 (setq he-expand-list
1656 (and symbol (python-symbol-completions symbol)))))
1657 (while (and he-expand-list
1658 (he-string-member (car he-expand-list) he-tried-table))
1659 (pop he-expand-list))
1660 (if he-expand-list
1661 (progn
1662 (he-substitute-string (pop he-expand-list))
1663 t)
1664 (if old (he-reset-string))
1665 nil)))
1666
1505;;;; Modes. 1667;;;; Modes.
1506 1668
1507(defvar outline-heading-end-regexp) 1669(defvar outline-heading-end-regexp)
1508(defvar eldoc-print-current-symbol-info-function) 1670(defvar eldoc-print-current-symbol-info-function)
1509(defvar python-mode-running) 1671
1510;;;###autoload 1672;;;###autoload
1511(define-derived-mode python-mode fundamental-mode "Python" 1673(define-derived-mode python-mode fundamental-mode "Python"
1512 "Major mode for editing Python files. 1674 "Major mode for editing Python files.
@@ -1548,11 +1710,10 @@ lines count as headers.
1548 )) 1710 ))
1549 (set (make-local-variable 'parse-sexp-lookup-properties) t) 1711 (set (make-local-variable 'parse-sexp-lookup-properties) t)
1550 (set (make-local-variable 'comment-start) "# ") 1712 (set (make-local-variable 'comment-start) "# ")
1551 ;; Fixme: define a comment-indent-function? 1713 (set (make-local-variable 'comment-indent-function) #'python-comment-indent)
1552 (set (make-local-variable 'indent-line-function) #'python-indent-line) 1714 (set (make-local-variable 'indent-line-function) #'python-indent-line)
1553 (set (make-local-variable 'paragraph-start) "\\s-*$") 1715 (set (make-local-variable 'paragraph-start) "\\s-*$")
1554 (set (make-local-variable 'fill-paragraph-function) 1716 (set (make-local-variable 'fill-paragraph-function) 'python-fill-paragraph)
1555 'python-fill-paragraph)
1556 (set (make-local-variable 'require-final-newline) t) 1717 (set (make-local-variable 'require-final-newline) t)
1557 (set (make-local-variable 'add-log-current-defun-function) 1718 (set (make-local-variable 'add-log-current-defun-function)
1558 #'python-current-defun) 1719 #'python-current-defun)
@@ -1570,6 +1731,9 @@ lines count as headers.
1570 #'python-eldoc-function) 1731 #'python-eldoc-function)
1571 (add-hook 'eldoc-mode-hook 1732 (add-hook 'eldoc-mode-hook
1572 '(lambda () (run-python 0 t)) nil t) ; need it running 1733 '(lambda () (run-python 0 t)) nil t) ; need it running
1734 (if (featurep 'hippie-exp)
1735 (set (make-local-variable 'hippie-expand-try-functions-list)
1736 (cons 'python-try-complete hippie-expand-try-functions-list)))
1573 (unless font-lock-mode (font-lock-mode 1)) 1737 (unless font-lock-mode (font-lock-mode 1))
1574 (when python-guess-indent (python-guess-indent)) 1738 (when python-guess-indent (python-guess-indent))
1575 (set (make-local-variable 'python-command) python-python-command) 1739 (set (make-local-variable 'python-command) python-python-command)