Emacs provides a wrapper for various debuggers including GDB called the Grand Unified Debugger (GUD). I’ve tried it in the past but always run into lots of minor annoyances with the UI so I just use command line GDB instead. But recently I’ve being trying to adopt a more “Emacs native” workflow, including using EShell instead of a separate terminal window for Bash, Magit instead of command line git, ERC for IRC, etc. So let’s see if we can fix these GUD problems…
(setq gdb-many-windows t gdb-use-separate-io-buffer t)
The default mode of GUD just creates a single window with the the normal GDB terminal. This doesn’t seem to offer much over running GDB directly. The “many windows” mode splits the screen into six separate windows showing the current source file, locals/registers, output, etc.
Source file opens in the wrong window
By default if you jump to a source file from e.g. the stack trace window it will open on top of the command input window (labeled “2” below) rather than the source file window “1”.
This seems to be “normal” behaviour, and there are loads of threads on Stack Overflow complaining about it but with no conclusive solution. E.g. see here or here.
The problem here is that GUD makes all the popup windows “dedicated” except for the command window. When you jump to a file it opens in the first non-dedicated window, which sort-of makes sense. The function that sets up the windows is called
gdb-setup-windows so we can use Emacs’ “advice” system to hook this function and run some extra code afterwards to make the command window dedicated:
(advice-add 'gdb-setup-windows :after (lambda () (set-window-dedicated-p (selected-window) t)))
This works because
gdb-setup-windows always leaves the command window selected when it finishes.
Quitting messes up the window configuration
How do you quit anyway? I think the correct way is just to run
quit in the command window. But no matter how you quit GUD always messes up whatever window configuration you had before you opened it.
We can fix that by saving the window layout when we run
M-x gdb by storing the layout into a register in
gud-sentinal function runs when some event occurs on the inferior
gdb process. We can hook that to restore the window state when the process exits.
(defconst gud-window-register 123456) (defun gud-quit () (interactive) (gud-basic-call "quit")) (add-hook 'gud-mode-hook (lambda () (gud-tooltip-mode) (window-configuration-to-register gud-window-register) (local-set-key (kbd "C-q") 'gud-quit))) (advice-add 'gud-sentinel :after (lambda (proc msg) (when (memq (process-status proc) '(signal exit)) (jump-to-register gud-window-register) (bury-buffer))))
gud-quit which send the
quit command to GDB to save typing.