aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/progmodes/python.el
diff options
context:
space:
mode:
authorKen Manheimer2008-02-21 22:28:13 +0000
committerKen Manheimer2008-02-21 22:28:13 +0000
commit82ede38976aab812724f8c8075c83985ec771074 (patch)
treeba6dda6060ef97352a1f5e0b56ef550a0a378306 /lisp/progmodes/python.el
parent26e99723805dcf1809ffbe209f05722dc82845c3 (diff)
downloademacs-82ede38976aab812724f8c8075c83985ec771074.tar.gz
emacs-82ede38976aab812724f8c8075c83985ec771074.zip
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/progmodes/python.el')
-rw-r--r--lisp/progmodes/python.el195
1 files changed, 146 insertions, 49 deletions
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 9057e51e439..1b6632e0c29 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
545 545
546(defcustom python-pdbtrack-do-tracking-p t 546(defcustom python-pdbtrack-do-tracking-p t
547 "*Controls whether the pdbtrack feature is enabled or not. 547 "*Controls whether the pdbtrack feature is enabled or not.
548
548When non-nil, pdbtrack is enabled in all comint-based buffers, 549When non-nil, pdbtrack is enabled in all comint-based buffers,
549e.g. shell buffers and the *Python* buffer. When using pdb to debug a 550e.g. shell interaction buffers and the *Python* buffer.
550Python program, pdbtrack notices the pdb prompt and displays the 551
551source file and line that the program is stopped at, much the same way 552When using pdb to debug a Python program, pdbtrack notices the
552as gud-mode does for debugging C programs with gdb." 553pdb prompt and presents the line in the source file where the
554program is stopped in a pop-up buffer. It's similar to what
555gud-mode does for debugging C programs with gdb, but without
556having to restart the program."
553 :type 'boolean 557 :type 'boolean
554 :group 'python) 558 :group 'python)
555(make-variable-buffer-local 'python-pdbtrack-do-tracking-p) 559(make-variable-buffer-local 'python-pdbtrack-do-tracking-p)
556 560
561(defcustom python-pdbtrack-minor-mode-string " PDB"
562 "*Minor-mode sign to be displayed when pdbtrack is active."
563 :type 'string
564 :group 'python)
565
566;; Add a designator to the minor mode strings
567(or (assq 'python-pdbtrack-is-tracking-p minor-mode-alist)
568 (push '(python-pdbtrack-is-tracking-p python-pdbtrack-minor-mode-string)
569 minor-mode-alist))
570
557;; Bind python-file-queue before installing the kill-emacs-hook. 571;; Bind python-file-queue before installing the kill-emacs-hook.
558(defvar python-file-queue nil 572(defvar python-file-queue nil
559 "Queue of Python temp files awaiting execution. 573 "Queue of Python temp files awaiting execution.
@@ -562,10 +576,10 @@ Currently-active file is at the head of the list.")
562(defvar python-pdbtrack-is-tracking-p nil) 576(defvar python-pdbtrack-is-tracking-p nil)
563 577
564(defconst python-pdbtrack-stack-entry-regexp 578(defconst python-pdbtrack-stack-entry-regexp
565 "> \\([^(]+\\)(\\([0-9]+\\))[?a-zA-Z0-9_]+()" 579 "^> \\(.*\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_]+\\)()"
566 "Regular expression pdbtrack uses to find a stack trace entry.") 580 "Regular expression pdbtrack uses to find a stack trace entry.")
567 581
568(defconst python-pdbtrack-input-prompt "\n[(<]?pdb[>)]? " 582(defconst python-pdbtrack-input-prompt "\n[(<]*[Pp]db[>)]+ "
569 "Regular expression pdbtrack uses to recognize a pdb prompt.") 583 "Regular expression pdbtrack uses to recognize a pdb prompt.")
570 584
571(defconst python-pdbtrack-track-range 10000 585(defconst python-pdbtrack-track-range 10000
@@ -2375,6 +2389,10 @@ without confirmation."
2375 2389
2376;;;; Modes. 2390;;;; Modes.
2377 2391
2392;; pdb tracking is alert once this file is loaded, but takes no action if
2393;; `python-pdbtrack-do-tracking-p' is nil.
2394(add-hook 'comint-output-filter-functions 'python-pdbtrack-track-stack-file)
2395
2378(defvar outline-heading-end-regexp) 2396(defvar outline-heading-end-regexp)
2379(defvar eldoc-documentation-function) 2397(defvar eldoc-documentation-function)
2380(defvar python-mode-running) ;Dynamically scoped var. 2398(defvar python-mode-running) ;Dynamically scoped var.
@@ -2700,17 +2718,16 @@ This function is appropriate for `comint-output-filter-functions'."
2700 (python-execute-file pyproc (car python-file-queue)))))) 2718 (python-execute-file pyproc (car python-file-queue))))))
2701 2719
2702(defun python-pdbtrack-overlay-arrow (activation) 2720(defun python-pdbtrack-overlay-arrow (activation)
2703 "Activate or de arrow at beginning-of-line in current buffer." 2721 "Activate or deactivate arrow at beginning-of-line in current buffer."
2704 ;; This was derived/simplified from edebug-overlay-arrow 2722 (if activation
2705 (cond (activation 2723 (progn
2706 (setq overlay-arrow-position (make-marker)) 2724 (setq overlay-arrow-position (make-marker)
2707 (setq overlay-arrow-string "=>") 2725 overlay-arrow-string "=>"
2708 (set-marker overlay-arrow-position 2726 python-pdbtrack-is-tracking-p t)
2709 (python-point 'bol) (current-buffer)) 2727 (set-marker overlay-arrow-position
2710 (setq python-pdbtrack-is-tracking-p t)) 2728 (python-point 'bol) (current-buffer)))
2711 (python-pdbtrack-is-tracking-p 2729 (setq overlay-arrow-position nil
2712 (setq overlay-arrow-position nil) 2730 python-pdbtrack-is-tracking-p nil)))
2713 (setq python-pdbtrack-is-tracking-p nil))))
2714 2731
2715(defun python-pdbtrack-track-stack-file (text) 2732(defun python-pdbtrack-track-stack-file (text)
2716 "Show the file indicated by the pdb stack entry line, in a separate window. 2733 "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'."
2718Activity is disabled if the buffer-local variable 2735Activity is disabled if the buffer-local variable
2719`python-pdbtrack-do-tracking-p' is nil. 2736`python-pdbtrack-do-tracking-p' is nil.
2720 2737
2721We depend on the pdb input prompt matching `python-pdbtrack-input-prompt' 2738We depend on the pdb input prompt being a match for
2722at the beginning of the line." 2739`python-pdbtrack-input-prompt'.
2740
2741If the traceback target file path is invalid, we look for the
2742most recently visited python-mode buffer which either has the
2743name of the current function or class, or which defines the
2744function or class. This is to provide for scripts not in the
2745local filesytem (e.g., Zope's 'Script \(Python)', but it's not
2746Zope specific). If you put a copy of the script in a buffer
2747named for the script and activate python-mode, then pdbtrack will
2748find it."
2723 ;; Instead of trying to piece things together from partial text 2749 ;; Instead of trying to piece things together from partial text
2724 ;; (which can be almost useless depending on Emacs version), we 2750 ;; (which can be almost useless depending on Emacs version), we
2725 ;; monitor to the point where we have the next pdb prompt, and then 2751 ;; monitor to the point where we have the next pdb prompt, and then
2726 ;; check all text from comint-last-input-end to process-mark. 2752 ;; check all text from comint-last-input-end to process-mark.
2727 ;; 2753 ;;
2728 ;; KLM: It might be nice to provide an optional override, so this 2754 ;; Also, we're very conservative about clearing the overlay arrow,
2729 ;; routine could be fed debugger output strings as the text 2755 ;; to minimize residue. This means, for instance, that executing
2730 ;; argument, for deliberate application elsewhere. 2756 ;; other pdb commands wipe out the highlight. You can always do a
2731 ;; 2757 ;; 'where' (aka 'w') PDB command to reveal the overlay arrow.
2732 ;; KLM: We're very conservative about clearing the overlay arrow, to 2758
2733 ;; minimize residue. This means, for instance, that executing other
2734 ;; pdb commands wipes out the highlight.
2735 (let* ((origbuf (current-buffer)) 2759 (let* ((origbuf (current-buffer))
2736 (currproc (get-buffer-process origbuf))) 2760 (currproc (get-buffer-process origbuf)))
2761
2737 (if (not (and currproc python-pdbtrack-do-tracking-p)) 2762 (if (not (and currproc python-pdbtrack-do-tracking-p))
2738 (python-pdbtrack-overlay-arrow nil) 2763 (python-pdbtrack-overlay-arrow nil)
2739 (let* (;(origdir default-directory) 2764
2740 (procmark (process-mark currproc)) 2765 (let* ((procmark (process-mark currproc))
2741 (block (buffer-substring (max comint-last-input-end 2766 (block (buffer-substring (max comint-last-input-end
2742 (- procmark 2767 (- procmark
2743 python-pdbtrack-track-range)) 2768 python-pdbtrack-track-range))
2744 procmark)) 2769 procmark))
2745 fname lineno) 2770 target target_fname target_lineno target_buffer)
2771
2746 (if (not (string-match (concat python-pdbtrack-input-prompt "$") block)) 2772 (if (not (string-match (concat python-pdbtrack-input-prompt "$") block))
2747 (python-pdbtrack-overlay-arrow nil) 2773 (python-pdbtrack-overlay-arrow nil)
2748 (if (not (string-match 2774
2749 (concat ".*" python-pdbtrack-stack-entry-regexp ".*") 2775 (setq target (python-pdbtrack-get-source-buffer block))
2750 block)) 2776
2751 (python-pdbtrack-overlay-arrow nil) 2777 (if (stringp target)
2752 (setq fname (match-string 1 block) 2778 (progn
2753 lineno (match-string 2 block)) 2779 (python-pdbtrack-overlay-arrow nil)
2754 (if (file-exists-p fname) 2780 (message "pdbtrack: %s" target))
2755 (progn 2781
2756 (find-file-other-window fname) 2782 (setq target_lineno (car target)
2757 (goto-line (string-to-number lineno)) 2783 target_buffer (cadr target)
2758 (message "pdbtrack: line %s, file %s" lineno fname) 2784 target_fname (buffer-file-name target_buffer))
2759 (python-pdbtrack-overlay-arrow t) 2785 (switch-to-buffer-other-window target_buffer)
2760 (pop-to-buffer origbuf t) ) 2786 (goto-line target_lineno)
2761 (if (= (elt fname 0) ?\<) 2787 (message "pdbtrack: line %s, file %s" target_lineno target_fname)
2762 (message "pdbtrack: (Non-file source: '%s')" fname) 2788 (python-pdbtrack-overlay-arrow t)
2763 (message "pdbtrack: File not found: %s" fname))))))))) 2789 (pop-to-buffer origbuf t)
2790 ;; in large shell buffers, above stuff may cause point to lag output
2791 (goto-char procmark)
2792 )))))
2793 )
2794
2795(defun python-pdbtrack-get-source-buffer (block)
2796 "Return line number and buffer of code indicated by block's traceback text.
2797
2798We look first to visit the file indicated in the trace.
2799
2800Failing that, we look for the most recently visited python-mode buffer
2801with the same name or having the named function.
2802
2803If we're unable find the source code we return a string describing the
2804problem."
2805
2806 (if (not (string-match python-pdbtrack-stack-entry-regexp block))
2807
2808 "Traceback cue not found"
2809
2810 (let* ((filename (match-string 1 block))
2811 (lineno (string-to-number (match-string 2 block)))
2812 (funcname (match-string 3 block))
2813 funcbuffer)
2814
2815 (cond ((file-exists-p filename)
2816 (list lineno (find-file-noselect filename)))
2817
2818 ((setq funcbuffer (python-pdbtrack-grub-for-buffer funcname lineno))
2819 (if (string-match "/Script (Python)$" filename)
2820 ;; Add in number of lines for leading '##' comments:
2821 (setq lineno
2822 (+ lineno
2823 (save-excursion
2824 (set-buffer funcbuffer)
2825 (if (equal (point-min)(point-max))
2826 0
2827 (count-lines
2828 (point-min)
2829 (max (point-min)
2830 (string-match "^\\([^#]\\|#[^#]\\|#$\\)"
2831 (buffer-substring
2832 (point-min) (point-max)))
2833 )))))))
2834 (list lineno funcbuffer))
2835
2836 ((= (elt filename 0) ?\<)
2837 (format "(Non-file source: '%s')" filename))
2838
2839 (t (format "Not found: %s(), %s" funcname filename)))
2840 )
2841 )
2842 )
2843
2844(defun python-pdbtrack-grub-for-buffer (funcname lineno)
2845 "Find recent python-mode buffer named, or having function named funcname."
2846 (let ((buffers (buffer-list))
2847 buf
2848 got)
2849 (while (and buffers (not got))
2850 (setq buf (car buffers)
2851 buffers (cdr buffers))
2852 (if (and (save-excursion (set-buffer buf)
2853 (string= major-mode "python-mode"))
2854 (or (string-match funcname (buffer-name buf))
2855 (string-match (concat "^\\s-*\\(def\\|class\\)\\s-+"
2856 funcname "\\s-*(")
2857 (save-excursion
2858 (set-buffer buf)
2859 (buffer-substring (point-min)
2860 (point-max))))))
2861 (setq got buf)))
2862 got))
2764 2863
2765(defun python-toggle-shells (arg) 2864(defun python-toggle-shells (arg)
2766 "Toggles between the CPython and JPython shells. 2865 "Toggles between the CPython and JPython shells.
@@ -2857,14 +2956,12 @@ filter."
2857 (switch-to-buffer-other-window 2956 (switch-to-buffer-other-window
2858 (apply 'make-comint python-which-bufname python-which-shell nil args)) 2957 (apply 'make-comint python-which-bufname python-which-shell nil args))
2859 (make-local-variable 'comint-prompt-regexp) 2958 (make-local-variable 'comint-prompt-regexp)
2860 (set-process-sentinel (get-buffer-process (current-buffer)) 'python-sentinel) 2959 (set-process-sentinel (get-buffer-process (current-buffer))
2960 'python-sentinel)
2861 (setq comint-prompt-regexp "^>>> \\|^[.][.][.] \\|^(pdb) ") 2961 (setq comint-prompt-regexp "^>>> \\|^[.][.][.] \\|^(pdb) ")
2862 (add-hook 'comint-output-filter-functions 2962 (add-hook 'comint-output-filter-functions
2863 'python-comint-output-filter-function nil t) 2963 'python-comint-output-filter-function nil t)
2864 ;; pdbtrack 2964 ;; pdbtrack
2865 (add-hook 'comint-output-filter-functions
2866 'python-pdbtrack-track-stack-file nil t)
2867 (setq python-pdbtrack-do-tracking-p t)
2868 (set-syntax-table python-mode-syntax-table) 2965 (set-syntax-table python-mode-syntax-table)
2869 (use-local-map python-shell-map))) 2966 (use-local-map python-shell-map)))
2870 2967