mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	First round of changes, mostly subprocess stuff.
(py-execute-file): Better interaction with comint. Set comint-scroll-to-bottom-on-output to t. Wrapper buffer change in unwind-protect in case process filter fails. (py-shell): Start Python with -i flag to fix tty problem on Windows; presumably -- not yet tested. (py-clear-queue): New function to clear the pending exec file queue. Not currently keybound. (py-execute-region, py-execute-buffer): Added optional async flag (use via C-u prefix) to execute the region in a new asynchrous buffer, even if the Python shell is running. (py-append-to-process-buffer): Removed as obsolete. Comint provides this functionality. Removed fbound test defun of match-string. All modern X/Emacsen have this function.
This commit is contained in:
		
							parent
							
								
									bfa9f13e14
								
							
						
					
					
						commit
						a97a3f34d6
					
				
					 1 changed files with 129 additions and 138 deletions
				
			
		|  | @ -6,7 +6,6 @@ | |||
| ;;         1992-1994 Tim Peters | ||||
| ;; Maintainer: python-mode@python.org | ||||
| ;; Created:    Feb 1992 | ||||
| ;; Version:       3.0 | ||||
| ;; Keywords:   python languages oop | ||||
| 
 | ||||
| (defconst py-version "3.0" | ||||
|  | @ -32,10 +31,10 @@ | |||
| 
 | ||||
| ;; python-mode.el is currently distributed with XEmacs 19 and XEmacs | ||||
| ;; 20.  Since this file is not GPL'd it is not distributed with Emacs, | ||||
| ;; but it is compatible with the EOL 19 series and current 20 series | ||||
| ;; Emacsen.  By default, in XEmacs when you visit a .py file, it is | ||||
| ;; put in Python mode.  In Emacs, you need to add the following to | ||||
| ;; your .emacs file (you don't need this for XEmacs): | ||||
| ;; but it is compatible with 19.34 and the current 20 series Emacsen. | ||||
| ;; By default, in XEmacs when you visit a .py file, it is put in | ||||
| ;; Python mode.  In Emacs, you need to add the following to your | ||||
| ;; .emacs file (you don't need this for XEmacs): | ||||
| ;; | ||||
| ;;     (autoload 'python-mode "python-mode" "Python editing mode." t) | ||||
| ;;     (setq auto-mode-alist | ||||
|  | @ -854,110 +853,32 @@ Electric behavior is inhibited inside a string or comment." | |||
| 	    ))))) | ||||
| 
 | ||||
