aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorKen Manheimer <[email protected]>2008-02-21 22:28:13 +0000
committerKen Manheimer <[email protected]>2008-02-21 22:28:13 +0000
commit82ede38976aab812724f8c8075c83985ec771074 (patch)
treeba6dda6060ef97352a1f5e0b56ef550a0a378306 /lisp
parent26e99723805dcf1809ffbe209f05722dc82845c3 (diff)
Revise pdbtrack functionality to incorporate advances in python-mode.el.
(I'm doing this python.el checkin with some byte-compiler warnings. These warnings existed before Nick Roberts or I applied any of the pdbtrack changes, and look very clearly like preexisting, incomplete adoption of code from python-mode.el. I'm going to next look at settling those warnings, though I don't have time for a major reconciliation of the two python-mode implementations.) (python-pdbtrack-toggle-stack-tracking): Clarify docstring. (python-pdbtrack-minor-mode-string): A sign indicating that pdb tracking is happening. (python-pdbtrack-stack-entry-regexp): Better recognize stack traces. (python-pdbtrack-input-prompt): Better recognize PDB prompts. (add python-pdbtrack-track-stack-file to comint-output-filter-functions): Tracking is plugged in to all comint buffers once python.el is loaded. (python-pdbtrack-overlay-arrow): Toggle activation of `python-pdbtrack-minor-mode-string' in addition to the overlay arrow. (python-pdbtrack-track-stack-file): Use new `python-pdbtrack-get-source-buffer' for more flexible access to debugging source files. (python-pdbtrack-get-source-buffer): Identify debugging target buffer according to pdb stack trace, optionally using new `python-pdbtrack-grub-for-buffer' if file is not locally available. (python-pdbtrack-grub-for-buffer): Find most recent python-mode named buffer, or having function with indicated name. (python-shell): Remove comint-output-filter-functions hook addition, it's being done elsewhere. Wrap long line.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog27
-rw-r--r--lisp/progmodes/python.el195
2 files changed, 173 insertions, 49 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index d7e1686af1..bec4431dba 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,30 @@
+2008-02-21 Ken Manheimer <[email protected]>
+
+ * python.el (python-pdbtrack-toggle-stack-tracking): Clarify
+ docstring.
+ (python-pdbtrack-minor-mode-string): A sign indicating that pdb
+ tracking is happening.
+ (python-pdbtrack-stack-entry-regexp): Better recognize stack
+ traces.
+ (python-pdbtrack-input-prompt): Better recognize PDB prompts.
+ (add python-pdbtrack-track-stack-file to
+ comint-output-filter-functions): Tracking is plugged in to all
+ comint buffers once python.el is loaded.
+ (python-pdbtrack-overlay-arrow): Toggle activation of
+ `python-pdbtrack-minor-mode-string' in addition to the overlay
+ arrow.
+ (python-pdbtrack-track-stack-file): Use new
+ `python-pdbtrack-get-source-buffer' for more flexible access to
+ debugging source files.
+ (python-pdbtrack-get-source-buffer): Identify debugging target
+ buffer according to pdb stack trace, optionally using new
+ `python-pdbtrack-grub-for-buffer' if file is not locally
+ available.
+ (python-pdbtrack-grub-for-buffer): Find most recent python-mode
+ named buffer, or having function with indicated name.
+ (python-shell): Remove comint-output-filter-functions hook
+ addition, it's being done elsewhere. Wrap long line.
+
2008-02-21 Michael Olson <[email protected]>
* net/json.el: Install new file by Edward O'Connor. json.el is a
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 9057e51e43..1b6632e0c2 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -545,15 +545,29 @@ mode buffer is visited during an Emacs session. After that, use
(defcustom python-pdbtrack-do-tracking-p t
"*Controls whether the pdbtrack feature is enabled or not.
+
When non-nil, pdbtrack is enabled in all comint-based buffers,
-e.g. shell buffers and the *Python* buffer. When using pdb to debug a
-Python program, pdbtrack notices the pdb prompt and displays the
-source file and line that the program is stopped at, much the same way
-as gud-mode does for debugging C programs with gdb."
+e.g. shell interaction buffers and the *Python* buffer.
+
+When using pdb to debug a Python program, pdbtrack notices the
+pdb prompt and presents the line in the source file where the
+program is stopped in a pop-up buffer. It's similar to what
+gud-mode does for debugging C programs with gdb, but without
+having to restart the program."
:type 'boolean
:group 'python)
(make-variable-buffer-local 'python-pdbtrack-do-tracking-p)
+(defcustom python-pdbtrack-minor-mode-string " PDB"
+ "*Minor-mode sign to be displayed when pdbtrack is active."
+ :type 'string
+ :group 'python)
+
+;; Add a designator to the minor mode strings
+(or (assq 'python-pdbtrack-is-tracking-p minor-mode-alist)
+ (push '(python-pdbtrack-is-tracking-p python-pdbtrack-minor-mode-string)
+ minor-mode-alist))
+
;; Bind python-file-queue before installing the kill-emacs-hook.
(defvar python-file-queue nil
"Queue of Python temp files awaiting execution.
@@ -562,10 +576,10 @@ Currently-active file is at the head of the list.")
(defvar python-pdbtrack-is-tracking-p nil)
(defconst python-pdbtrack-stack-entry-regexp
- "> \\([^(]+\\)(\\([0-9]+\\))[?a-zA-Z0-9_]+()"
+ "^> \\(.*\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
"Regular expression pdbtrack uses to find a stack trace entry.")
-(defconst python-pdbtrack-input-prompt "\n[(<]?pdb[>)]? "
+(defconst python-pdbtrack-input-prompt "\n[(<]*[Pp]db[>)]+ "
"Regular expression pdbtrack uses to recognize a pdb prompt.")
(defconst python-pdbtrack-track-range 10000
@@ -2375,6 +2389,10 @@ without confirmation."
;;;; Modes.
+;; pdb tracking is alert once this file is loaded, but takes no action if
+;; `python-pdbtrack-do-tracking-p' is nil.
+(add-hook 'comint-output-filter-functions 'python-pdbtrack-track-stack-file)
+
(defvar outline-heading-end-regexp)
(defvar eldoc-documentation-function)
(defvar python-mode-running) ;Dynamically scoped var.
@@ -2700,17 +2718,16 @@ This function is appropriate for `comint-output-filter-functions'."
(python-execute-file pyproc (car python-file-queue))))))
(defun python-pdbtrack-overlay-arrow (activation)
- "Activate or de arrow at beginning-of-line in current buffer."
- ;; This was derived/simplified from edebug-overlay-arrow
- (cond (activation
- (setq overlay-arrow-position (make-marker))
- (setq overlay-arrow-string "=>")
- (set-marker overlay-arrow-position
- (python-point 'bol) (current-buffer))
- (setq python-pdbtrack-is-tracking-p t))
- (python-pdbtrack-is-tracking-p
- (setq overlay-arrow-position nil)
- (setq python-pdbtrack-is-tracking-p nil))))
+ "Activate or deactivate arrow at beginning-of-line in current buffer."
+ (if activation
+ (progn
+ (setq overlay-arrow-position (make-marker)
+ overlay-arrow-string "=>"
+ python-pdbtrack-is-tracking-p t)
+ (set-marker overlay-arrow-position
+ (python-point 'bol) (current-buffer)))
+ (setq overlay-arrow-position nil
+ python-pdbtrack-is-tracking-p nil)))
(defun python-pdbtrack-track-stack-file (text)
"Show the file indicated by the pdb stack entry line, in a separate window.
@@ -2718,49 +2735,131 @@ This function is appropriate for `comint-output-filter-functions'."
Activity is disabled if the buffer-local variable
`python-pdbtrack-do-tracking-p' is nil.
-We depend on the pdb input prompt matching `python-pdbtrack-input-prompt'
-at the beginning of the line."
+We depend on the pdb input prompt being a match for
+`python-pdbtrack-input-prompt'.
+
+If the traceback target file path is invalid, we look for the
+most recently visited python-mode buffer which either has the
+name of the current function or class, or which defines the
+function or class. This is to provide for scripts not in the
+local filesytem (e.g., Zope's 'Script \(Python)', but it's not
+Zope specific). If you put a copy of the script in a buffer
+named for the script and activate python-mode, then pdbtrack will
+find it."
;; Instead of trying to piece things together from partial text
;; (which can be almost useless depending on Emacs version), we
;; monitor to the point where we have the next pdb prompt, and then
;; check all text from comint-last-input-end to process-mark.
;;
- ;; KLM: It might be nice to provide an optional override, so this
- ;; routine could be fed debugger output strings as the text
- ;; argument, for deliberate application elsewhere.
- ;;
- ;; KLM: We're very conservative about clearing the overlay arrow, to
- ;; minimize residue. This means, for instance, that executing other
- ;; pdb commands wipes out the highlight.
+ ;; Also, we're very conservative about clearing the overlay arrow,
+ ;; to minimize residue. This means, for instance, that executing
+ ;; other pdb commands wipe out the highlight. You can always do a
+ ;; 'where' (aka 'w') PDB command to reveal the overlay arrow.
+
(let* ((origbuf (current-buffer))
(currproc (get-buffer-process origbuf)))
+
(if (not (and currproc python-pdbtrack-do-tracking-p))
(python-pdbtrack-overlay-arrow nil)
- (let* (;(origdir default-directory)
- (procmark (process-mark currproc))
+
+ (let* ((procmark (process-mark currproc))
(block (buffer-substring (max comint-last-input-end
(- procmark
python-pdbtrack-track-range))
procmark))
- fname lineno)
+ target target_fname target_lineno target_buffer)
+
(if (not (string-match (concat python-pdbtrack-input-prompt "$") block))
(python-pdbtrack-overlay-arrow nil)
- (if (not (string-match
- (concat ".*" python-pdbtrack-stack-entry-regexp ".*")
- block))
- (python-pdbtrack-overlay-arrow nil)
- (setq fname (match-string 1 block)
- lineno (match-string 2 block))
- (if (file-exists-p fname)
- (progn
- (find-file-other-window fname)
- (goto-line (string-to-number lineno))
- (message "pdbtrack: line %s, file %s" lineno fname)
- (python-pdbtrack-overlay-arrow t)
- (pop-to-buffer origbuf t) )
- (if (= (elt fname 0) ?\<)
- (message "pdbtrack: (Non-file source: '%s')" fname)
- (message "pdbtrack: File not found: %s" fname)))))))))
+
+ (setq target (python-pdbtrack-get-source-buffer block))
+
+ (if (stringp target)
+ (progn
+ (python-pdbtrack-overlay-arrow nil)
+ (message "pdbtrack: %s" target))
+
+ (setq target_lineno (car target)
+ target_buffer (cadr target)
+ target_fname (buffer-file-name target_buffer))
+ (switch-to-buffer-other-window target_buffer)
+ (goto-line target_lineno)
+ (message "pdbtrack: line %s, file %s" target_lineno target_fname)
+ (python-pdbtrack-overlay-arrow t)
+ (pop-to-buffer origbuf t)
+ ;; in large shell buffers, above stuff may cause point to lag output
+ (goto-char procmark)
+ )))))
+ )
+
+(defun python-pdbtrack-get-source-buffer (block)
+ "Return line number and buffer of code indicated by block's traceback text.
+
+We look first to visit the file indicated in the trace.
+
+Failing that, we look for the most recently visited python-mode buffer
+with the same name or having the named function.
+
+If we're unable find the source code we return a string describing the
+problem."
+
+ (if (not (string-match python-pdbtrack-stack-entry-regexp block))
+
+ "Traceback cue not found"
+
+ (let* ((filename (match-string 1 block))
+ (lineno (string-to-number (match-string 2 block)))
+ (funcname (match-string 3 block))
+ funcbuffer)
+
+ (cond ((file-exists-p filename)
+ (list lineno (find-file-noselect filename)))
+
+ ((setq funcbuffer (python-pdbtrack-grub-for-buffer funcname lineno))
+ (if (string-match "/Script (Python)$" filename)
+ ;; Add in number of lines for leading '##' comments:
+ (setq lineno
+ (+ lineno
+ (save-excursion
+ (set-buffer funcbuffer)
+ (if (equal (point-min)(point-max))
+ 0
+ (count-lines
+ (point-min)
+ (max (point-min)
+ (string-match "^\\([^#]\\|#[^#]\\|#$\\)"
+ (buffer-substring
+ (point-min) (point-max)))
+ )))))))
+ (list lineno funcbuffer))
+
+ ((= (elt filename 0) ?\<)
+ (format "(Non-file source: '%s')" filename))
+
+ (t (format "Not found: %s(), %s" funcname filename)))
+ )
+ )
+ )
+
+(defun python-pdbtrack-grub-for-buffer (funcname lineno)
+ "Find recent python-mode buffer named, or having function named funcname."
+ (let ((buffers (buffer-list))
+ buf
+ got)
+ (while (and buffers (not got))
+ (setq buf (car buffers)
+ buffers (cdr buffers))
+ (if (and (save-excursion (set-buffer buf)
+ (string= major-mode "python-mode"))
+ (or (string-match funcname (buffer-name buf))
+ (string-match (concat "^\\s-*\\(def\\|class\\)\\s-+"
+ funcname "\\s-*(")
+ (save-excursion
+ (set-buffer buf)
+ (buffer-substring (point-min)
+ (point-max))))))
+ (setq got buf)))
+ got))
(defun python-toggle-shells (arg)
"Toggles between the CPython and JPython shells.
@@ -2857,14 +2956,12 @@ filter."
(switch-to-buffer-other-window
(apply 'make-comint python-which-bufname python-which-shell nil args))
(make-local-variable 'comint-prompt-regexp)
- (set-process-sentinel (get-buffer-process (current-buffer)) 'python-sentinel)
+ (set-process-sentinel (get-buffer-process (current-buffer))
+ 'python-sentinel)
(setq comint-prompt-regexp "^>>> \\|^[.][.][.] \\|^(pdb) ")
(add-hook 'comint-output-filter-functions
'python-comint-output-filter-function nil t)
;; pdbtrack
- (add-hook 'comint-output-filter-functions
- 'python-pdbtrack-track-stack-file nil t)
- (setq python-pdbtrack-do-tracking-p t)
(set-syntax-table python-mode-syntax-table)
(use-local-map python-shell-map)))