Update & refactor tools/debugger

- Polish dap-mode support
- Fix realgud autoloads
- Add +debugger/start and +debugger/quit
- Move dap-breakpoints file into doom-etc-dir
- Fix SPC o d
- Add popup rule for realgud:pdb debugger
- Update display-in-popup advice to reflect changes upstream
- Realgud command buffer is auto-killed (and popup closed) when quitting
  the debugger.
- (evil users) Add :debug ex command
This commit is contained in:
Henrik Lissner 2019-07-07 21:56:03 +02:00
parent f09a2b60c4
commit 096a3b96cc
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
5 changed files with 138 additions and 43 deletions

View file

@ -436,19 +436,7 @@
:n "gb" #'git-timemachine-blame))
;;; :tools
(map! (:when (featurep! :tools debugger)
:after realgud
:map realgud:shortkey-mode-map
:n "j" #'evil-next-line
:n "k" #'evil-previous-line
:n "h" #'evil-backward-char
:n "l" #'evil-forward-char
:n "c" #'realgud:cmd-continue
:m "n" #'realgud:cmd-next
:m "b" #'realgud:cmd-break
:m "B" #'realgud:cmd-clear)
(:when (featurep! :tools eval)
(map! (:when (featurep! :tools eval)
:g "M-r" #'+eval/buffer
:nv "gr" #'+eval:region
:n "gR" #'+eval/buffer
@ -721,7 +709,7 @@
:desc "Tags search" "m" #'org-tags-view
:desc "View search" "v" #'org-search-view)
:desc "Default browser" "b" #'browse-url-of-file
:desc "Debugger" "d" #'+debug/open
:desc "Start debugger" "d" #'+debugger/start
:desc "REPL" "r" #'+eval/open-repl-other-window
:desc "REPL (same window)" "R" #'+eval/open-repl-same-window
:desc "Dired" "-" #'dired-jump

View file

@ -177,7 +177,7 @@ If BANG, search Doom documentation."
;;; Project tools
(evil-ex-define-cmd "compile" #'+evil:compile)
(evil-ex-define-cmd "mak[e]" #'+evil:make)
;; (evil-ex-define-cmd "debug" #'+debug/run)
(evil-ex-define-cmd "debug" #'+debugger/start)
(evil-ex-define-cmd "er[rors]" #'flycheck-list-errors)
;;; File operations

View file

@ -1,11 +0,0 @@
;;; tools/debugger/autoload/debug.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +debugger/quit ()
"Quit the active debugger, if any."
(interactive)
(ignore-errors (call-interactively #'realgud:cmd-quit))
(doom/popup-close)
(when (featurep 'evil)
(evil-normal-state)))

View file

@ -0,0 +1,82 @@
;;; tools/debugger/autoload/debugger.el -*- lexical-binding: t; -*-
(defvar +debugger--last nil)
(defun +debugger-list-for-dap ()
(when (and (bound-and-true-p lsp-mode)
(require 'dap-mode nil t)
dsp-mode)
(mapcar #'car dap--debug-template-configurations)))
(defun +debugger-list-for-realgud ()
(cl-loop for (sym . plist) in +debugger-realgud-alist
for sym-name = (symbol-name sym)
for modes = (plist-get plist :modes)
if (or (null modes) (apply #'derived-mode-p modes))
collect sym))
(defun +debugger-list-available ()
"TODO"
(append (+debugger-list-for-dap)
(+debugger-list-for-realgud)
nil))
;;
;;; Interactive commands
;;;###autoload
(defun +debugger/start-last ()
"Relaunch the last debugger session."
(interactive)
(unless +debugger--last
(user-error "No last debugger to invoke"))
(call-interactively +debugger--last))
;;;###autoload
(defun +debugger/start (arg)
"Launch a debugger session.
Launches the last used debugger, if one exists. Otherwise, you will be prompted
for what debugger to use. If the prefix ARG is set, prompt anyway."
(interactive "P")
(if (or arg (null +debugger--last))
(let ((debugger (intern-soft (completing-read "Start debugger: " (+debugger-list-available)))))
(unless debugger
(user-error "No debugging session to quit"))
(unless (fboundp debugger)
(user-error "Couldn't find debugger backend %S" debugger))
(setq-local +debugger--last debugger)
(call-interactively debugger))
(+debugger/start-last)))
;;;###autoload
(defun +debugger/quit ()
"Quit the active debugger, if any."
(interactive)
(cond ((and (fboundp 'dap--cur-session) (dap--cur-session))
(dap-disconnect))
((and (fboundp 'realgud-get-cmdbuf) (realgud-get-cmdbuf))
(let ((buf (realgud-get-cmdbuf)))
(ignore-errors
(call-interactively #'realgud:cmd-quit))
(let (realgud-safe-mode)
(kill-buffer buf))))
((user-error "No debugging session to quit"))))
;; TODO debugger breakpoint commands
;; ;;;###autoload
;; (defun +debugger/toggle-breakpoint ()
;; (interactive)
;; (user-error "not implemented yet"))
;; ;;;###autoload
;; (defun +debugger/next-breakpoint ()
;; (interactive)
;; (user-error "not implemented yet"))
;; ;;;###autoload
;; (defun +debugger/previous-breakpoint ()
;; (interactive)
;; (user-error "not implemented yet"))

View file

@ -1,9 +1,31 @@
;;; tools/debugger/config.el -*- lexical-binding: t; -*-
(defvar +debugger--realgud-alist
'((realgud:zshdb :modes (sh-mode))
(realgud:kshdb :modes (sh-mode))
(realgud:rdebug :modes (ruby-mode enh-ruby-mode))
(realgud:pdb :modes (python-mode))
(realgud:trepan2 :modes (python-mode))
(realgud:gub :modes (go-mode))
(realgud:gdb)
(realgud:trepan :modes (perl-mode perl6-mode))
(realgud:trepanpl :modes (perl-mode perl6-mode))
(realgud:trepanjs :modes (javascript-mode js2-mode js3-mode))
(realgud:remake)
(realgud:trepan3k :modes (python-mode))
(realgud:bashdb :modes (sh-mode))
(realgud:perldb :modes (perl-mode perl6-mode))))
;;
;;; Packages
(def-package! dap-mode
:when (featurep! :tools lsp)
:hook (dap-mode . dap-ui-mode)
:after lsp-mode
:init
(setq dap--breakpoints-file (concat doom-etc-dir "dap-breakpoints"))
:config
(dap-mode 1)
(dolist (module '(((:lang . java) lsp-java dap-java)
@ -26,24 +48,35 @@
(require 'dap-node)))))
;; FIXME wildly outdated and untested; rewrite me!
(def-package! realgud
:commands (realgud:gdb realgud:trepanjs realgud:bashdb realgud:zshdb)
:defer t
:init
(def-package! realgud-trepan-ni
:defer t
:init (add-to-list '+debugger--realgud-alist
'(realgud:trepan-ni :modes (javascript-mode js2-mode js3-mode)
:package realgud-trepan-ni)))
;; Realgud doesn't generate its autoloads properly so we do it ourselves
(dolist (debugger +debugger--realgud-alist)
(autoload (car debugger)
(if-let (sym (plist-get (cdr debugger) :package))
(symbol-name sym)
"realgud")
nil t))
:config
(set-popup-rule! "^\\*\\(?:trepanjs:\\(?:g\\|zsh\\|bash\\)db\\)" :size 20)
(set-popup-rule! "^\\*\\(?:trepanjs:\\(?:g\\|zsh\\|bash\\)db\\|pdb \\)"
:size 20 :select nil :quit nil)
(when (featurep! :lang javascript)
(after! js2-mode
(require 'realgud-trepan-ni)))
;; TODO Temporary Ex commands for the debugger
;; (def-tmp-excmd! doom:def-debug-on doom:def-debug-off
;; ("n[ext]" . realgud:cmd-next)
;; ("s[tep]" . realgud:cmd-step)
;; ("b[reak]" . +debug:toggle-breakpoint)
;; ("c[ontinue]" . realgud:cmd-continue))
;; (advice-add #'realgud-cmdbuf-init :after #'doom:def-debug-on)
;; (advice-add #'realgud:cmd-quit :after #'doom:def-debug-off)
(defun +debugger*cleanup-when-realgud-terminates (&optional buf)
"Kill command buffer when debugging session ends (which closes its popup)."
(when (stringp buf)
(setq buf (get-buffer buf)))
(when-let (cmdbuf (realgud-get-cmdbuf buf))
(let (kill-buffer-hook)
(kill-buffer buf))))
(advice-add #'realgud:terminate :after #'+debugger*cleanup-when-realgud-terminates)
;; Monkey-patch `realgud:run-process' to run in a popup.
;; TODO Find a more elegant solution
@ -55,7 +88,7 @@
(process (get-buffer-process cmd-buf)))
(cond ((and process (eq 'run (process-status process)))
(pop-to-buffer cmd-buf)
(define-key evil-emacs-state-local-map (kbd "ESC ESC") #'+debug/quit)
(define-key evil-emacs-state-local-map (kbd "ESC ESC") #'+debugger/quit)
(realgud:track-set-debugger debugger-name)
(realgud-cmdbuf-info-in-debugger?= 't)
(realgud-cmdbuf-info-cmd-args= cmd-args)
@ -65,8 +98,11 @@
(let* ((info realgud-cmdbuf-info)
(cmd-args (realgud-cmdbuf-info-cmd-args info))
(cmd-str (mapconcat #'identity cmd-args " ")))
(if (boundp 'starting-directory)
(realgud-cmdbuf-info-starting-directory= starting-directory))
(set minibuffer-history-var
(list-utils-uniq (cons cmd-str (eval minibuffer-history-var))))))))
(cl-remove-duplicates
(cons cmd-str (eval minibuffer-history)) :from-end))))))
(t
(if cmd-buf (switch-to-buffer cmd-buf))
(message "Error running command: %s" (mapconcat #'identity cmd-args " "))))