mirror of https://github.com/python/cpython
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
|
@ -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…
Reference in New Issue