Commit fa2bcf43 authored by Martin Rudalics's avatar Martin Rudalics
Browse files

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)
parent aa7d57c5
...@@ -645,6 +645,8 @@ The interpretation of the DECLS is determined by `defun-declarations-alist'. ...@@ -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 error type and new function `user-error'. Doesn't trigger the debugger.
** New option `debugger-bury-or-kill'.
+++ +++
** New utility function `buffer-narrowed-p'. ** New utility function `buffer-narrowed-p'.
...@@ -653,20 +655,25 @@ The interpretation of the DECLS is determined by `defun-declarations-alist'. ...@@ -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 *** The functions get-lru-window, get-mru-window and get-largest-window
now accept a third argument to avoid choosing the selected 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 *** New display action functions `display-buffer-below-selected' and
fit-frame-to-buffer-bottom-margin. `display-buffer-in-previous-window'.
*** New display action function display-buffer-below-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 `inhibit-switch-frame', if non-nil, tells *** New display action alist entry `pop-up-frame-parameters', if
display action functions to avoid changing which frame is selected. non-nil, specifies frame parameters to give any newly-created frame.
*** New display action alist `pop-up-frame-parameters', if non-nil, *** New display action alist entry `previous-window', if non-nil,
specifies frame parameters to give any newly-created frame. specifies window to reuse in `display-buffer-in-previous-window'.
*** The following variables are obsolete, as they can be replaced by *** The following variables are obsolete, as they can be replaced by
appropriate entries in the `display-buffer-alist' function introduced appropriate entries in the `display-buffer-alist' function introduced
......
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> 2012-09-07 Stefan Monnier <monnier@iro.umontreal.ca>
   
