diff options
| author | Andrii Kolomoiets | 2019-11-02 18:08:13 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2019-11-07 18:53:04 +0200 |
| commit | e50587b1db8475fd45e6668f97ca7bc28b798996 (patch) | |
| tree | e51d7e5dd91759fa98780b1799032e8aa6411ce2 | |
| parent | 3df1cf75f2f2be9549b6ffe3649387d2b4246f06 (diff) | |
| download | emacs-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/NEWS | 5 | ||||
| -rw-r--r-- | lisp/progmodes/python.el | 160 |
2 files changed, 140 insertions, 25 deletions
| @@ -1445,6 +1445,11 @@ unescaping text. | |||
| 1445 | The maximum level is used by default; customize | 1445 | The 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'. | ||
| 1450 | If nil, buffers opened during pdbtracking session are not killed when | ||
| 1451 | pdbtracking 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. |
| 3730 | Pdbtracking 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 | ||
| 3732 | inspected line in that file. | ||
| 3733 | |||
| 3734 | After command listed in `python-pdbtrack-continue-command' or | ||
| 3735 | `python-pdbtrack-exit-command' is sent to pdb, pdbtracking session is | ||
| 3736 | considered over. Overlay arrow will be removed from currentry tracked | ||
| 3737 | buffer. Additionally, if `python-pdbtrack-kill-buffers' is non-nil, all | ||
| 3738 | files 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. |
| 3739 | Used to extract the current line and module being inspected." | 3746 | Used to extract the current line and module being inspected. |
| 3747 | |||
| 3748 | Must match lines with real filename, like | ||
| 3749 | > /path/to/file.py(42)<module>()->None | ||
| 3750 | and lines in which filename starts with '<', e.g. | ||
| 3751 | > <stdin>(1)<module>()->None | ||
| 3752 | |||
| 3753 | In the first case /path/to/file.py file will be visited and overlay icon | ||
| 3754 | will be placed in line 42. | ||
| 3755 | In the second case pdbtracking session will be considered over because | ||
| 3756 | the top stack frame has been reached. | ||
| 3757 | |||
| 3758 | Filename is expected in the first parenthesized expression. | ||
| 3759 | Line 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. | ||
| 3766 | After one of this commands is sent to pdb, pdbtracking session is | ||
| 3767 | considered over. | ||
| 3768 | |||
| 3769 | This command is remembered by pdbtracking. If next command sent to pdb | ||
| 3770 | is empty string, it considered 'continue' command if previous command | ||
| 3771 | was 'continue'. This behavior slightly differentiate 'continue' command | ||
| 3772 | from 'exit' commands listed in `python-pdbtrack-exit-command'. | ||
| 3773 | |||
| 3774 | See `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. | ||
| 3780 | After one of this commands is sent to pdb, pdbtracking session is | ||
| 3781 | considered over. | ||
| 3782 | |||
| 3783 | See `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. | ||
| 3789 | Only buffers opened by pdbtracking will be killed. | ||
| 3790 | |||
| 3791 | See `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. |
| 3746 | Never set this variable directly, use | 3797 | Never 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. |
| 3754 | Internally it uses the `python-pdbtrack-tracked-buffer' variable. | 3808 | Internally 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. | ||
| 3853 | Commands 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. |
| 3774 | Argument OUTPUT is a string with the output from the comint process." | 3872 | Argument 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 | ||