aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuan Fu2020-04-06 09:56:15 +0200
committerMartin Rudalics2020-04-06 09:56:15 +0200
commitfd4ee361395060c8afa95393245ac8d51655ae54 (patch)
tree7fb6cc73f0792261e9ea4bf16cc2302d9fbbbd44
parent981cea9b624f61de3bc84226d19303ff3f8cbd8b (diff)
downloademacs-fd4ee361395060c8afa95393245ac8d51655ae54.tar.gz
emacs-fd4ee361395060c8afa95393245ac8d51655ae54.zip
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.
-rw-r--r--doc/emacs/building.texi8
-rw-r--r--etc/NEWS6
-rw-r--r--lisp/progmodes/gdb-mi.el75
-rw-r--r--lisp/progmodes/gud.el14
4 files changed, 77 insertions, 26 deletions
diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi
index 8a05680c742..77a0e807c2b 100644
--- a/doc/emacs/building.texi
+++ b/doc/emacs/building.texi
@@ -1022,6 +1022,14 @@ is the relevant buffer type, such as @samp{breakpoints}. You can do
1022the same with the menu bar, with the @samp{GDB-Windows} and 1022the same with the menu bar, with the @samp{GDB-Windows} and
1023@samp{GDB-Frames} sub-menus of the @samp{GUD} menu. 1023@samp{GDB-Frames} sub-menus of the @samp{GUD} menu.
1024 1024
1025@vindex gdb-max-source-window-count
1026@vindex gdb-display-source-buffer-action
1027By default, GDB uses at most one window to display the source file.
1028You can make it use more windows by customizing
1029@code{gdb-max-source-window-count}. You can also customize
1030@code{gdb-display-source-buffer-action} to control how GDB displays
1031source files.
1032
1025 When you finish debugging, kill the GUD interaction buffer with 1033 When you finish debugging, kill the GUD interaction buffer with
1026@kbd{C-x k}, which will also kill all the buffers associated with the 1034@kbd{C-x k}, which will also kill all the buffers associated with the
1027session. However you need not do this if, after editing and 1035session. However you need not do this if, after editing and
diff --git a/etc/NEWS b/etc/NEWS
index 81a70e9a974..1af368caa63 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -233,6 +233,12 @@ will remember the window configuration before GDB started and restore
233it after GDB quits. A toggle button is also provided under 'Gud -- 233it after GDB quits. A toggle button is also provided under 'Gud --
234GDB-Windows'. 234GDB-Windows'.
235 235
236+++
237*** gdb-mi now has a better logic for displaying source buffers
238Now GDB only uses one source window to display source file by default.
239Customize 'gdb-max-source-window-count' to use more than one window.
240Control source file display by 'gdb-display-source-buffer-action'.
241
236** Gravatar 242** Gravatar
237 243
238--- 244---
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index 07506834f18..ba586981de6 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -224,7 +224,9 @@ Only used for files that Emacs can't find.")
224(defvar gdb-source-file-list nil 224(defvar gdb-source-file-list nil
225 "List of source files for the current executable.") 225 "List of source files for the current executable.")
226(defvar gdb-first-done-or-error t) 226(defvar gdb-first-done-or-error t)
227(defvar gdb-source-window nil) 227(defvar gdb-source-window-list nil
228 "List of windows used for displaying source files.
229Sorted in most-recently-visited-first order.")
228(defvar gdb-inferior-status nil) 230(defvar gdb-inferior-status nil)
229(defvar gdb-continuation nil) 231(defvar gdb-continuation nil)
230(defvar gdb-supports-non-stop nil) 232(defvar gdb-supports-non-stop nil)
@@ -645,6 +647,21 @@ Note that this variable only takes effect when variable
645 :group 'gdb 647 :group 'gdb
646 :version "28.1") 648 :version "28.1")
647 649
650(defcustom gdb-display-source-buffer-action '(nil . ((inhibit-same-window . t)))
651 "`display-buffer' action used when GDB displays a source buffer."
652 :type 'list
653 :group 'gdb
654 :version "28.1")
655
656(defcustom gdb-max-source-window-count 1
657 "Maximum number of source windows to use.
658Until there are such number of source windows on screen, GDB
659tries to open a new window when visiting a new source file; after
660that GDB starts to reuse existing source windows."
661 :type 'number
662 :group 'gdb
663 :version "28.1")
664
648(defvar gdbmi-debug-mode nil 665(defvar gdbmi-debug-mode nil
649 "When non-nil, print the messages sent/received from GDB/MI in *Messages*.") 666 "When non-nil, print the messages sent/received from GDB/MI in *Messages*.")
650 667
@@ -984,7 +1001,7 @@ detailed description of this mode.
984 gdb-first-done-or-error t 1001 gdb-first-done-or-error t
985 gdb-buffer-fringe-width (car (window-fringes)) 1002 gdb-buffer-fringe-width (car (window-fringes))
986 gdb-debug-log nil 1003 gdb-debug-log nil
987 gdb-source-window nil 1004 gdb-source-window-list nil
988 gdb-inferior-status nil 1005 gdb-inferior-status nil
989 gdb-continuation nil 1006 gdb-continuation nil
990 gdb-buf-publisher '() 1007 gdb-buf-publisher '()
@@ -2070,17 +2087,36 @@ is running."
2070;; GDB frame (after up, down etc). If no GDB frame is visible but the last 2087;; GDB frame (after up, down etc). If no GDB frame is visible but the last
2071;; visited breakpoint is, use that window. 2088;; visited breakpoint is, use that window.
2072(defun gdb-display-source-buffer (buffer) 2089(defun gdb-display-source-buffer (buffer)
2073 (let* ((last-window (if gud-last-last-frame 2090 "Find a window to display BUFFER.
2074 (get-buffer-window 2091Always find a window to display buffer, and return it."
2075 (gud-find-file (car gud-last-last-frame))))) 2092 ;; This function doesn't take care of setting up source window(s) at startup,
2076 (source-window (or last-window 2093 ;; that's handled by `gdb-setup-windows' (if `gdb-many-windows' is non-nil).
2077 (if (and gdb-source-window 2094 ;; If `buffer' is already shown in a window, use that window.
2078 (window-live-p gdb-source-window)) 2095 (or (get-buffer-window buffer)
2079 gdb-source-window)))) 2096 (progn
2080 (when source-window 2097 ;; First, update the window list.
2081 (setq gdb-source-window source-window) 2098 (setq gdb-source-window-list
2082 (set-window-buffer source-window buffer)) 2099 (cl-remove-duplicates
2083 source-window)) 2100 (cl-remove-if-not
2101 (lambda (win)
2102 (and (window-live-p win)
2103 (eq (window-frame win)
2104 (selected-frame))))
2105 gdb-source-window-list)))
2106 ;; Should we create a new window or reuse one?
2107 (if (> gdb-max-source-window-count
2108 (length gdb-source-window-list))
2109 ;; Create a new window, push it to window list and return it.
2110 (car (push (display-buffer buffer gdb-display-source-buffer-action)
2111 gdb-source-window-list))
2112 ;; Reuse a window, we use the oldest window and put that to
2113 ;; the front of the window list.
2114 (let ((last-win (car (last gdb-source-window-list)))
2115 (rest (butlast gdb-source-window-list)))
2116 (set-window-buffer last-win buffer)
2117 (setq gdb-source-window-list
2118 (cons last-win rest))
2119 last-win)))))
2084 2120
2085 2121
2086(defun gdbmi-start-with (str offset match) 2122(defun gdbmi-start-with (str offset match)
@@ -4071,9 +4107,7 @@ DOC is an optional documentation string."
4071 (let* ((buffer (find-file-noselect 4107 (let* ((buffer (find-file-noselect
4072 (if (file-exists-p file) file 4108 (if (file-exists-p file) file
4073 (cdr (assoc bptno gdb-location-alist))))) 4109 (cdr (assoc bptno gdb-location-alist)))))
4074 (window (or (gdb-display-source-buffer buffer) 4110 (window (gdb-display-source-buffer buffer)))
4075 (display-buffer buffer))))
4076 (setq gdb-source-window window)
4077 (with-current-buffer buffer 4111 (with-current-buffer buffer
4078 (goto-char (point-min)) 4112 (goto-char (point-min))
4079 (forward-line (1- (string-to-number line))) 4113 (forward-line (1- (string-to-number line)))
@@ -4722,7 +4756,7 @@ file\" where the GDB session starts (see `gdb-main-file')."
4722 (select-window win2) 4756 (select-window win2)
4723 (set-window-buffer win2 (or (gdb-get-source-buffer) 4757 (set-window-buffer win2 (or (gdb-get-source-buffer)
4724 (list-buffers-noselect))) 4758 (list-buffers-noselect)))
4725 (setq gdb-source-window (selected-window)) 4759 (setq gdb-source-window-list (list (selected-window)))
4726 (let ((win4 (split-window-right))) 4760 (let ((win4 (split-window-right)))
4727 (gdb-set-window-buffer 4761 (gdb-set-window-buffer
4728 (gdb-get-buffer-create 'gdb-inferior-io) nil win4)) 4762 (gdb-get-buffer-create 'gdb-inferior-io) nil win4))
@@ -4798,7 +4832,8 @@ You can later restore this configuration from that file by
4798 (error "Unrecognized gdb buffer mode: %s" major-mode))) 4832 (error "Unrecognized gdb buffer mode: %s" major-mode)))
4799 ;; Command buffer. 4833 ;; Command buffer.
4800 ((derived-mode-p 'gud-mode) 'command) 4834 ((derived-mode-p 'gud-mode) 'command)
4801 ((equal (selected-window) gdb-source-window) 'source))) 4835 ;; Consider everything else as source buffer.
4836 (t 'source)))
4802 (with-window-non-dedicated nil 4837 (with-window-non-dedicated nil
4803 (set-window-buffer nil placeholder) 4838 (set-window-buffer nil placeholder)
4804 (set-window-prev-buffers (selected-window) nil) 4839 (set-window-prev-buffers (selected-window) nil)
@@ -4841,7 +4876,7 @@ FILE should be a window configuration file saved by
4841 (pcase buffer-type 4876 (pcase buffer-type
4842 ('source (when source-buffer 4877 ('source (when source-buffer
4843 (set-window-buffer nil source-buffer) 4878 (set-window-buffer nil source-buffer)
4844 (setq gdb-source-window (selected-window)))) 4879 (push (selected-window) gdb-source-window-list)))
4845 ('command (switch-to-buffer gud-comint-buffer)) 4880 ('command (switch-to-buffer gud-comint-buffer))
4846 (_ (let ((buffer (gdb-get-buffer-create buffer-type))) 4881 (_ (let ((buffer (gdb-get-buffer-create buffer-type)))
4847 (with-window-non-dedicated nil 4882 (with-window-non-dedicated nil
@@ -4882,7 +4917,7 @@ This arrangement depends on the values of variable
4882 (if gud-last-last-frame 4917 (if gud-last-last-frame
4883 (gud-find-file (car gud-last-last-frame)) 4918 (gud-find-file (car gud-last-last-frame))
4884 (gud-find-file gdb-main-file))) 4919 (gud-find-file gdb-main-file)))
4885 (setq gdb-source-window win))))) 4920 (setq gdb-source-window-list (list win))))))
4886 4921
4887;; Called from `gud-sentinel' in gud.el: 4922;; Called from `gud-sentinel' in gud.el:
4888(defun gdb-reset () 4923(defun gdb-reset ()
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index 567f452b935..eb43e8b7e44 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -2826,9 +2826,13 @@ Obeying it means displaying in another window the specified file and line."
2826 (buffer 2826 (buffer
2827 (with-current-buffer gud-comint-buffer 2827 (with-current-buffer gud-comint-buffer
2828 (gud-find-file true-file))) 2828 (gud-find-file true-file)))
2829 (window (and buffer 2829 (window
2830 (or (get-buffer-window buffer) 2830 (when buffer
2831 (display-buffer buffer '(nil (inhibit-same-window . t)))))) 2831 (if (eq gud-minor-mode 'gdbmi)
2832 (gdb-display-source-buffer buffer)
2833 ;; Gud still has the old behavior.
2834 (or (get-buffer-window buffer)
2835 (display-buffer buffer '(nil (inhibit-same-window . t)))))))
2832 (pos)) 2836 (pos))
2833 (when buffer 2837 (when buffer
2834 (with-current-buffer buffer 2838 (with-current-buffer buffer
@@ -2858,9 +2862,7 @@ Obeying it means displaying in another window the specified file and line."
2858 (widen) 2862 (widen)
2859 (goto-char pos)))) 2863 (goto-char pos))))
2860 (when window 2864 (when window
2861 (set-window-point window gud-overlay-arrow-position) 2865 (set-window-point window gud-overlay-arrow-position)))))
2862 (if (eq gud-minor-mode 'gdbmi)
2863 (setq gdb-source-window window))))))
2864 2866
2865;; The gud-call function must do the right thing whether its invoking 2867;; The gud-call function must do the right thing whether its invoking
2866;; keystroke is from the GUD buffer itself (via major-mode binding) 2868;; keystroke is from the GUD buffer itself (via major-mode binding)