* emacs-lisp/byte-run.el (defun): Tweak message. Simplify code. * 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." ...@@ -48,6 +48,39 @@ the middle is discarded, and just the beginning and end are displayed."
:group 'debugger :group 'debugger
:version "21.1") :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 (defvar debug-function-list nil
"List of functions currently set for debug on entry.") "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." ...@@ -60,6 +93,9 @@ the middle is discarded, and just the beginning and end are displayed."
(defvar debugger-old-buffer nil (defvar debugger-old-buffer nil
"This is the buffer that was current when the debugger was entered.") "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 (defvar debugger-previous-backtrace nil
"The contents of the previous backtrace (including text properties). "The contents of the previous backtrace (including text properties).
This is to optimize `debugger-make-xrefs'.") This is to optimize `debugger-make-xrefs'.")
...@@ -133,7 +169,7 @@ first will be printed into the backtrace buffer." ...@@ -133,7 +169,7 @@ first will be printed into the backtrace buffer."
(with-current-buffer (get-buffer "*Backtrace*") (with-current-buffer (get-buffer "*Backtrace*")
(list major-mode (buffer-string))))) (list major-mode (buffer-string)))))
(debugger-buffer (get-buffer-create "*Backtrace*")) (debugger-buffer (get-buffer-create "*Backtrace*"))
(debugger-old-buffer (current-buffer)) (debugger-window nil)
(debugger-step-after-exit nil) (debugger-step-after-exit nil)
(debugger-will-be-back nil) (debugger-will-be-back nil)
;; Don't keep reading from an executing kbd macro! ;; Don't keep reading from an executing kbd macro!
...@@ -184,78 +220,63 @@ first will be printed into the backtrace buffer." ...@@ -184,78 +220,63 @@ first will be printed into the backtrace buffer."
(cursor-in-echo-area nil)) (cursor-in-echo-area nil))
(unwind-protect (unwind-protect
(save-excursion (save-excursion
(save-window-excursion (with-no-warnings
(with-no-warnings (setq unread-command-char -1))
(setq unread-command-char -1)) (when (eq (car debugger-args) 'debug)
(when (eq (car debugger-args) 'debug) ;; Skip the frames for backtrace-debug, byte-code,
;; Skip the frames for backtrace-debug, byte-code, ;; and implement-debug-on-entry.
;; and implement-debug-on-entry. (backtrace-debug 4 t)
(backtrace-debug 4 t) ;; Place an extra debug-on-exit for macro's.
;; Place an extra debug-on-exit for macro's. (when (eq 'lambda (car-safe (cadr (backtrace-frame 4))))
(when (eq 'lambda (car-safe (cadr (backtrace-frame 4)))) (backtrace-debug 5 t)))
(backtrace-debug 5 t))) (pop-to-buffer
(pop-to-buffer debugger-buffer) debugger-buffer
(debugger-mode) `((display-buffer-reuse-window
(debugger-setup-buffer debugger-args) display-buffer-in-previous-window)
(when noninteractive . (,(when debugger-previous-window
;; If the backtrace is long, save the beginning `(previous-window . ,debugger-previous-window)))))
;; and the end, but discard the middle. (setq debugger-window (selected-window))
(when (> (count-lines (point-min) (point-max)) (setq debugger-previous-window debugger-window)
debugger-batch-max-lines) (debugger-mode)
(goto-char (point-min)) (debugger-setup-buffer debugger-args)
(forward-line (/ 2 debugger-batch-max-lines)) (when noninteractive
(let ((middlestart (point))) ;; If the backtrace is long, save the beginning
(goto-char (point-max)) ;; and the end, but discard the middle.
(forward-line (- (/ 2 debugger-batch-max-lines) (when (> (count-lines (point-min) (point-max))
debugger-batch-max-lines)) debugger-batch-max-lines)
(delete-region middlestart (point)))
(insert "...\n"))
(goto-char (point-min)) (goto-char (point-min))
(message "%s" (buffer-string)) (forward-line (/ 2 debugger-batch-max-lines))
(kill-emacs -1)) (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 "") (message "")
(let ((standard-output nil) ;; Make sure we unbind buffer-read-only in the right buffer.
(buffer-read-only t)) (save-excursion
(message "") (recursive-edit))))
;; Make sure we unbind buffer-read-only in the right buffer. (when (and (window-live-p debugger-window)
(save-excursion (eq (window-buffer debugger-window) debugger-buffer))
(recursive-edit))))) ;; Unshow debugger-buffer.
;; Kill or at least neuter the backtrace buffer, so that users (quit-restore-window debugger-window debugger-bury-or-kill))
;; don't try to execute debugger commands in an invalid context. ;; Restore previous state of debugger-buffer in case we were
(if (get-buffer-window debugger-buffer 0) ;; in a recursive invocation of the debugger, otherwise just
;; Still visible despite the save-window-excursion? Maybe it ;; erase the buffer and put it into fundamental mode.
;; it's in a pop-up frame. It would be annoying to delete and (when (buffer-live-p debugger-buffer)
;; recreate it every time the debugger stops, so instead we'll (with-current-buffer debugger-buffer
;; erase it (and maybe hide it) but keep it alive. (let ((inhibit-read-only t))
(with-current-buffer debugger-buffer (erase-buffer)
(with-selected-window (get-buffer-window debugger-buffer 0) (if (null debugger-previous-state)
(when (and (window-dedicated-p (selected-window)) (fundamental-mode)
(not debugger-will-be-back)) (insert (nth 1 debugger-previous-state))
;; If the window is not dedicated, burying the buffer (funcall (nth 0 debugger-previous-state))))))
;; 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))))))
(with-timeout-unsuspend debugger-with-timeout-suspend) (with-timeout-unsuspend debugger-with-timeout-suspend)
(set-match-data debugger-outer-match-data))) (set-match-data debugger-outer-match-data)))
;; Put into effect the modified values of these variables ;; Put into effect the modified values of these variables
......
...@@ -5521,6 +5521,62 @@ the selected one." ...@@ -5521,6 +5521,62 @@ the selected one."
(window--display-buffer (window--display-buffer
buffer window 'reuse display-buffer-mark-dedicated))))) 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) (defun display-buffer-use-some-window (buffer alist)
"Display BUFFER in an existing window. "Display BUFFER in an existing window.
Search for a usable window, set that window to the buffer, and Search for a usable window, set that window to the buffer, and
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment