mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
support for multiple Python buffers
This commit is contained in:
parent
936d4d31d5
commit
fd0672fa8e
@ -375,10 +375,12 @@ support for features needed by `python-mode'.")
|
||||
(put 'python-mode 'font-lock-defaults '(python-font-lock-keywords))
|
||||
|
||||
;; have to bind py-file-queue before installing the kill-emacs-hook
|
||||
(defvar py-file-queue nil
|
||||
"Queue of Python temp files awaiting execution.
|
||||
Currently-active file is at the head of the list.")
|
||||
|
||||
;; (defvar py-file-queue nil
|
||||
;; "Queue of Python temp files awaiting execution.
|
||||
;; Currently-active file is at the head of the list.")
|
||||
(defvar py-file-queues (make-hash-table)
|
||||
"hash table of Python process to queue of Python temp files awaiting
|
||||
execution. Currently-active file is at the head of each list.")
|
||||
|
||||
;; Constants
|
||||
|
||||
@ -585,6 +587,7 @@ Currently-active file is at the head of the list.")
|
||||
(define-key py-shell-map [return] 'comint-interrupt-subjob-or-maybe-return)
|
||||
(define-key py-shell-map "\C-c\C-r" 'python-resume)
|
||||
(define-key py-shell-map "\C-c\C-s" 'pyd-shell)
|
||||
(define-key py-shell-map "\C-c\C-f" 'py-kill-shells)
|
||||
)
|
||||
|
||||
(defvar py-mode-syntax-table nil
|
||||
@ -1114,8 +1117,7 @@ comment."
|
||||
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))
|
||||
(let ((procbuf (process-buffer proc))
|
||||
;(comint-scroll-to-bottom-on-output t)
|
||||
;; VR STUDIO DE-HANCEMENT: GET RID OF ANNOYING MESSAGE
|
||||
;(msg (format "## working on region in file %s...\n" filename))
|
||||
@ -1126,24 +1128,26 @@ comint believe the user typed this string so that
|
||||
(set-buffer procbuf)
|
||||
(goto-char (point-max))
|
||||
(move-marker (process-mark proc) (point))
|
||||
(funcall (process-filter proc) proc msg))
|
||||
(set-buffer curbuf))
|
||||
(funcall (process-filter proc) proc msg)))
|
||||
(process-send-string proc cmd)))
|
||||
|
||||
(defun py-comint-output-filter-function (string)
|
||||
"Watch output for Python prompt and exec next file waiting in queue.
|
||||
This function is appropriate for `comint-output-filter-functions'."
|
||||
(let* ((proc (get-buffer-process (current-buffer)))
|
||||
(file-queue (gethash proc py-file-queues nil)))
|
||||
;; TBD: this should probably use split-string
|
||||
(when (and (or (string-equal string ">>> ")
|
||||
(when (and file-queue
|
||||
(or (string-equal string ">>> ")
|
||||
(and (>= (length string) 5)
|
||||
(string-equal (substring string -5) "\n>>> ")))
|
||||
py-file-queue)
|
||||
(py-safe (delete-file (car py-file-queue)))
|
||||
(setq py-file-queue (cdr py-file-queue))
|
||||
(if py-file-queue
|
||||
(let ((pyproc (get-buffer-process (current-buffer))))
|
||||
(py-execute-file pyproc (car py-file-queue))))
|
||||
))
|
||||
(string-equal (substring string -5) "\n>>> "))))
|
||||
(let ((entry (car file-queue)))
|
||||
(py-safe (delete-file (car entry)))
|
||||
(setq file-queue (cdr file-queue))
|
||||
(if file-queue
|
||||
(let ((entry (car file-queue)))
|
||||
(py-execute-file (cdar entry) (car entry))))
|
||||
))))
|
||||
|
||||
(defun py-postprocess-output-buffer (buf)
|
||||
"Highlight exceptions found in BUF.
|
||||
@ -1182,7 +1186,7 @@ If an exception occurred return t, otherwise return nil. BUF must exist."
|
||||
(defvar ppy-which-args ppy-python-command-args)
|
||||
(defvar pyd-which-args pyd-python-command-args)
|
||||
(defvar pyo-which-args pyo-python-command-args)
|
||||
(defvar py-which-bufname "Python")
|
||||
(defvar py-which-bufname-moved "Python")
|
||||
(make-variable-buffer-local 'py-which-shell)
|
||||
(make-variable-buffer-local 'ppy-which-shell)
|
||||
(make-variable-buffer-local 'pyd-which-shell)
|
||||
@ -1191,7 +1195,7 @@ If an exception occurred return t, otherwise return nil. BUF must exist."
|
||||
(make-variable-buffer-local 'ppy-which-args)
|
||||
(make-variable-buffer-local 'pyd-which-args)
|
||||
(make-variable-buffer-local 'pyo-which-args)
|
||||
(make-variable-buffer-local 'py-which-bufname)
|
||||
(make-variable-buffer-local 'py-which-bufname-moved)
|
||||
(make-variable-buffer-local 'ppy-which-bufname)
|
||||
(make-variable-buffer-local 'pyd-which-bufname)
|
||||
(make-variable-buffer-local 'pyo-which-bufname)
|
||||
@ -1246,6 +1250,21 @@ Programmatically, ARG can also be one of the symbols `cpython' or
|
||||
(message "Using the %s shell" msg)
|
||||
(setq py-output-buffer (format "*%s Output*" py-which-bufname))))
|
||||
|
||||
(defun py-kill-shells ()
|
||||
(interactive)
|
||||
(save-current-buffer
|
||||
(for-all-py-procs
|
||||
(lambda (proc)
|
||||
(let ((procbuf (process-buffer proc)))
|
||||
(set-buffer procbuf)
|
||||
(comint-send-eof)
|
||||
(py-point-to-max proc)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;;;###autoload
|
||||
(defun py-shell (&optional argprompt)
|
||||
"Start an interactive Python interpreter in another window.
|
||||
@ -1337,7 +1356,7 @@ filter."
|
||||
))
|
||||
|
||||
(defun pyo-shell (&optional argprompt)
|
||||
"This is Jesse's hacked version of py-shell which runs the debug python"
|
||||
"This is Jesse's hacked version of py-shell which runs the optimized python"
|
||||
(interactive "P")
|
||||
;; Set the default shell if not already set
|
||||
(when (null pyo-which-shell)
|
||||
@ -1392,17 +1411,88 @@ filter."
|
||||
(use-local-map py-shell-map)
|
||||
))
|
||||
|
||||
(defun py-shell-named (bufname)
|
||||
"This is Darren's hacked version of py-shell that allows for multiple
|
||||
Python shells in a single Emacs window via different buffer names.
|
||||
Creates a buffer named *Python-bufname*
|
||||
"
|
||||
(interactive "sShell Name: ")
|
||||
;; Set the default shell if not already set
|
||||
(when (null py-which-shell)
|
||||
(py-toggle-shells py-default-interpreter))
|
||||
(let ((bname py-which-bufname))
|
||||
(when bufname
|
||||
(setq bname (concat py-which-bufname "-" bufname)))
|
||||
(switch-to-buffer ;; -other-window
|
||||
(apply 'make-comint bname py-which-shell nil py-which-args))
|
||||
(make-local-variable 'comint-prompt-regexp)
|
||||
(setq comint-prompt-regexp "^>>> \\|^[.][.][.] \\|^(pdb) ")
|
||||
(add-hook 'comint-output-filter-functions
|
||||
'py-comint-output-filter-function)
|
||||
(set-syntax-table py-mode-syntax-table)
|
||||
(use-local-map py-shell-map))
|
||||
)
|
||||
|
||||
(defun py-clear-queue ()
|
||||
(defun py-start-process (name command)
|
||||
(let ((bufname (format "*Python-%s*" name))
|
||||
(macro (format "%s\r" command))
|
||||
(curbuf (current-buffer))
|
||||
(newbuf nil))
|
||||
(py-shell-named name)
|
||||
(switch-to-buffer bufname)
|
||||
(setq newbuf (current-buffer))
|
||||
(execute-kbd-macro macro)
|
||||
(py-point-to-max (get-buffer-process (current-buffer)))
|
||||
(switch-to-buffer curbuf)
|
||||
; make sure that the new buffer is visible
|
||||
(display-buffer newbuf)
|
||||
)
|
||||
)
|
||||
|
||||
(defun is-py-bufname (bufname)
|
||||
(and (eq (compare-strings py-which-bufname 0 (length py-which-bufname)
|
||||
bufname 0 (length py-which-bufname)) t)
|
||||
(not (string-equal bufname "Python Output")))
|
||||
)
|
||||
|
||||
(defun is-py-proc (proc)
|
||||
(is-py-bufname (process-name proc))
|
||||
)
|
||||
|
||||
(defun for-all-py-procs (callback)
|
||||
"Call a function for each python process. Callback must accept process.
|
||||
If args are provided they will be passed to callback before process."
|
||||
;; run through all the Python processes and call the callback
|
||||
(mapcar
|
||||
(lambda (proc)
|
||||
(if (is-py-proc proc)
|
||||
(let ()
|
||||
(apply callback (list proc))
|
||||
)
|
||||
)
|
||||
)
|
||||
(process-list)
|
||||
)
|
||||
)
|
||||
|
||||
(defun py-clear-queues ()
|
||||
"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)
|
||||
(when py-file-queues
|
||||
(let ()
|
||||
(maphash (lambda (proc file-queue)
|
||||
(let ((n (length file-queue)))
|
||||
(mapcar #'(lambda (entry)
|
||||
(py-safe (delete-file (car entry))))
|
||||
file-queue)
|
||||
(setq file-queue nil)
|
||||
(message "%d pending files de-queued." n)))
|
||||
py-file-queues
|
||||
)
|
||||
(clrhash py-file-queues))
|
||||
))
|
||||
|
||||
|
||||
(defun py-execute-region (start end &optional async)
|
||||
(defun py-execute-region (start end proc &optional async)
|
||||
"Execute the region in a Python interpreter.
|
||||
|
||||
The region is first copied into a temporary file (in the directory
|
||||
@ -1426,11 +1516,11 @@ 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'."
|
||||
is inserted at the end. See also the command `py-clear-queues'."
|
||||
(interactive "r\nP")
|
||||
(or (< start end)
|
||||
(error "Region is empty"))
|
||||
(let* ((proc (get-process py-which-bufname))
|
||||
(let* ((bufname (process-name proc))
|
||||
(temp (if (memq 'broken-temp-names py-emacs-features)
|
||||
(let
|
||||
((sn py-serial-number)
|
||||
@ -1457,11 +1547,14 @@ is inserted at the end. See also the command `py-clear-queue'."
|
||||
;; execution there.
|
||||
(proc
|
||||
;; use the existing python shell
|
||||
(if (not py-file-queue)
|
||||
(let ((file-queue (gethash proc py-file-queues nil)))
|
||||
(if (not file-queue)
|
||||
(py-execute-file proc file)
|
||||
(message "File %s queued for execution" file))
|
||||
(setq py-file-queue (append py-file-queue (list file)))
|
||||
(setq py-exception-buffer (cons file (current-buffer))))
|
||||
(setq file-queue (append file-queue (list file)))
|
||||
(setq py-exception-buffer (cons file (current-buffer)))
|
||||
)
|
||||
)
|
||||
(t
|
||||
;; TBD: a horrible hack, buy why create new Custom variables?
|
||||
(let ((cmd (concat py-which-shell
|
||||
@ -1565,7 +1658,7 @@ subtleties, including the use of the optional ASYNC argument."
|
||||
(py-execute-region (mark) (point) async)))
|
||||
|
||||
|
||||
(defun py-execute-string (string &optional async)
|
||||
(defun py-execute-string (string proc &optional async)
|
||||
"Send the argument STRING to a Python interpreter.
|
||||
|
||||
If there is a *Python* process buffer it is used.
|
||||
@ -1577,7 +1670,7 @@ subtleties, including the use of the optional ASYNC argument."
|
||||
(set-buffer (get-buffer-create
|
||||
(generate-new-buffer-name " *Python Command*")))
|
||||
(insert string)
|
||||
(py-execute-region (point-min) (point-max) async)))
|
||||
(py-execute-region (point-min) (point-max) proc async)))
|
||||
|
||||
|
||||
|
||||
@ -3251,11 +3344,10 @@ to do so may mean a greater delay in fixing your bug.\n\n")
|
||||
|
||||
|
||||
(defun py-kill-emacs-hook ()
|
||||
"Delete files in `py-file-queue'.
|
||||
"Delete files in `py-file-queues'.
|
||||
These are Python temporary files awaiting execution."
|
||||
(mapcar #'(lambda (filename)
|
||||
(py-safe (delete-file filename)))
|
||||
py-file-queue))
|
||||
(py-clear-queues)
|
||||
)
|
||||
|
||||
;; arrange to kill temp files when Emacs exists
|
||||
(add-hook 'kill-emacs-hook 'py-kill-emacs-hook)
|
||||
@ -3271,17 +3363,32 @@ These are Python temporary files awaiting execution."
|
||||
(goto-char (- current 4))
|
||||
(if (or (search-forward ">>> " current t)
|
||||
(search-forward "... " current t))
|
||||
(python-resume)
|
||||
(save-current-buffer
|
||||
(goto-char current)
|
||||
(for-all-py-procs
|
||||
(lambda (proc)
|
||||
(let ((procbuf (process-buffer proc)))
|
||||
(set-buffer procbuf)
|
||||
(let ((current (point)))
|
||||
(goto-char (point-max))
|
||||
(if (and (eobp) (= (point) (marker-position (process-mark proc))))
|
||||
(let ()
|
||||
(goto-char (- current 4))
|
||||
(if (or (search-forward ">>> " current t)
|
||||
(search-forward "... " current t))
|
||||
(let ()
|
||||
(python-resume proc)
|
||||
)
|
||||
(let ()
|
||||
(goto-char current)
|
||||
))))
|
||||
)))))
|
||||
(let ()
|
||||
(goto-char current)
|
||||
(message "End of buffer")
|
||||
)
|
||||
)
|
||||
)
|
||||
)))
|
||||
(delete-char arg)
|
||||
)
|
||||
)
|
||||
)
|
||||
)))
|
||||
|
||||
|
||||
(defun comint-interrupt-subjob-or-maybe-return (arg)
|
||||
@ -3295,27 +3402,52 @@ These are Python temporary files awaiting execution."
|
||||
(if (or (search-forward ">>> " current t)
|
||||
(search-forward "... " current t))
|
||||
(comint-send-input)
|
||||
(let ()
|
||||
(save-current-buffer
|
||||
(goto-char current)
|
||||
(comint-interrupt-subjob))))
|
||||
(comint-send-input))))
|
||||
(for-all-py-procs
|
||||
(lambda (proc)
|
||||
(let ((procbuf (process-buffer proc)))
|
||||
(set-buffer procbuf)
|
||||
(goto-char (point-max))
|
||||
(if (and (eobp) proc (= (point) (marker-position (process-mark proc))))
|
||||
(comint-interrupt-subjob))
|
||||
)
|
||||
)
|
||||
))
|
||||
)
|
||||
)
|
||||
(comint-send-input)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun py-point-to-max (proc)
|
||||
;; updates the cursor position of a buffer for all windows
|
||||
;; into that buffer
|
||||
(save-current-buffer
|
||||
(let ((procbuf (process-buffer proc)))
|
||||
(mapcar (lambda (window)
|
||||
(set-window-point window (point-max)))
|
||||
(get-buffer-window-list procbuf))
|
||||
(set-buffer procbuf)
|
||||
(goto-char (point-max))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; Function to try to resume panda mainloop
|
||||
(defun python-resume ()
|
||||
(defun python-resume (proc)
|
||||
(interactive)
|
||||
(let* ((curbuf (current-buffer))
|
||||
(proc (get-process py-which-bufname))
|
||||
(procbuf (process-buffer proc))
|
||||
(save-current-buffer
|
||||
(let ((procbuf (process-buffer proc))
|
||||
)
|
||||
(set-buffer procbuf)
|
||||
(insert "run()\n")
|
||||
(py-execute-string "try:\n\trun()\nexcept NameError,e:\n\tif e.__str__() == 'run':\n\t\tpass\n\telse:\n\t\traise\nexcept:\n\traise")
|
||||
(goto-char (point-max))
|
||||
(set-buffer curbuf)
|
||||
(insert "run()\n")
|
||||
(py-execute-string "try:\n\trun()\nexcept NameError,e:\n\tif e.__str__() == 'run':\n\t\tpass\n\telse:\n\t\traise\nexcept:\n\traise" proc)
|
||||
(py-point-to-max proc)
|
||||
))
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
(defun py-redefine-class (&optional async)
|
||||
@ -3328,12 +3460,9 @@ These are Python temporary files awaiting execution."
|
||||
)
|
||||
|
||||
|
||||
(defun py-redefine-class-region (start end &optional async)
|
||||
(defun py-redefine-class-region-for-proc (start end proc)
|
||||
(interactive "r\nP")
|
||||
(or (< start end)
|
||||
(error "Region is empty"))
|
||||
(let* ((proc (get-process py-which-bufname))
|
||||
(temp (if (memq 'broken-temp-names py-emacs-features)
|
||||
(let* ((temp (if (memq 'broken-temp-names py-emacs-features)
|
||||
(let
|
||||
((sn py-serial-number)
|
||||
(pid (and (fboundp 'emacs-pid) (emacs-pid))))
|
||||
@ -3350,6 +3479,19 @@ These are Python temporary files awaiting execution."
|
||||
(py-redefine-class-file proc file)
|
||||
))))
|
||||
|
||||
(defun py-redefine-class-region (start end &optional async)
|
||||
(interactive "r\nP")
|
||||
(or (< start end)
|
||||
(error "Region is empty"))
|
||||
;; run through all the Python processes and redefine the class
|
||||
(save-current-buffer
|
||||
(let ((curbuf (current-buffer)))
|
||||
(for-all-py-procs (lambda (proc)
|
||||
(set-buffer curbuf)
|
||||
(py-redefine-class-region-for-proc start end proc)))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;; Python subprocess utilities and filters
|
||||
(defun py-redefine-class-file (proc filename)
|
||||
@ -3358,8 +3500,7 @@ 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."
|
||||
(interactive)
|
||||
(let ((curbuf (current-buffer))
|
||||
(procbuf (process-buffer proc))
|
||||
(let ((procbuf (process-buffer proc))
|
||||
(cmd (format "from direct.showbase import Finder; Finder.rebindClass(__builtins__.globals(), r'%s')\n" filename))
|
||||
)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user