[Python-Dev] Enhancement to pdb in gud.el (original) (raw)
Nick Roberts nick at nick.uklinux.net
Sat Sep 20 11:20:50 EDT 2003
- Previous message: [Python-Dev] Enhancement to pdb in gud.el
- Next message: [Python-Dev] Enhancement to pdb in gud.el
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Kevin J. Butler writes:
...
After my patch: (Pdb) cl 3 Deleted breakpoint 3 at z:\work\wm\wm.py:136 (Pdb) cl wm.py:17 Deleted breakpoint 5 at z:\work\wm\wm.py:17
I've applied your patch manually to my files bdb.py and pdb.py (I have 2.2) and it appears to work. If you load the file below in Emacs (M-x eval-buffer or M-x load-file), then type M-x pdb, the debugger (with your patch) should work with breakpoint icons in the display margin. Emacs must be a version from the CVS repository to work straight away. This will also give you buttons for debugging if you turn the toolbar on (M-x tool-bar-mode).
I've tested it on GNU/Linux but it should work on Windows too if I've defined the regexp correctly.
I've just noticed that you can enable/disable breakpoints in python. In my mode for gdb, the breakpoints are greyed out when the breakpoints become disabled. I could do this for python too if these commands were changed to emit a message.
If your patches are accepted (by SF?) then I will integrate my changes into gud.el in the Emacs CVS repository.
Nick
(require 'gud)
(defun gud-sentinel (proc msg) (cond ((null (buffer-name (process-buffer proc))) ;; buffer killed ;; Stop displaying an arrow in a source file. (setq overlay-arrow-position nil) (set-process-buffer proc nil) (if (memq gud-minor-mode-type '(gdba pdb)) (gdb-reset) (gud-reset))) ((memq (process-status proc) '(signal exit)) ;; Stop displaying an arrow in a source file. (setq overlay-arrow-position nil) (with-current-buffer gud-comint-buffer (if (memq gud-minor-mode '(gdba pdb)) (gdb-reset) (gud-reset))) (let* ((obuf (current-buffer))) ;; save-excursion isn't the right thing if ;; process-buffer is current-buffer (unwind-protect (progn ;; Write something in compilation and hack its mode line, (set-buffer (process-buffer proc)) ;; Fix the mode line. (setq mode-line-process (concat ":" (symbol-name (process-status proc)))) (force-mode-line-update) (if (eobp) (insert ?\n mode-name " " msg) (save-excursion (goto-char (point-max)) (insert ?\n mode-name " " msg))) ;; If buffer and mode line will show that the process ;; is dead, we can delete it now. Otherwise it ;; will stay around until M-x list-processes. (delete-process proc)) ;; Restore old buffer, but don't restore old point ;; if obuf is the gud buffer. (set-buffer obuf))))))
(defun gdb-reset () "Exit a debugging session cleanly by killing the gdb buffers and resetting the source buffers." (dolist (buffer (buffer-list)) (if (not (eq buffer gud-comint-buffer)) (with-current-buffer buffer (if (memq gud-minor-mode '(gdba pdb)) (if (string-match "^*.+*$" (buffer-name)) (kill-buffer nil) (if (display-images-p) (remove-images (point-min) (point-max)) (gdb-remove-strings (point-min) (point-max))) (setq left-margin-width 0) (setq gud-minor-mode nil) (kill-local-variable 'tool-bar-map) (setq gud-running nil) (if (get-buffer-window (current-buffer)) (set-window-margins (get-buffer-window (current-buffer)) left-margin-width right-margin-width))))))))
(defun gdb-put-string (putstring pos)
"Put string PUTSTRING in front of POS in the current buffer.
PUTSTRING is displayed by putting an overlay into the current buffer with a
before-string' STRING that has a
display' property whose value is
PUTSTRING."
(let ((gdb-string "x")
(buffer (current-buffer)))
(let ((overlay (make-overlay pos pos buffer))
(prop (list (list 'margin 'left-margin) putstring)))
(put-text-property 0 (length gdb-string) 'display prop gdb-string)
(overlay-put overlay 'put-break t)
(overlay-put overlay 'before-string gdb-string))))
(defun gdb-remove-strings (start end &optional buffer) "Remove strings between START and END in BUFFER. Remove only strings that were put in BUFFER with calls to `put-string'. BUFFER nil or omitted means use the current buffer." (unless buffer (setq buffer (current-buffer))) (let ((overlays (overlays-in start end))) (while overlays (let ((overlay (car overlays))) (when (overlay-get overlay 'put-break) (delete-overlay overlay))) (setq overlays (cdr overlays)))))
(defconst breakpoint-xpm-data "/* XPM */ static char magick[] = { / columns rows colors chars-per-pixel / "12 12 2 1", " c red", "+ c None", / pixels */ "++++++++++++", "+++ +++", "++ ++", "+ +", "+ +", "+ +", "+ +", "+ +", "+ +", "++ ++", "+++ +++", "++++++++++++" };" "XPM data used for breakpoint icon.")
(defconst breakpoint-enabled-pbm-data "P1 12 12", 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0" "PBM data used for enabled breakpoint icon.")
(defvar breakpoint-enabled-icon (find-image `((:type xpm :data ,breakpoint-xpm-data) (:type pbm :data ,breakpoint-enabled-pbm-data))) "Icon for enabled breakpoint in display margin")
;; ====================================================================== ;; pdb (Python debugger) functions
;; History of argument lists passed to pdb. (defvar gud-pdb-history nil)
;; Last group is for return value, e.g. "> test.py(2)foo()->None" ;; Either file or function name may be omitted: "> (0)?()" (defvar gud-pdb-marker-regexp "^> \([-a-zA-Z0-9_/.:\]*\|\)(\([0-9]+\))\([a-zA-Z0-9_]*\|\?\)()\(->[^\n]*\)?\n") (defvar gud-pdb-marker-regexp-file-group 1) (defvar gud-pdb-marker-regexp-line-group 2) (defvar gud-pdb-marker-regexp-fnname-group 3)
(defvar gud-pdb-marker-regexp-start "^> ")
(defvar gud-pdb-marker-regexp-breakpoint "reakpoint [0-9]+ at \(\([a-zA-Z]:\)?[^:\n]*\):\([0-9]*\)\n")
;; There's no guarantee that Emacs will hand the filter the entire ;; marker at once; it could be broken up across several strings. We ;; might even receive a big chunk with several markers in it. If we ;; receive a chunk of text which looks like it might contain the ;; beginning of a marker, we save it here between calls to the ;; filter. (defun gud-pdb-marker-filter (string) (setq gud-marker-acc (concat gud-marker-acc string)) (let ((output ""))
;; Process all the complete markers in this chunk.
(while (string-match gud-pdb-marker-regexp gud-marker-acc)
(setq
;; Extract the frame position from the marker.
gud-last-frame
(let ((file (match-string gud-pdb-marker-regexp-file-group
gud-marker-acc))
(line (string-to-int
(match-string gud-pdb-marker-regexp-line-group
gud-marker-acc))))
(if (string-equal file "<string>")
gud-last-frame
(cons file line)))
;; Output everything instead of the below
output (concat output (substring gud-marker-acc 0 (match-end 0)))
;; ;; Append any text before the marker to the output we're going ;; ;; to return - we don't include the marker in this text. ;; output (concat output ;; (substring gud-marker-acc 0 (match-beginning 0))) ;; Set the accumulator to the remaining text. gud-marker-acc (substring gud-marker-acc (match-end 0))))
(if (string-match (concat "B" gud-pdb-marker-regexp-breakpoint)
gud-marker-acc)
(let ((file (match-string 1 gud-marker-acc))
(line (match-string 3 gud-marker-acc)))
(gud-pdb-insert-breakpoint file line)))
(if (string-match (concat "Deleted b" gud-pdb-marker-regexp-breakpoint)
gud-marker-acc)
(let ((file (match-string 1 gud-marker-acc))
(line (match-string 3 gud-marker-acc)))
(gud-pdb-remove-breakpoint file line)))
;; Does the remaining text look like it might end with the
;; beginning of another marker? If it does, then keep it in
;; gud-marker-acc until we receive the rest of it. Since we
;; know the full marker regexp above failed, it's pretty simple to
;; test for marker starts.
(if (string-match gud-pdb-marker-regexp-start gud-marker-acc)
(progn
;; Everything before the potential marker start can be output.
(setq output (concat output (substring gud-marker-acc
0 (match-beginning 0))))
;; Everything after, we save, to combine with later input.
(setq gud-marker-acc
(substring gud-marker-acc (match-beginning 0))))
(setq output (concat output gud-marker-acc)
gud-marker-acc ""))
output))
(defun gud-pdb-insert-breakpoint (file line) (with-current-buffer (find-file-noselect file) (save-current-buffer (set (make-local-variable 'gud-minor-mode) 'pdb) (set (make-local-variable 'tool-bar-map) gud-tool-bar-map) (setq left-margin-width 2) (if (get-buffer-window (current-buffer)) (set-window-margins (get-buffer-window (current-buffer)) left-margin-width right-margin-width))) (save-excursion (goto-line (string-to-number line)) (let ((start (progn (beginning-of-line) (- (point) 1))) (end (progn (end-of-line) (+ (point) 1)))) (if (display-images-p) (progn (remove-images start end) (put-image breakpoint-enabled-icon (+ start 1) "breakpoint icon enabled" 'left-margin)) (gdb-remove-strings start end) (gdb-put-string "B" (+ start 1)))))))
(defun gud-pdb-remove-breakpoint (file line) (with-current-buffer (find-file-noselect file) (save-excursion (goto-line (string-to-number line)) (let ((start (progn (beginning-of-line) (- (point) 1))) (end (progn (end-of-line) (+ (point) 1)))) (if (display-images-p) (remove-images start end) (gdb-remove-strings start end))))))
(defcustom gud-pdb-command-name "pdb" "File name for executing the Python debugger. This should be an executable on your path, or an absolute file name." :type 'string :group 'gud)
(defun pdb (command-line) "Run pdb on program FILE in buffer `gud-FILE'. The directory containing FILE becomes the initial working directory and source-file directory for your debugger." (interactive (list (gud-query-cmdline 'pdb)))
(gud-common-init command-line nil 'gud-pdb-marker-filter) (set (make-local-variable 'gud-minor-mode) 'pdb)
(gud-def gud-break "break %l" "\C-b" "Set breakpoint at current line.") (gud-def gud-remove "clear %f:%l" "\C-d" "Remove breakpoint at current line") (gud-def gud-step "step" "\C-s" "Step one source line with display.") (gud-def gud-next "next" "\C-n" "Step one line (skip functions).") (gud-def gud-cont "continue" "\C-r" "Continue with display.") (gud-def gud-finish "return" "\C-f" "Finish executing current function.") (gud-def gud-up "up" "<" "Up one stack frame.") (gud-def gud-down "down" ">" "Down one stack frame.") (gud-def gud-print "p %e" "\C-p" "Evaluate Python expression at point.") ;; Is this right? (gud-def gud-statement "! %e" "\C-e" "Execute Python statement at point.")
;; (setq comint-prompt-regexp "^(.*pdb[+]?) *") (setq comint-prompt-regexp "^(Pdb) *") (setq paragraph-start comint-prompt-regexp) (run-hooks 'pdb-mode-hook))
- Previous message: [Python-Dev] Enhancement to pdb in gud.el
- Next message: [Python-Dev] Enhancement to pdb in gud.el
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]