Fix handling of debugger window. (Bug#8789)
* window.el (display-buffer-in-previous-window): New buffer display action function. * emacs-lisp/debug.el (debugger-bury-or-kill): New option. (debugger-previous-window): New variable. (debug): Rewrite using display-buffer-in-previous-window, quit-restore-window and debugger-bury-or-kill. (Bug#8789)
This commit is contained in:
parent
aa7d57c507
commit
fa2bcf435d
4 changed files with 174 additions and 80 deletions
25
etc/NEWS
25
etc/NEWS
|
@ -645,6 +645,8 @@ The interpretation of the DECLS is determined by `defun-declarations-alist'.
|
|||
|
||||
** New error type and new function `user-error'. Doesn't trigger the debugger.
|
||||
|
||||
** New option `debugger-bury-or-kill'.
|
||||
|
||||
+++
|
||||
** New utility function `buffer-narrowed-p'.
|
||||
|
||||
|
@ -653,20 +655,25 @@ The interpretation of the DECLS is determined by `defun-declarations-alist'.
|
|||
*** The functions get-lru-window, get-mru-window and get-largest-window
|
||||
now accept a third argument to avoid choosing the selected window.
|
||||
|
||||
*** New macro with-temp-buffer-window.
|
||||
*** New macro `with-temp-buffer-window'.
|
||||
|
||||
*** New option temp-buffer-resize-frames.
|
||||
*** New option `temp-buffer-resize-frames'.
|
||||
|
||||
*** New function fit-frame-to-buffer and new option
|
||||
fit-frame-to-buffer-bottom-margin.
|
||||
*** New function `fit-frame-to-buffer' and new option
|
||||
`fit-frame-to-buffer-bottom-margin'.
|
||||
|
||||
*** New display action function display-buffer-below-selected.
|
||||
*** New display action functions `display-buffer-below-selected' and
|
||||
`display-buffer-in-previous-window'.
|
||||
|
||||
*** New display action alist `inhibit-switch-frame', if non-nil, tells
|
||||
display action functions to avoid changing which frame is selected.
|
||||
*** New display action alist entry `inhibit-switch-frame', if non-nil,
|
||||
tells display action functions to avoid changing which frame is
|
||||
selected.
|
||||
|
||||
*** New display action alist `pop-up-frame-parameters', if non-nil,
|
||||
specifies frame parameters to give any newly-created frame.
|
||||
*** New display action alist entry `pop-up-frame-parameters', if
|
||||
non-nil, specifies frame parameters to give any newly-created frame.
|
||||
|
||||
*** New display action alist entry `previous-window', if non-nil,
|
||||
specifies window to reuse in `display-buffer-in-previous-window'.
|
||||
|
||||
*** The following variables are obsolete, as they can be replaced by
|
||||
appropriate entries in the `display-buffer-alist' function introduced
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
2012-09-08 Martin Rudalics <rudalics@gmx.at>
|
||||
|
||||
* window.el (display-buffer-in-previous-window): New buffer
|
||||
display action function.
|
||||
|
||||
* emacs-lisp/debug.el (debugger-bury-or-kill): New option.
|
||||
(debugger-previous-window): New variable.
|
||||
(debug): Rewrite using display-buffer-in-previous-window,
|
||||
quit-restore-window and debugger-bury-or-kill. (Bug#8789)
|
||||
|
||||
2012-09-07 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* emacs-lisp/byte-run.el (defun): Tweak message. Simplify code.
|
||||
|
|
|
@ -48,6 +48,39 @@ the middle is discarded, and just the beginning and end are displayed."
|
|||
:group 'debugger
|
||||
:version "21.1")
|
||||
|
||||
(defcustom debugger-bury-or-kill 'bury
|
||||
"How to proceed with the debugger buffer when exiting `debug'.
|
||||
The value used here affects the behavior of operations on any
|
||||
window previously showing the debugger buffer.
|
||||
|
||||
`nil' means that if its window is not deleted when exiting the
|
||||
debugger, invoking `switch-to-prev-buffer' will usually show
|
||||
the debugger buffer again.
|
||||
|
||||
`append' means that if the window is not deleted, the debugger
|
||||
buffer moves to the end of the window's previous buffers so
|
||||
it's less likely that a future invocation of
|
||||
`switch-to-prev-buffer' will switch to it. Also, it moves the
|
||||
buffer to the end of the frame's buffer list.
|
||||
|
||||
`bury' means that if the window is not deleted, its buffer is
|
||||
removed from the window's list of previous buffers. Also, it
|
||||
moves the buffer to the end of the frame's buffer list. This
|
||||
value provides the most reliable remedy to not have
|
||||
`switch-to-prev-buffer' switch to the debugger buffer again
|
||||
without killing the buffer.
|
||||
|
||||
`kill' means to kill the debugger buffer.
|
||||
|
||||
The value used here is passed to `quit-restore-window'."
|
||||
:type '(choice
|
||||
(const :tag "Keep alive" nil)
|
||||
(const :tag "Append" 'append)
|
||||
(const :tag "Bury" 'bury)
|
||||
(const :tag "Kill" 'kill))
|
||||
:group 'debugger
|
||||
:version "24.2")
|
||||
|
||||
(defvar debug-function-list nil
|
||||
"List of functions currently set for debug on entry.")
|
||||
|
||||
|
@ -60,6 +93,9 @@ the middle is discarded, and just the beginning and end are displayed."
|
|||
(defvar debugger-old-buffer nil
|
||||
"This is the buffer that was current when the debugger was entered.")
|
||||
|
||||
(defvar debugger-previous-window nil
|
||||
"This is the window last showing the debugger buffer.")
|
||||
|
||||
(defvar debugger-previous-backtrace nil
|
||||
"The contents of the previous backtrace (including text properties).
|
||||
This is to optimize `debugger-make-xrefs'.")
|
||||
|
@ -133,7 +169,7 @@ first will be printed into the backtrace buffer."
|
|||
(with-current-buffer (get-buffer "*Backtrace*")
|
||||
(list major-mode (buffer-string)))))
|
||||
(debugger-buffer (get-buffer-create "*Backtrace*"))
|
||||
(debugger-old-buffer (current-buffer))
|
||||
(debugger-window nil)
|
||||
(debugger-step-after-exit nil)
|
||||
(debugger-will-be-back nil)
|
||||
;; Don't keep reading from an executing kbd macro!
|
||||
|
@ -184,78 +220,63 @@ first will be printed into the backtrace buffer."
|
|||
(cursor-in-echo-area nil))
|
||||
(unwind-protect
|
||||
(save-excursion
|
||||
(save-window-excursion
|
||||
(with-no-warnings
|
||||
(setq unread-command-char -1))
|
||||
(when (eq (car debugger-args) 'debug)
|
||||
;; Skip the frames for backtrace-debug, byte-code,
|
||||
;; and implement-debug-on-entry.
|
||||
(backtrace-debug 4 t)
|
||||
;; Place an extra debug-on-exit for macro's.
|
||||
(when (eq 'lambda (car-safe (cadr (backtrace-frame 4))))
|
||||
(backtrace-debug 5 t)))
|
||||
(pop-to-buffer debugger-buffer)
|
||||
(debugger-mode)
|
||||
(debugger-setup-buffer debugger-args)
|
||||
(when noninteractive
|
||||
;; If the backtrace is long, save the beginning
|
||||
;; and the end, but discard the middle.
|
||||
(when (> (count-lines (point-min) (point-max))
|
||||
debugger-batch-max-lines)
|
||||
(goto-char (point-min))
|
||||
(forward-line (/ 2 debugger-batch-max-lines))
|
||||
(let ((middlestart (point)))
|
||||
(goto-char (point-max))
|
||||
(forward-line (- (/ 2 debugger-batch-max-lines)
|
||||
debugger-batch-max-lines))
|
||||
(delete-region middlestart (point)))
|
||||
(insert "...\n"))
|
||||
(with-no-warnings
|
||||
(setq unread-command-char -1))
|
||||
(when (eq (car debugger-args) 'debug)
|
||||
;; Skip the frames for backtrace-debug, byte-code,
|
||||
;; and implement-debug-on-entry.
|
||||
(backtrace-debug 4 t)
|
||||
;; Place an extra debug-on-exit for macro's.
|
||||
(when (eq 'lambda (car-safe (cadr (backtrace-frame 4))))
|
||||
(backtrace-debug 5 t)))
|
||||
(pop-to-buffer
|
||||
debugger-buffer
|
||||
`((display-buffer-reuse-window
|
||||
display-buffer-in-previous-window)
|
||||
. (,(when debugger-previous-window
|
||||
`(previous-window . ,debugger-previous-window)))))
|
||||
(setq debugger-window (selected-window))
|
||||
(setq debugger-previous-window debugger-window)
|
||||
(debugger-mode)
|
||||
(debugger-setup-buffer debugger-args)
|
||||
(when noninteractive
|
||||
;; If the backtrace is long, save the beginning
|
||||
;; and the end, but discard the middle.
|
||||
(when (> (count-lines (point-min) (point-max))
|
||||
debugger-batch-max-lines)
|
||||
(goto-char (point-min))
|
||||
(message "%s" (buffer-string))
|
||||
(kill-emacs -1))
|
||||
(forward-line (/ 2 debugger-batch-max-lines))
|
||||
(let ((middlestart (point)))
|
||||
(goto-char (point-max))
|
||||
(forward-line (- (/ 2 debugger-batch-max-lines)
|
||||
debugger-batch-max-lines))
|
||||
(delete-region middlestart (point)))
|
||||
(insert "...\n"))
|
||||
(goto-char (point-min))
|
||||
(message "%s" (buffer-string))
|
||||
(kill-emacs -1))
|
||||
(message "")
|
||||
(let ((standard-output nil)
|
||||
(buffer-read-only t))
|
||||
(message "")
|
||||
(let ((standard-output nil)
|
||||
(buffer-read-only t))
|
||||
(message "")
|
||||
;; Make sure we unbind buffer-read-only in the right buffer.
|
||||
(save-excursion
|
||||
(recursive-edit)))))
|
||||
;; Kill or at least neuter the backtrace buffer, so that users
|
||||
;; don't try to execute debugger commands in an invalid context.
|
||||
(if (get-buffer-window debugger-buffer 0)
|
||||
;; Still visible despite the save-window-excursion? Maybe it
|
||||
;; it's in a pop-up frame. It would be annoying to delete and
|
||||
;; recreate it every time the debugger stops, so instead we'll
|
||||
;; erase it (and maybe hide it) but keep it alive.
|
||||
(with-current-buffer debugger-buffer
|
||||
(with-selected-window (get-buffer-window debugger-buffer 0)
|
||||
(when (and (window-dedicated-p (selected-window))
|
||||
(not debugger-will-be-back))
|
||||
;; If the window is not dedicated, burying the buffer
|
||||
;; will mean that the frame created for it is left
|
||||
;; around showing some random buffer, and next time we
|
||||
;; pop to the debugger buffer we'll create yet
|
||||
;; another frame.
|
||||
;; If debugger-will-be-back is non-nil, the frame
|
||||
;; would need to be de-iconified anyway immediately
|
||||
;; after when we re-enter the debugger, so iconifying it
|
||||
;; here would cause flashing.
|
||||
;; Drew Adams is not happy with this: he wants to frame
|
||||
;; to be left at the top-level, still working on how
|
||||
;; best to do that.
|
||||
(bury-buffer))))
|
||||
(unless debugger-previous-state
|
||||
(kill-buffer debugger-buffer)))
|
||||
;; Restore the previous state of the debugger-buffer, in case we were
|
||||
;; in a recursive invocation of the debugger.
|
||||
(when (buffer-live-p debugger-buffer)
|
||||
(with-current-buffer debugger-buffer
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)
|
||||
(if (null debugger-previous-state)
|
||||
(fundamental-mode)
|
||||
(insert (nth 1 debugger-previous-state))
|
||||
(funcall (nth 0 debugger-previous-state))))))
|
||||
;; Make sure we unbind buffer-read-only in the right buffer.
|
||||
(save-excursion
|
||||
(recursive-edit))))
|
||||
(when (and (window-live-p debugger-window)
|
||||
(eq (window-buffer debugger-window) debugger-buffer))
|
||||
;; Unshow debugger-buffer.
|
||||
(quit-restore-window debugger-window debugger-bury-or-kill))
|
||||
;; Restore previous state of debugger-buffer in case we were
|
||||
;; in a recursive invocation of the debugger, otherwise just
|
||||
;; erase the buffer and put it into fundamental mode.
|
||||
(when (buffer-live-p debugger-buffer)
|
||||
(with-current-buffer debugger-buffer
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)
|
||||
(if (null debugger-previous-state)
|
||||
(fundamental-mode)
|
||||
(insert (nth 1 debugger-previous-state))
|
||||
(funcall (nth 0 debugger-previous-state))))))
|
||||
(with-timeout-unsuspend debugger-with-timeout-suspend)
|
||||
(set-match-data debugger-outer-match-data)))
|
||||
;; Put into effect the modified values of these variables
|
||||
|
|
|
@ -5521,6 +5521,62 @@ the selected one."
|
|||
(window--display-buffer
|
||||
buffer window 'reuse display-buffer-mark-dedicated)))))
|
||||
|
||||
(defun display-buffer-in-previous-window (buffer alist)
|
||||
"Display BUFFER in a window previously showing it.
|
||||
If ALIST has a non-nil `inhibit-same-window' entry, the selected
|
||||
window is not eligible for reuse.
|
||||
|
||||
If ALIST contains a `reusable-frames' entry, its value determines
|
||||
which frames to search for a reusable window:
|
||||
nil -- the selected frame (actually the last non-minibuffer frame)
|
||||
A frame -- just that frame
|
||||
`visible' -- all visible frames
|
||||
0 -- all frames on the current terminal
|
||||
t -- all frames.
|
||||
|
||||
If ALIST contains no `reusable-frames' entry, search just the
|
||||
selected frame if `display-buffer-reuse-frames' and
|
||||
`pop-up-frames' are both nil; search all frames on the current
|
||||
terminal if either of those variables is non-nil.
|
||||
|
||||
If ALIST has a `previous-window' entry, the window specified by
|
||||
that entry will override any other window found by the methods
|
||||
above, even if that window never showed BUFFER before."
|
||||
(let* ((alist-entry (assq 'reusable-frames alist))
|
||||
(inhibit-same-window
|
||||
(cdr (assq 'inhibit-same-window alist)))
|
||||
(frames (cond
|
||||
(alist-entry (cdr alist-entry))
|
||||
((if (eq pop-up-frames 'graphic-only)
|
||||
(display-graphic-p)
|
||||
pop-up-frames)
|
||||
0)
|
||||
(display-buffer-reuse-frames 0)
|
||||
(t (last-nonminibuffer-frame))))
|
||||
entry best-window second-best-window window)
|
||||
;; Scan windows whether they have shown the buffer recently.
|
||||
(catch 'best
|
||||
(dolist (window (window-list-1 (frame-first-window) 'nomini frames))
|
||||
(when (and (assq buffer (window-prev-buffers window))
|
||||
(not (window-dedicated-p window)))
|
||||
(if (eq window (selected-window))
|
||||
(unless inhibit-same-window
|
||||
(setq second-best-window window))
|
||||
(setq best-window window)
|
||||
(throw 'best t)))))
|
||||
;; When ALIST has a `previous-window' entry, that entry may override
|
||||
;; anything we found so far.
|
||||
(when (and (setq window (cdr (assq 'previous-window alist)))
|
||||
(window-live-p window)
|
||||
(not (window-dedicated-p window)))
|
||||
(if (eq window (selected-window))
|
||||
(unless inhibit-same-window
|
||||
(setq second-best-window window))
|
||||
(setq best-window window)))
|
||||
;; Return best or second best window found.
|
||||
(when (setq window (or best-window second-best-window))
|
||||
(window--display-buffer buffer window 'reuse))))
|
||||
|
||||
(defun display-buffer-use-some-window (buffer alist)
|
||||
"Display BUFFER in an existing window.
|
||||
Search for a usable window, set that window to the buffer, and
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue