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)) :n "gb" #'git-timemachine-blame))
;;; :tools ;;; :tools
(map! (:when (featurep! :tools debugger) (map! (:when (featurep! :tools eval)
: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)
:g "M-r" #'+eval/buffer :g "M-r" #'+eval/buffer
:nv "gr" #'+eval:region :nv "gr" #'+eval:region
:n "gR" #'+eval/buffer :n "gR" #'+eval/buffer
@ -721,7 +709,7 @@
:desc "Tags search" "m" #'org-tags-view :desc "Tags search" "m" #'org-tags-view
:desc "View search" "v" #'org-search-view) :desc "View search" "v" #'org-search-view)
:desc "Default browser" "b" #'browse-url-of-file :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" "r" #'+eval/open-repl-other-window
:desc "REPL (same window)" "R" #'+eval/open-repl-same-window :desc "REPL (same window)" "R" #'+eval/open-repl-same-window
:desc "Dired" "-" #'dired-jump :desc "Dired" "-" #'dired-jump

View file

@ -177,7 +177,7 @@ If BANG, search Doom documentation."
;;; Project tools ;;; Project tools
(evil-ex-define-cmd "compile" #'+evil:compile) (evil-ex-define-cmd "compile" #'+evil:compile)
(evil-ex-define-cmd "mak[e]" #'+evil:make) (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) (evil-ex-define-cmd "er[rors]" #'flycheck-list-errors)
;;; File operations ;;; 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; -*- ;;; 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 (def-package! dap-mode
:when (featurep! :tools lsp) :when (featurep! :tools lsp)
:hook (dap-mode . dap-ui-mode) :hook (dap-mode . dap-ui-mode)
:after lsp-mode :after lsp-mode
:init
(setq dap--breakpoints-file (concat doom-etc-dir "dap-breakpoints"))
:config :config
(dap-mode 1) (dap-mode 1)
(dolist (module '(((:lang . java) lsp-java dap-java) (dolist (module '(((:lang . java) lsp-java dap-java)
@ -26,24 +48,35 @@
(require 'dap-node))))) (require 'dap-node)))))
;; FIXME wildly outdated and untested; rewrite me!
(def-package! realgud (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 :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) (defun +debugger*cleanup-when-realgud-terminates (&optional buf)
(after! js2-mode "Kill command buffer when debugging session ends (which closes its popup)."
(require 'realgud-trepan-ni))) (when (stringp buf)
(setq buf (get-buffer buf)))
;; TODO Temporary Ex commands for the debugger (when-let (cmdbuf (realgud-get-cmdbuf buf))
;; (def-tmp-excmd! doom:def-debug-on doom:def-debug-off (let (kill-buffer-hook)
;; ("n[ext]" . realgud:cmd-next) (kill-buffer buf))))
;; ("s[tep]" . realgud:cmd-step) (advice-add #'realgud:terminate :after #'+debugger*cleanup-when-realgud-terminates)
;; ("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)
;; Monkey-patch `realgud:run-process' to run in a popup. ;; Monkey-patch `realgud:run-process' to run in a popup.
;; TODO Find a more elegant solution ;; TODO Find a more elegant solution
@ -55,7 +88,7 @@
(process (get-buffer-process cmd-buf))) (process (get-buffer-process cmd-buf)))
(cond ((and process (eq 'run (process-status process))) (cond ((and process (eq 'run (process-status process)))
(pop-to-buffer cmd-buf) (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:track-set-debugger debugger-name)
(realgud-cmdbuf-info-in-debugger?= 't) (realgud-cmdbuf-info-in-debugger?= 't)
(realgud-cmdbuf-info-cmd-args= cmd-args) (realgud-cmdbuf-info-cmd-args= cmd-args)
@ -65,8 +98,11 @@
(let* ((info realgud-cmdbuf-info) (let* ((info realgud-cmdbuf-info)
(cmd-args (realgud-cmdbuf-info-cmd-args info)) (cmd-args (realgud-cmdbuf-info-cmd-args info))
(cmd-str (mapconcat #'identity cmd-args " "))) (cmd-str (mapconcat #'identity cmd-args " ")))
(if (boundp 'starting-directory)
(realgud-cmdbuf-info-starting-directory= starting-directory))
(set minibuffer-history-var (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 (t
(if cmd-buf (switch-to-buffer cmd-buf)) (if cmd-buf (switch-to-buffer cmd-buf))
(message "Error running command: %s" (mapconcat #'identity cmd-args " ")))) (message "Error running command: %s" (mapconcat #'identity cmd-args " "))))