1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-17 10:06:13 +00:00

Unify and improve gdb-mi source buffer display logic

Unify the behavior of source buffer display for gdb-mi.  Before this
change, stepping and other gdb command handlers use 'gud-display-line',
and 'gdb-goto-breakpoint' uses 'gdb-display-source-buffer'.  Now whenever
gdb-mi code tries to open a source buffer, 'gdb-display-source-buffer'
is used.  Also, simplify the logic in 'gdb-display-source-buffer' and
add a feature to limit the maximum number of source windows.

* doc/emacs/building.texi (GDB User Interface Layout): Explain source
file display in GDB.
* etc/NEWS (gdb-mi): Add news about source display.
* lisp/progmodes/gdb-mi.el (gdb-source-window): Remove variable,
change to 'gdb-source-window-list'.
(gdb-source-window-list): New variable.
(gdb-display-source-buffer-action,
gdb-max-source-window-count): New options.
(gdb-init-1, gdb-setup-windows, gdb-load-window-configuration,
gdb-restore-windows): Use 'gdb-source-window' rather than
'gdb-source-window-list'.
(gdb-save-window-configuration): Use 'gdb-source-window' rather than
'gdb-source-window-list'.  And consider any buffer that is not a
command or function buffer as a source buffer.
(gdb-display-source-buffer): Use new logic.
(gdb-goto-breakpoint): Remove 'display-buffer' call
and don't set 'gdb-source-buffer' anymore.
* lisp/progmodes/gud.el (gud-display-line): If used by gdb-mi, use
'gdb-display-source-buffer' rather than 'display-buffer'.  Don't set
'gdb-source-buffer' anymore.
This commit is contained in:
Yuan Fu 2020-04-06 09:56:15 +02:00 committed by Martin Rudalics
parent 981cea9b62
commit fd4ee36139
4 changed files with 77 additions and 26 deletions

View File

@ -1022,6 +1022,14 @@ is the relevant buffer type, such as @samp{breakpoints}. You can do
the same with the menu bar, with the @samp{GDB-Windows} and the same with the menu bar, with the @samp{GDB-Windows} and
@samp{GDB-Frames} sub-menus of the @samp{GUD} menu. @samp{GDB-Frames} sub-menus of the @samp{GUD} menu.
@vindex gdb-max-source-window-count
@vindex gdb-display-source-buffer-action
By default, GDB uses at most one window to display the source file.
You can make it use more windows by customizing
@code{gdb-max-source-window-count}. You can also customize
@code{gdb-display-source-buffer-action} to control how GDB displays
source files.
When you finish debugging, kill the GUD interaction buffer with When you finish debugging, kill the GUD interaction buffer with
@kbd{C-x k}, which will also kill all the buffers associated with the @kbd{C-x k}, which will also kill all the buffers associated with the
session. However you need not do this if, after editing and session. However you need not do this if, after editing and

View File

@ -233,6 +233,12 @@ will remember the window configuration before GDB started and restore
it after GDB quits. A toggle button is also provided under 'Gud -- it after GDB quits. A toggle button is also provided under 'Gud --
GDB-Windows'. GDB-Windows'.
+++
*** gdb-mi now has a better logic for displaying source buffers
Now GDB only uses one source window to display source file by default.
Customize 'gdb-max-source-window-count' to use more than one window.
Control source file display by 'gdb-display-source-buffer-action'.
** Gravatar ** Gravatar
--- ---

View File

@ -224,7 +224,9 @@ Only used for files that Emacs can't find.")
(defvar gdb-source-file-list nil (defvar gdb-source-file-list nil
"List of source files for the current executable.") "List of source files for the current executable.")
(defvar gdb-first-done-or-error t) (defvar gdb-first-done-or-error t)
(defvar gdb-source-window nil) (defvar gdb-source-window-list nil
"List of windows used for displaying source files.
Sorted in most-recently-visited-first order.")
(defvar gdb-inferior-status nil) (defvar gdb-inferior-status nil)
(defvar gdb-continuation nil) (defvar gdb-continuation nil)
(defvar gdb-supports-non-stop nil) (defvar gdb-supports-non-stop nil)
@ -645,6 +647,21 @@ Note that this variable only takes effect when variable
:group 'gdb :group 'gdb
:version "28.1") :version "28.1")
(defcustom gdb-display-source-buffer-action '(nil . ((inhibit-same-window . t)))
"`display-buffer' action used when GDB displays a source buffer."
:type 'list
:group 'gdb
:version "28.1")
(defcustom gdb-max-source-window-count 1
"Maximum number of source windows to use.
Until there are such number of source windows on screen, GDB
tries to open a new window when visiting a new source file; after
that GDB starts to reuse existing source windows."
:type 'number
:group 'gdb
:version "28.1")
(defvar gdbmi-debug-mode nil (defvar gdbmi-debug-mode nil
"When non-nil, print the messages sent/received from GDB/MI in *Messages*.") "When non-nil, print the messages sent/received from GDB/MI in *Messages*.")
@ -984,7 +1001,7 @@ detailed description of this mode.
gdb-first-done-or-error t gdb-first-done-or-error t
gdb-buffer-fringe-width (car (window-fringes)) gdb-buffer-fringe-width (car (window-fringes))
gdb-debug-log nil gdb-debug-log nil
gdb-source-window nil gdb-source-window-list nil
gdb-inferior-status nil gdb-inferior-status nil
gdb-continuation nil gdb-continuation nil
gdb-buf-publisher '() gdb-buf-publisher '()
@ -2070,17 +2087,36 @@ is running."
;; GDB frame (after up, down etc). If no GDB frame is visible but the last ;; GDB frame (after up, down etc). If no GDB frame is visible but the last
;; visited breakpoint is, use that window. ;; visited breakpoint is, use that window.
(defun gdb-display-source-buffer (buffer) (defun gdb-display-source-buffer (buffer)
(let* ((last-window (if gud-last-last-frame "Find a window to display BUFFER.
(get-buffer-window Always find a window to display buffer, and return it."
(gud-find-file (car gud-last-last-frame))))) ;; This function doesn't take care of setting up source window(s) at startup,
(source-window (or last-window ;; that's handled by `gdb-setup-windows' (if `gdb-many-windows' is non-nil).
(if (and gdb-source-window ;; If `buffer' is already shown in a window, use that window.
(window-live-p gdb-source-window)) (or (get-buffer-window buffer)
gdb-source-window)))) (progn
(when source-window ;; First, update the window list.
(setq gdb-source-window source-window) (setq gdb-source-window-list
(set-window-buffer source-window buffer)) (cl-remove-duplicates
source-window)) (cl-remove-if-not
(lambda (win)
(and (window-live-p win)
(eq (window-frame win)
(selected-frame))))
gdb-source-window-list)))
;; Should we create a new window or reuse one?
(if (> gdb-max-source-window-count
(length gdb-source-window-list))
;; Create a new window, push it to window list and return it.
(car (push (display-buffer buffer gdb-display-source-buffer-action)
gdb-source-window-list))
;; Reuse a window, we use the oldest window and put that to
;; the front of the window list.
(let ((last-win (car (last gdb-source-window-list)))
(rest (butlast gdb-source-window-list)))
(set-window-buffer last-win buffer)
(setq gdb-source-window-list
(cons last-win rest))
last-win)))))
(defun gdbmi-start-with (str offset match) (defun gdbmi-start-with (str offset match)
@ -4071,9 +4107,7 @@ DOC is an optional documentation string."
(let* ((buffer (find-file-noselect (let* ((buffer (find-file-noselect
(if (file-exists-p file) file (if (file-exists-p file) file
(cdr (assoc bptno gdb-location-alist))))) (cdr (assoc bptno gdb-location-alist)))))
(window (or (gdb-display-source-buffer buffer) (window (gdb-display-source-buffer buffer)))
(display-buffer buffer))))
(setq gdb-source-window window)
(with-current-buffer buffer (with-current-buffer buffer
(goto-char (point-min)) (goto-char (point-min))
(forward-line (1- (string-to-number line))) (forward-line (1- (string-to-number line)))
@ -4722,7 +4756,7 @@ file\" where the GDB session starts (see `gdb-main-file')."
(select-window win2) (select-window win2)
(set-window-buffer win2 (or (gdb-get-source-buffer) (set-window-buffer win2 (or (gdb-get-source-buffer)
(list-buffers-noselect))) (list-buffers-noselect)))
(setq gdb-source-window (selected-window)) (setq gdb-source-window-list (list (selected-window)))
(let ((win4 (split-window-right))) (let ((win4 (split-window-right)))
(gdb-set-window-buffer (gdb-set-window-buffer
(gdb-get-buffer-create 'gdb-inferior-io) nil win4)) (gdb-get-buffer-create 'gdb-inferior-io) nil win4))
@ -4798,7 +4832,8 @@ You can later restore this configuration from that file by
(error "Unrecognized gdb buffer mode: %s" major-mode))) (error "Unrecognized gdb buffer mode: %s" major-mode)))
;; Command buffer. ;; Command buffer.
((derived-mode-p 'gud-mode) 'command) ((derived-mode-p 'gud-mode) 'command)
((equal (selected-window) gdb-source-window) 'source))) ;; Consider everything else as source buffer.
(t 'source)))
(with-window-non-dedicated nil (with-window-non-dedicated nil
(set-window-buffer nil placeholder) (set-window-buffer nil placeholder)
(set-window-prev-buffers (selected-window) nil) (set-window-prev-buffers (selected-window) nil)
@ -4841,7 +4876,7 @@ FILE should be a window configuration file saved by
(pcase buffer-type (pcase buffer-type
('source (when source-buffer ('source (when source-buffer
(set-window-buffer nil source-buffer) (set-window-buffer nil source-buffer)
(setq gdb-source-window (selected-window)))) (push (selected-window) gdb-source-window-list)))
('command (switch-to-buffer gud-comint-buffer)) ('command (switch-to-buffer gud-comint-buffer))
(_ (let ((buffer (gdb-get-buffer-create buffer-type))) (_ (let ((buffer (gdb-get-buffer-create buffer-type)))
(with-window-non-dedicated nil (with-window-non-dedicated nil
@ -4882,7 +4917,7 @@ This arrangement depends on the values of variable
(if gud-last-last-frame (if gud-last-last-frame
(gud-find-file (car gud-last-last-frame)) (gud-find-file (car gud-last-last-frame))
(gud-find-file gdb-main-file))) (gud-find-file gdb-main-file)))
(setq gdb-source-window win))))) (setq gdb-source-window-list (list win))))))
;; Called from `gud-sentinel' in gud.el: ;; Called from `gud-sentinel' in gud.el:
(defun gdb-reset () (defun gdb-reset ()

View File

@ -2826,9 +2826,13 @@ Obeying it means displaying in another window the specified file and line."
(buffer (buffer
(with-current-buffer gud-comint-buffer (with-current-buffer gud-comint-buffer
(gud-find-file true-file))) (gud-find-file true-file)))
(window (and buffer (window
(or (get-buffer-window buffer) (when buffer
(display-buffer buffer '(nil (inhibit-same-window . t)))))) (if (eq gud-minor-mode 'gdbmi)
(gdb-display-source-buffer buffer)
;; Gud still has the old behavior.
(or (get-buffer-window buffer)
(display-buffer buffer '(nil (inhibit-same-window . t)))))))
(pos)) (pos))
(when buffer (when buffer
(with-current-buffer buffer (with-current-buffer buffer
@ -2858,9 +2862,7 @@ Obeying it means displaying in another window the specified file and line."
(widen) (widen)
(goto-char pos)))) (goto-char pos))))
(when window (when window
(set-window-point window gud-overlay-arrow-position) (set-window-point window gud-overlay-arrow-position)))))
(if (eq gud-minor-mode 'gdbmi)
(setq gdb-source-window window))))))
;; The gud-call function must do the right thing whether its invoking ;; The gud-call function must do the right thing whether its invoking
;; keystroke is from the GUD buffer itself (via major-mode binding) ;; keystroke is from the GUD buffer itself (via major-mode binding)