aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrii Kolomoiets2019-11-02 18:08:13 +0200
committerEli Zaretskii2019-11-07 18:53:04 +0200
commite50587b1db8475fd45e6668f97ca7bc28b798996 (patch)
treee51d7e5dd91759fa98780b1799032e8aa6411ce2
parent3df1cf75f2f2be9549b6ffe3649387d2b4246f06 (diff)
downloademacs-e50587b1db8475fd45e6668f97ca7bc28b798996.tar.gz
emacs-e50587b1db8475fd45e6668f97ca7bc28b798996.zip
python.el: Pdbtracking improvements
Allow not to kill buffers when pdbtracking session is finished. Pdbtracking session considered finished judging from the user input. * lisp/progmodes/python.el (python-pdbtrack-kill-buffers): New customizable variable. (python-pdbtrack-set-tracked-buffer): Use it. (python-pdbtrack-unset-tracked-buffer) (python-pdbtrack-tracking-finish): New functions. (python-pdbtrack-continue-command, python-pdbtrack-exit-command): New customizable variables. (python-pdbtrack-process-sentinel): New function. Finish pdbtracking session when process is killed. (python-pdbtrack-prev-command-continue): New variable. (python-pdbtrack-comint-input-filter-function): New function. Finish pdbtracking session based on commands sent to pdb. (python-pdbtrack-comint-output-filter-function): Unset/set tracking buffer if looking at pdb prompt; finish pdbtracking session if filename of current stack frame starts with "<" e.g. "<stdin>". (python-pdbtrack-comint-output-filter-function): Don't override overlay-arrow-string. (python-pdbtrack-setup-tracking): New function. (inferior-python-mode): Use it. (python-pdbtrack-stacktrace-info-regexp): Default value is changed. Must also match lines with filename like "<stdin>" and "<string>". * etc/NEWS: Mention python-pdbtrack-kill-buffers
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/progmodes/python.el160
2 files changed, 140 insertions, 25 deletions
diff --git a/etc/NEWS b/etc/NEWS
index e5d0fc1c6cf..2e4f938060f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1445,6 +1445,11 @@ unescaping text.
1445The maximum level is used by default; customize 1445The maximum level is used by default; customize
1446'font-lock-maximum-decoration' to tone down the decoration. 1446'font-lock-maximum-decoration' to tone down the decoration.
1447 1447
1448---
1449*** New user option 'python-pdbtrack-kill-buffers'.
1450If nil, buffers opened during pdbtracking session are not killed when
1451pdbtracking session is finished.
1452
1448** Help 1453** Help
1449 1454
1450--- 1455---
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index bdc0f1cd96f..e672645c734 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -2785,7 +2785,6 @@ variable.
2785 (set (make-local-variable 'comint-output-filter-functions) 2785 (set (make-local-variable 'comint-output-filter-functions)
2786 '(ansi-color-process-output 2786 '(ansi-color-process-output
2787 python-shell-comint-watch-for-first-prompt-output-filter 2787 python-shell-comint-watch-for-first-prompt-output-filter
2788 python-pdbtrack-comint-output-filter-function
2789 python-comint-postoutput-scroll-to-bottom 2788 python-comint-postoutput-scroll-to-bottom
2790 comint-watch-for-password-prompt)) 2789 comint-watch-for-password-prompt))
2791 (set (make-local-variable 'compilation-error-regexp-alist) 2790 (set (make-local-variable 'compilation-error-regexp-alist)
@@ -2794,12 +2793,11 @@ variable.
2794 #'python-shell-completion-at-point nil 'local) 2793 #'python-shell-completion-at-point nil 'local)
2795 (define-key inferior-python-mode-map "\t" 2794 (define-key inferior-python-mode-map "\t"
2796 'python-shell-completion-complete-or-indent) 2795 'python-shell-completion-complete-or-indent)
2797 (make-local-variable 'python-pdbtrack-buffers-to-kill)
2798 (make-local-variable 'python-pdbtrack-tracked-buffer)
2799 (make-local-variable 'python-shell-internal-last-output) 2796 (make-local-variable 'python-shell-internal-last-output)
2800 (when python-shell-font-lock-enable 2797 (when python-shell-font-lock-enable
2801 (python-shell-font-lock-turn-on)) 2798 (python-shell-font-lock-turn-on))
2802 (compilation-shell-minor-mode 1)) 2799 (compilation-shell-minor-mode 1)
2800 (python-pdbtrack-setup-tracking))
2803 2801
2804(defun python-shell-make-comint (cmd proc-name &optional show internal) 2802(defun python-shell-make-comint (cmd proc-name &optional show internal)
2805 "Create a Python shell comint buffer. 2803 "Create a Python shell comint buffer.
@@ -3728,19 +3726,72 @@ If not try to complete."
3728;;; PDB Track integration 3726;;; PDB Track integration
3729 3727
3730(defcustom python-pdbtrack-activate t 3728(defcustom python-pdbtrack-activate t
3731 "Non-nil makes Python shell enable pdbtracking." 3729 "Non-nil makes Python shell enable pdbtracking.
3730Pdbtracking would open the file for current stack frame found in pdb output by
3731`python-pdbtrack-stacktrace-info-regexp' and add overlay arrow in currently
3732inspected line in that file.
3733
3734After command listed in `python-pdbtrack-continue-command' or
3735`python-pdbtrack-exit-command' is sent to pdb, pdbtracking session is
3736considered over. Overlay arrow will be removed from currentry tracked
3737buffer. Additionally, if `python-pdbtrack-kill-buffers' is non-nil, all
3738files opened by pdbtracking will be killed."
3732 :type 'boolean 3739 :type 'boolean
3733 :group 'python 3740 :group 'python
3734 :safe 'booleanp) 3741 :safe 'booleanp)
3735 3742
3736(defcustom python-pdbtrack-stacktrace-info-regexp 3743(defcustom python-pdbtrack-stacktrace-info-regexp
3737 "> \\([^\"(<]+\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_<>]+\\)()" 3744 "> \\([^\"(]+\\)(\\([0-9]+\\))\\([?a-zA-Z0-9_<>]+\\)()"
3738 "Regular expression matching stacktrace information. 3745 "Regular expression matching stacktrace information.
3739Used to extract the current line and module being inspected." 3746Used to extract the current line and module being inspected.
3747
3748Must match lines with real filename, like
3749 > /path/to/file.py(42)<module>()->None
3750and lines in which filename starts with '<', e.g.
3751 > <stdin>(1)<module>()->None
3752
3753In the first case /path/to/file.py file will be visited and overlay icon
3754will be placed in line 42.
3755In the second case pdbtracking session will be considered over because
3756the top stack frame has been reached.
3757
3758Filename is expected in the first parenthesized expression.
3759Line number is expected in the second parenthesized expression."
3740 :type 'string 3760 :type 'string
3741 :group 'python 3761 :version "27.1"
3742 :safe 'stringp) 3762 :safe 'stringp)
3743 3763
3764(defcustom python-pdbtrack-continue-command '("c" "cont" "continue")
3765 "Pdb 'continue' command aliases.
3766After one of this commands is sent to pdb, pdbtracking session is
3767considered over.
3768
3769This command is remembered by pdbtracking. If next command sent to pdb
3770is empty string, it considered 'continue' command if previous command
3771was 'continue'. This behavior slightly differentiate 'continue' command
3772from 'exit' commands listed in `python-pdbtrack-exit-command'.
3773
3774See `python-pdbtrack-activate' for pdbtracking session overview."
3775 :type 'list
3776 :version "27.1")
3777
3778(defcustom python-pdbtrack-exit-command '("q" "quit" "exit")
3779 "Pdb 'exit' command aliases.
3780After one of this commands is sent to pdb, pdbtracking session is
3781considered over.
3782
3783See `python-pdbtrack-activate' for pdbtracking session overview."
3784 :type 'list
3785 :version "27.1")
3786
3787(defcustom python-pdbtrack-kill-buffers t
3788 "If non-nil, kill buffers when pdbtracking session is over.
3789Only buffers opened by pdbtracking will be killed.
3790
3791See `python-pdbtrack-activate' for pdbtracking session overview."
3792 :type 'boolean
3793 :version "27.1")
3794
3744(defvar python-pdbtrack-tracked-buffer nil 3795(defvar python-pdbtrack-tracked-buffer nil
3745 "Variable containing the value of the current tracked buffer. 3796 "Variable containing the value of the current tracked buffer.
3746Never set this variable directly, use 3797Never set this variable directly, use
@@ -3749,6 +3800,9 @@ Never set this variable directly, use
3749(defvar python-pdbtrack-buffers-to-kill nil 3800(defvar python-pdbtrack-buffers-to-kill nil
3750 "List of buffers to be deleted after tracking finishes.") 3801 "List of buffers to be deleted after tracking finishes.")
3751 3802
3803(defvar python-pdbtrack-prev-command-continue nil
3804 "Is t if previous pdb command was 'continue'.")
3805
3752(defun python-pdbtrack-set-tracked-buffer (file-name) 3806(defun python-pdbtrack-set-tracked-buffer (file-name)
3753 "Set the buffer for FILE-NAME as the tracked buffer. 3807 "Set the buffer for FILE-NAME as the tracked buffer.
3754Internally it uses the `python-pdbtrack-tracked-buffer' variable. 3808Internally it uses the `python-pdbtrack-tracked-buffer' variable.
@@ -3756,8 +3810,7 @@ Returns the tracked buffer."
3756 (let* ((file-name-prospect (concat (file-remote-p default-directory) 3810 (let* ((file-name-prospect (concat (file-remote-p default-directory)
3757 file-name)) 3811 file-name))
3758 (file-buffer (get-file-buffer file-name-prospect))) 3812 (file-buffer (get-file-buffer file-name-prospect)))
3759 (if file-buffer 3813 (unless file-buffer
3760 (setq python-pdbtrack-tracked-buffer file-buffer)
3761 (cond 3814 (cond
3762 ((file-exists-p file-name-prospect) 3815 ((file-exists-p file-name-prospect)
3763 (setq file-buffer (find-file-noselect file-name-prospect))) 3816 (setq file-buffer (find-file-noselect file-name-prospect)))
@@ -3765,10 +3818,55 @@ Returns the tracked buffer."
3765 (file-exists-p file-name)) 3818 (file-exists-p file-name))
3766 ;; Fallback to a locally available copy of the file. 3819 ;; Fallback to a locally available copy of the file.
3767 (setq file-buffer (find-file-noselect file-name-prospect)))) 3820 (setq file-buffer (find-file-noselect file-name-prospect))))
3768 (when (not (member file-buffer python-pdbtrack-buffers-to-kill)) 3821 (when (and python-pdbtrack-kill-buffers
3822 (not (member file-buffer python-pdbtrack-buffers-to-kill)))
3769 (add-to-list 'python-pdbtrack-buffers-to-kill file-buffer))) 3823 (add-to-list 'python-pdbtrack-buffers-to-kill file-buffer)))
3824 (setq python-pdbtrack-tracked-buffer file-buffer)
3770 file-buffer)) 3825 file-buffer))
3771 3826
3827(defun python-pdbtrack-unset-tracked-buffer ()
3828 "Untrack currently tracked buffer."
3829 (when python-pdbtrack-tracked-buffer
3830 (with-current-buffer python-pdbtrack-tracked-buffer
3831 (set-marker overlay-arrow-position nil))
3832 (setq python-pdbtrack-tracked-buffer nil)))
3833
3834(defun python-pdbtrack-tracking-finish ()
3835 "Finish tracking."
3836 (python-pdbtrack-unset-tracked-buffer)
3837 (when python-pdbtrack-kill-buffers
3838 (mapc #'(lambda (buffer)
3839 (ignore-errors (kill-buffer buffer)))
3840 python-pdbtrack-buffers-to-kill))
3841 (setq python-pdbtrack-buffers-to-kill nil))
3842
3843(defun python-pdbtrack-process-sentinel (process _event)
3844 "Untrack buffers when PROCESS is killed."
3845 (unless (process-live-p process)
3846 (let ((buffer (process-buffer process)))
3847 (when (buffer-live-p buffer)
3848 (with-current-buffer buffer
3849 (python-pdbtrack-tracking-finish))))))
3850
3851(defun python-pdbtrack-comint-input-filter-function (input)
3852 "Finish tracking session depending on command in INPUT.
3853Commands that must finish tracking session is listed in
3854`python-pdbtrack-untracking-commands'."
3855 (when (and python-pdbtrack-tracked-buffer
3856 ;; Empty input is sent by C-d or `comint-send-eof'
3857 (or (string-empty-p input)
3858 ;; "n some text" is "n" command for pdb. Split input and get firs part
3859 (let* ((command (car (split-string (string-trim input) " "))))
3860 (setq python-pdbtrack-prev-command-continue
3861 (or (member command python-pdbtrack-continue-command)
3862 ;; if command is empty and previous command was 'continue'
3863 ;; then current command is 'continue' too.
3864 (and (string-empty-p command)
3865 python-pdbtrack-prev-command-continue)))
3866 (or python-pdbtrack-prev-command-continue
3867 (member command python-pdbtrack-exit-command)))))
3868 (python-pdbtrack-tracking-finish)))
3869
3772(defun python-pdbtrack-comint-output-filter-function (output) 3870(defun python-pdbtrack-comint-output-filter-function (output)
3773 "Move overlay arrow to current pdb line in tracked buffer. 3871 "Move overlay arrow to current pdb line in tracked buffer.
3774Argument OUTPUT is a string with the output from the comint process." 3872Argument OUTPUT is a string with the output from the comint process."
@@ -3788,19 +3886,27 @@ Argument OUTPUT is a string with the output from the comint process."
3788 ;; the _last_ stack frame printed in the most recent 3886 ;; the _last_ stack frame printed in the most recent
3789 ;; batch of output, then jump to the corresponding 3887 ;; batch of output, then jump to the corresponding
3790 ;; file/line number. 3888 ;; file/line number.
3889 ;; Parse output only if at pdb prompt to avoid double code
3890 ;; run in situation when output and pdb prompt received in
3891 ;; different hunks
3791 (goto-char (point-max)) 3892 (goto-char (point-max))
3792 (when (re-search-backward python-pdbtrack-stacktrace-info-regexp nil t) 3893 (goto-char (line-beginning-position))
3894 (when (and (looking-at python-shell-prompt-pdb-regexp)
3895 (re-search-backward python-pdbtrack-stacktrace-info-regexp nil t))
3793 (setq line-number (string-to-number 3896 (setq line-number (string-to-number
3794 (match-string-no-properties 2))) 3897 (match-string-no-properties 2)))
3795 (match-string-no-properties 1))))) 3898 (match-string-no-properties 1)))))
3796 (if (and file-name line-number) 3899 (when (and file-name line-number)
3797 (let* ((tracked-buffer 3900 (if (string-prefix-p "<" file-name)
3798 (python-pdbtrack-set-tracked-buffer file-name)) 3901 ;; Finish tracking session if stacktrace info is like
3902 ;; "> <stdin>(1)<module>()->None"
3903 (python-pdbtrack-tracking-finish)
3904 (python-pdbtrack-unset-tracked-buffer)
3905 (let* ((tracked-buffer (python-pdbtrack-set-tracked-buffer file-name))
3799 (shell-buffer (current-buffer)) 3906 (shell-buffer (current-buffer))
3800 (tracked-buffer-window (get-buffer-window tracked-buffer)) 3907 (tracked-buffer-window (get-buffer-window tracked-buffer))
3801 (tracked-buffer-line-pos)) 3908 (tracked-buffer-line-pos))
3802 (with-current-buffer tracked-buffer 3909 (with-current-buffer tracked-buffer
3803 (set (make-local-variable 'overlay-arrow-string) "=>")
3804 (set (make-local-variable 'overlay-arrow-position) (make-marker)) 3910 (set (make-local-variable 'overlay-arrow-position) (make-marker))
3805 (setq tracked-buffer-line-pos (progn 3911 (setq tracked-buffer-line-pos (progn
3806 (goto-char (point-min)) 3912 (goto-char (point-min))
@@ -3811,17 +3917,21 @@ Argument OUTPUT is a string with the output from the comint process."
3811 tracked-buffer-window tracked-buffer-line-pos)) 3917 tracked-buffer-window tracked-buffer-line-pos))
3812 (set-marker overlay-arrow-position tracked-buffer-line-pos)) 3918 (set-marker overlay-arrow-position tracked-buffer-line-pos))
3813 (pop-to-buffer tracked-buffer) 3919 (pop-to-buffer tracked-buffer)
3814 (switch-to-buffer-other-window shell-buffer)) 3920 (switch-to-buffer-other-window shell-buffer))))))
3815 (when python-pdbtrack-tracked-buffer
3816 (with-current-buffer python-pdbtrack-tracked-buffer
3817 (set-marker overlay-arrow-position nil))
3818 (mapc #'(lambda (buffer)
3819 (ignore-errors (kill-buffer buffer)))
3820 python-pdbtrack-buffers-to-kill)
3821 (setq python-pdbtrack-tracked-buffer nil
3822 python-pdbtrack-buffers-to-kill nil)))))
3823 output) 3921 output)
3824 3922
3923(defun python-pdbtrack-setup-tracking ()
3924 "Setup pdb tracking in current buffer."
3925 (make-local-variable 'python-pdbtrack-buffers-to-kill)
3926 (make-local-variable 'python-pdbtrack-tracked-buffer)
3927 (add-to-list (make-local-variable 'comint-input-filter-functions)
3928 #'python-pdbtrack-comint-input-filter-function)
3929 (add-to-list (make-local-variable 'comint-output-filter-functions)
3930 #'python-pdbtrack-comint-output-filter-function)
3931 (add-function :before (process-sentinel (get-buffer-process (current-buffer)))
3932 #'python-pdbtrack-process-sentinel)
3933 (add-hook 'kill-buffer-hook #'python-pdbtrack-tracking-finish nil t))
3934
3825 3935
3826;;; Symbol completion 3936;;; Symbol completion
3827 3937