|  | ||||
| ;;; Functions that execute Python commands in a subprocess | ||||
| ;;;###autoload | ||||
| (defun py-shell () | ||||
|   "Start an interactive Python interpreter in another window. | ||||
| This is like Shell mode, except that Python is running in the window | ||||
| instead of a shell.  See the `Interactive Shell' and `Shell Mode' | ||||
| sections of the Emacs manual for details, especially for the key | ||||
| bindings active in the `*Python*' buffer. | ||||
| 
 | ||||
| See the docs for variable `py-scroll-buffer' for info on scrolling | ||||
| behavior in the process window. | ||||
| 
 | ||||
| Warning: Don't use an interactive Python if you change sys.ps1 or | ||||
| sys.ps2 from their default values, or if you're running code that | ||||
| prints `>>> ' or `... ' at the start of a line.  `python-mode' can't | ||||
| distinguish your output from Python's output, and assumes that `>>> ' | ||||
| at the start of a line is a prompt from Python.  Similarly, the Emacs | ||||
| Shell mode code assumes that both `>>> ' and `... ' at the start of a | ||||
| line are Python prompts.  Bad things can happen if you fool either | ||||
| mode. | ||||
| 
 | ||||
| Warning:  If you do any editing *in* the process buffer *while* the | ||||
| buffer is accepting output from Python, do NOT attempt to `undo' the | ||||
| changes.  Some of the output (nowhere near the parts you changed!) may | ||||
| be lost if you do.  This appears to be an Emacs bug, an unfortunate | ||||
| interaction between undo and process filters; the same problem exists in | ||||
| non-Python process buffers using the default (Emacs-supplied) process | ||||
| filter." | ||||
|   ;; BAW - should undo be disabled in the python process buffer, if | ||||
|   ;; this bug still exists? | ||||
|   (interactive) | ||||
|   (require 'comint) | ||||
|   (switch-to-buffer-other-window (make-comint "Python" py-python-command)) | ||||
|   (make-local-variable 'comint-prompt-regexp) | ||||
|   (setq comint-prompt-regexp "^>>> \\|^[.][.][.] ") | ||||
|   (set-process-filter (get-buffer-process (current-buffer)) nil) | ||||
|   (set-syntax-table py-mode-syntax-table) | ||||
|   (local-set-key [tab] 'self-insert-command)) | ||||
| 
 | ||||
| (defun py-execute-region (start end) | ||||
|   "Send the region between START and END to a Python interpreter. | ||||
| If there is a *Python* process it is used. | ||||
| 
 | ||||
| Hint: If you want to execute part of a Python file several times | ||||
| \(e.g., perhaps you're developing a function and want to flesh it out | ||||
| a bit at a time), use `\\[narrow-to-region]' to restrict the buffer to | ||||
| the region of interest, and send the code to a *Python* process via | ||||
| `\\[py-execute-buffer]' instead. | ||||
| 
 | ||||
| Following are subtleties to note when using a *Python* process: | ||||
| 
 | ||||
| If a *Python* process is used, the region is copied into a temporary | ||||
| file (in directory `py-temp-directory'), and an `execfile' command is | ||||
| sent to Python naming that file.  If you send regions faster than | ||||
| Python can execute them, `python-mode' will save them into distinct | ||||
| temp files, and execute the next one in the queue the next time it | ||||
| sees a `>>> ' prompt from Python.  Each time this happens, the process | ||||
| buffer is popped into a window (if it's not already in some window) so | ||||
| you can see it, and a comment of the form | ||||
| 
 | ||||
|   \t## working on region in file <name> ... | ||||
| 
 | ||||
| is inserted at the end. | ||||
| 
 | ||||
| Caution: No more than 26 regions can be pending at any given time. | ||||
| This limit is (indirectly) inherited from libc's mktemp(3). | ||||
| `python-mode' does not try to protect you from exceeding the limit. | ||||
| It's extremely unlikely that you'll get anywhere close to the limit in | ||||
| practice, unless you're trying to be a jerk <grin>. | ||||
| 
 | ||||
| See the `\\[py-shell]' docs for additional warnings." | ||||
|   (interactive "r") | ||||
|   (or (< start end) | ||||
|       (error "Region is empty")) | ||||
|   (let ((pyproc (get-process "Python")) | ||||
| 	fname) | ||||
|     (if (null pyproc) | ||||
| 	(let ((outbuf "*Python Output*")) | ||||
| 	  (shell-command-on-region start end py-python-command outbuf) | ||||
| 	  (save-excursion | ||||
| 	    (set-buffer outbuf) | ||||
| 	    ;; TBD: ??? | ||||
| 	    (goto-char (point-max)))) | ||||
|       ;; else feed it thru a temp file | ||||
|       (setq fname (py-make-temp-name)) | ||||
|       (write-region start end fname nil 'no-msg) | ||||
|       (setq py-file-queue (append py-file-queue (list fname))) | ||||
|       (if (cdr py-file-queue) | ||||
| 	  (message "File %s queued for execution" fname) | ||||
| 	;; else | ||||
| 	(py-execute-file pyproc fname))))) | ||||
| 
 | ||||
| (defun py-execute-file (pyproc fname) | ||||
|   (py-append-to-process-buffer | ||||
|    pyproc | ||||
|    (format "## working on region in file %s ...\n" fname)) | ||||
|   (process-send-string pyproc (format "execfile('%s')\n" fname))) | ||||
| ;; Python subprocess utilities and filters | ||||
| (defun py-execute-file (proc filename) | ||||
|   ;; Send a properly formatted execfile('FILENAME') to the underlying | ||||
|   ;; Python interpreter process FILENAME.  Make that process's buffer | ||||
|   ;; visible and force display.  Also make comint believe the user | ||||
|   ;; typed this string so that kill-output-from-shell does The Right | ||||
|   ;; Thing. | ||||
|   (let ((curbuf (current-buffer)) | ||||
| 	(procbuf (process-buffer proc)) | ||||
| 	(comint-scroll-to-bottom-on-output t) | ||||
| 	(msg (format "## working on region in file %s...\n" filename)) | ||||
| 	(cmd (format "execfile('%s')\n" filename))) | ||||
|     (unwind-protect | ||||
| 	(progn | ||||
| 	  (set-buffer procbuf) | ||||
| 	  (goto-char (point-max)) | ||||
| 	  (move-marker (process-mark proc) (point)) | ||||
| 	  (funcall (process-filter proc) proc msg)) | ||||
|       (set-buffer curbuf)) | ||||
|     (process-send-string proc cmd))) | ||||
| 
 | ||||
| (defun py-process-filter (pyproc string) | ||||
|   (let ((curbuf (current-buffer)) | ||||
| 	(pbuf (process-buffer pyproc)) | ||||
| 	(pmark (process-mark pyproc)) | ||||
| 	file-finished) | ||||
| 
 | ||||
|     ;; make sure we switch to a different buffer at least once.  if we | ||||
|     ;; *don't* do this, then if the process buffer is in the selected | ||||
|     ;; window, and point is before the end, and lots of output is | ||||
|  | @ -1017,16 +938,114 @@ See the `\\[py-shell]' docs for additional warnings." | |||
| 	    )) | ||||
|       (set-buffer curbuf)))) | ||||
| 
 | ||||
| (defun py-execute-buffer () | ||||
|  | ||||
| ;;; Subprocess commands | ||||
| 
 | ||||
| ;;;###autoload | ||||
| (defun py-shell () | ||||
|   "Start an interactive Python interpreter in another window. | ||||
| This is like Shell mode, except that Python is running in the window | ||||
| instead of a shell.  See the `Interactive Shell' and `Shell Mode' | ||||
| sections of the Emacs manual for details, especially for the key | ||||
| bindings active in the `*Python*' buffer. | ||||
| 
 | ||||
| See the docs for variable `py-scroll-buffer' for info on scrolling | ||||
| behavior in the process window. | ||||
| 
 | ||||
| Warning: Don't use an interactive Python if you change sys.ps1 or | ||||
| sys.ps2 from their default values, or if you're running code that | ||||
| prints `>>> ' or `... ' at the start of a line.  `python-mode' can't | ||||
| distinguish your output from Python's output, and assumes that `>>> ' | ||||
| at the start of a line is a prompt from Python.  Similarly, the Emacs | ||||
| Shell mode code assumes that both `>>> ' and `... ' at the start of a | ||||
| line are Python prompts.  Bad things can happen if you fool either | ||||
| mode. | ||||
| 
 | ||||
| Warning:  If you do any editing *in* the process buffer *while* the | ||||
| buffer is accepting output from Python, do NOT attempt to `undo' the | ||||
| changes.  Some of the output (nowhere near the parts you changed!) may | ||||
| be lost if you do.  This appears to be an Emacs bug, an unfortunate | ||||
| interaction between undo and process filters; the same problem exists in | ||||
| non-Python process buffers using the default (Emacs-supplied) process | ||||
| filter." | ||||
|   ;; BAW - should undo be disabled in the python process buffer, if | ||||
|   ;; this bug still exists? | ||||
|   (interactive) | ||||
|   (require 'comint) | ||||
|   (switch-to-buffer-other-window (make-comint "Python" py-python-command "-i")) | ||||
|   (make-local-variable 'comint-prompt-regexp) | ||||
|   (setq comint-prompt-regexp "^>>> \\|^[.][.][.] ") | ||||
|   (set-process-filter (get-buffer-process (current-buffer)) 'py-process-filter) | ||||
|   (set-syntax-table py-mode-syntax-table) | ||||
|   (local-set-key [tab] 'self-insert-command)) | ||||
| 
 | ||||
|  | ||||
| (defun py-clear-queue () | ||||
|   "Clear the queue of temporary files waiting to execute." | ||||
|   (interactive) | ||||
|   (let ((n (length py-file-queue))) | ||||
|     (mapcar 'delete-file py-file-queue) | ||||
|     (setq py-file-queue nil) | ||||
|     (message "%d pending files de-queued." n))) | ||||
| 
 | ||||
| (defun py-execute-region (start end &optional async) | ||||
|   "Execute the the region in a Python interpreter. | ||||
| The region is first copied into a temporary file (in the directory | ||||
| `py-temp-directory').  If there is no Python interpreter shell | ||||
| running, this file is executed synchronously using | ||||
| `shell-command-on-region'.  If the program is long running, use an | ||||
| optional \\[universal-argument] to run the command asynchronously in | ||||
| its own buffer. | ||||
| 
 | ||||
| If the Python interpreter shell is running, the region is execfile()'d | ||||
| in that shell.  If you try to execute regions too quickly, | ||||
| `python-mode' will queue them up and execute them one at a time when | ||||
| it sees a `>>> ' prompt from Python.  Each time this happens, the | ||||
| process buffer is popped into a window (if it's not already in some | ||||
| window) so you can see it, and a comment of the form | ||||
| 
 | ||||
|     \t## working on region in file <name>... | ||||
| 
 | ||||
| is inserted at the end.  See also the command `py-clear-queue'." | ||||
|   (interactive "r\nP") | ||||
|   (or (< start end) | ||||
|       (error "Region is empty")) | ||||
|   (let* ((proc (get-process "Python")) | ||||
| 	 (temp (make-temp-name "python")) | ||||
| 	 (file (concat (file-name-as-directory py-temp-directory) temp)) | ||||
| 	 (outbuf "*Python Output*")) | ||||
|     (write-region start end file nil 'nomsg) | ||||
|     (cond | ||||
|      ;; always run the code in it's own asynchronous subprocess | ||||
|      (async | ||||
|       (let* ((buf (generate-new-buffer-name "*Python Output*"))) | ||||
| 	(start-process "Python" buf py-python-command "-u" file) | ||||
| 	(pop-to-buffer buf) | ||||
| 	)) | ||||
|      ;; if the Python interpreter shell is running, queue it up for | ||||
|      ;; execution there. | ||||
|      (proc | ||||
|       ;; use the existing python shell | ||||
|       (if (not py-file-queue) | ||||
| 	  (py-execute-file proc file) | ||||
| 	(push file py-file-queue) | ||||
| 	(message "File %s queued for execution" file)) | ||||
|       ) | ||||
|      (t | ||||
|       ;; otherwise either run it synchronously in a subprocess | ||||
|       (shell-command-on-region start end py-python-command outbuf) | ||||
|       )))) | ||||
| 
 | ||||
| ;; Code execution command | ||||
| (defun py-execute-buffer (&optional async) | ||||
|   "Send the contents of the buffer to a Python interpreter. | ||||
| If there is a *Python* process buffer it is used.  If a clipping | ||||
| restriction is in effect, only the accessible portion of the buffer is | ||||
| sent.  A trailing newline will be supplied if needed. | ||||
| 
 | ||||
| See the `\\[py-execute-region]' docs for an account of some subtleties." | ||||
|   (interactive) | ||||
|   (py-execute-region (point-min) (point-max))) | ||||
| 
 | ||||
|   (interactive "P") | ||||
|   (py-execute-region (point-min) (point-max) async)) | ||||
| 
 | ||||
|  | ||||
| ;; Functions for Python style indentation | ||||
|  | @ -2363,10 +2382,6 @@ local bindings to py-newline-and-indent.")) | |||
| 	(intern (buffer-substring (match-beginning 1) (match-end 1))) | ||||
|       nil))) | ||||
| 
 | ||||
| (defun py-make-temp-name () | ||||
|   (make-temp-name | ||||
|    (concat (file-name-as-directory py-temp-directory) "python"))) | ||||
| 
 | ||||
| (defun py-delete-file-silently (fname) | ||||
|   (condition-case nil | ||||
|       (delete-file fname) | ||||
|  | @ -2378,30 +2393,6 @@ local bindings to py-newline-and-indent.")) | |||
| 	     (py-delete-file-silently (car py-file-queue)) | ||||
| 	     (setq py-file-queue (cdr py-file-queue))))) | ||||
| 
 | ||||
| ;; make PROCESS's buffer visible, append STRING to it, and force | ||||
| ;; display; also make shell-mode believe the user typed this string, | ||||
| ;; so that kill-output-from-shell and show-output-from-shell work | ||||
| ;; "right" | ||||
| (defun py-append-to-process-buffer (process string) | ||||
|   (let ((cbuf (current-buffer)) | ||||
| 	(pbuf (process-buffer process)) | ||||
| 	(py-scroll-process-buffer t)) | ||||
|     (set-buffer pbuf) | ||||
|     (goto-char (point-max)) | ||||
|     (move-marker (process-mark process) (point)) | ||||
|     (funcall (process-filter process) process string) | ||||
|     (set-buffer cbuf)) | ||||
|   (sit-for 0)) | ||||
| 
 | ||||
| ;; older Emacsen don't have this function | ||||
| (if (not (fboundp 'match-string)) | ||||
|     (defun match-string (n) | ||||
|       (let ((beg (match-beginning n)) | ||||
| 	    (end (match-end n))) | ||||
| 	(if (and beg end) | ||||
| 	    (buffer-substring beg end) | ||||
| 	  nil)))) | ||||
| 
 | ||||
| (defun py-current-defun () | ||||
|   ;; tell add-log.el how to find the current function/method/variable | ||||
|   (save-excursion | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Barry Warsaw
						Barry Warsaw