This commit is contained in:
ry
2022-01-11 18:05:13 -08:00
parent 2046befee2
commit 8e7b654716
846 changed files with 71287 additions and 4 deletions

View File

@@ -0,0 +1,134 @@
;;; tools/debugger/autoload/debugger.el -*- lexical-binding: t; -*-
(defvar-local +debugger--last-config nil
"Configuration of the last debugging session of buffer.")
(put '+debugger--last-config 'permanent-local t) ; don't kill on mode change
(defun +debugger--get-last-config ()
"Get last debugging configuration.
If in a project, returns the configuration of the last debugging session in the
project, if any. Else, returns the last debugging configuration of the current
buffer, if any."
(if (doom-project-p)
(doom-store-get (doom-project-root) "+debugger")
+debugger--last-config))
(defun +debugger--set-config (config)
"Remember this debugging configuration for `+debugger/start-last'.
If in a project, sets the project's debugging session configuration. Else, sets
the debugging configuration of the current buffer."
(if (doom-project-p)
(doom-store-put (doom-project-root) config
(lambda (key _cfg) (file-directory-p key))
"+debugger")
(setq +debugger--last-config config)))
(defun +debugger--list-for-dap ()
(and (or (bound-and-true-p lsp-mode)
(bound-and-true-p lsp--buffer-deferred))
(require 'dap-mode nil t)
dap-mode
(mapcar (lambda (c) (cons 'dap c))
(apply #'append (mapcar #'funcall dap-launch-configuration-providers)))))
(defun +debugger--list-for-realgud ()
(mapcar (lambda (c) (cons 'realgud (list (symbol-name c))))
(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)))
;; Based on dap--completing-read and dap-debug
(defun +debugger-completing-read ()
"Completing read for debug configuration.
Presents both dap and realgud configurations, and returns a list of the form
\('dap ...) or ('realgud ...) containing the corresponding debug configuration
infromation."
(let* ((result (mapcar (lambda (c) (cons (cadr c) c))
(append (+debugger--list-for-dap)
(+debugger--list-for-realgud))))
(completion (completing-read "Start debugger: " (mapcar #'car result) nil t)))
(if (or (null completion) (string-empty-p completion))
(user-error "No debugging configuration specified.")
(let ((configuration (cdr (assoc completion result))))
(if (eq (car configuration) 'dap)
;; get dap debugging arguments
(let* ((debug-args (dap-variables-expand-in-launch-configuration
(copy-tree (cddr configuration))))
(launch-args (or (catch 'is-nil
(funcall (or (gethash
(or (plist-get debug-args :type)
(throw 'is-nil nil)) dap--debug-providers)
(throw 'is-nil nil)) debug-args))
(user-error "Have you loaded the `%s' specific dap package?"
(or (plist-get debug-args :type)
(user-error "%s does not specify :type" debug-args))))))
(cons 'dap launch-args))
(cons 'realgud (intern (cadr configuration))))))))
;;
;;; Interactive commands
;;;###autoload
(defun +debugger/start-last ()
"Relaunch the last debugger session."
(interactive)
(let ((configuration (+debugger--get-last-config)))
(unless configuration
(user-error "No last debugger%s to invoke"
(if (doom-project-p)
" of this project"
"")))
(let ((launch-args (cdr configuration)))
(if (eq (car configuration) 'dap)
;; start dap configuration
(if (functionp launch-args)
(funcall launch-args #'dap-start-debugging-noexpand)
(dap-start-debugging-noexpand launch-args))
;; else start realgud configuration:
(call-interactively launch-args)))))
;;;###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")
(when (or arg (null (+debugger--get-last-config)))
(+debugger--set-config (+debugger-completing-read)))
(+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 (dap--cur-session)))
((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

@@ -0,0 +1,34 @@
;; tools/debugger/autoload/evil.el -*- lexical-binding: t; -*-
;;;###if (featurep! :editor evil)
;;;###autoload (autoload '+debugger:start "tools/debugger/autoload/evil" nil t)
(evil-define-command +debugger:start (&optional path)
"Initiate debugger for current major mode"
(interactive "<f>")
;; TODO Add python debugging
(let ((default-directory (doom-project-root)))
(pcase major-mode
((or 'c-mode 'c++-mode)
(realgud:gdb (if path (concat "gdb " path))))
('ruby-mode
;; FIXME
(doom:repl nil (format "run '%s'" (file-name-nondirectory (or path buffer-file-name)))))
('sh-mode
(let ((shell sh-shell))
(when (string= shell "sh")
(setq shell "bash"))
(pcase shell
("bash"
(realgud:bashdb (if path (concat "bashdb " path))))
("zsh"
(realgud:zshdb (if path (concat "zshdb " path))))
(_ (user-error "No shell debugger for %s" shell)))))
((or 'js-mode 'js2-mode 'js3-mode)
(realgud:trepanjs))
('haskell-mode (haskell-debug))
(_ (user-error "No debugger for %s" major-mode)))))
;;;###autoload (autoload '+debugger:toggle-breakpoint "tools/debugger/autoload/evil" nil t)
(evil-define-command +debugger:toggle-breakpoint (&optional bang)
(interactive "<!>")
(call-interactively (if bang #'realgud:cmd-clear #'realgud:cmd-break)))

View File

@@ -0,0 +1,160 @@
;;; tools/debugger/config.el -*- lexical-binding: t; -*-
(defvar +debugger--realgud-alist
'((realgud:bashdb :modes (sh-mode))
(realgud:gdb)
(realgud:gub :modes (go-mode))
(realgud:kshdb :modes (sh-mode))
(realgud:pdb :modes (python-mode))
(realgud:perldb :modes (perl-mode perl6-mode))
(realgud:rdebug :modes (ruby-mode))
(realgud:remake)
(realgud:trepan :modes (perl-mode perl6-mode))
(realgud:trepan2 :modes (python-mode))
(realgud:trepan3k :modes (python-mode))
(realgud:trepanjs :modes (javascript-mode js2-mode js3-mode))
(realgud:trepanpl :modes (perl-mode perl6-mode raku-mode))
(realgud:zshdb :modes (sh-mode))))
(defvar +debugger--dap-alist
`(((:lang cc +lsp) :after ccls :require (dap-lldb dap-gdb-lldb))
((:lang elixir +lsp) :after elixir-mode :require dap-elixir)
((:lang go +lsp) :after go-mode :require dap-go)
((:lang java +lsp) :after java-mode :require lsp-java)
((:lang php +lsp) :after php-mode :require dap-php)
((:lang python +lsp) :after python :require dap-python)
((:lang ruby +lsp) :after ruby-mode :require dap-ruby)
((:lang rust +lsp) :after rustic-mode :require (dap-lldb dap-cpptools))
((:lang javascript +lsp)
:after (js2-mode typescript-mode)
:require (dap-node dap-chrome dap-firefox ,@(if IS-WINDOWS '(dap-edge)))))
"TODO")
;;
;;; Packages
;;;###package gdb
(setq gdb-show-main t
gdb-many-windows t)
(use-package! projectile-variable
:defer t
:commands (projectile-variable-put
projectile-variable-get
projectile-variable-alist
projectile-variable-plist))
(use-package! realgud
:defer t
:init
(use-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\\|pdb \\)"
:size 20 :select nil :quit nil)
(defadvice! +debugger--cleanup-after-realgud-a (&optional buf)
"Kill command buffer when debugging session ends (which closes its popup)."
:after #'realgud:terminate
(when (stringp buf)
(setq buf (get-buffer buf)))
(when-let (cmdbuf (realgud-get-cmdbuf buf))
(let (kill-buffer-hook)
(kill-buffer buf))))
;; Monkey-patch `realgud:run-process' to run in a popup.
;; TODO Find a more elegant solution
;; FIXME Causes realgud:cmd-* to focus popup on every invocation
(defadvice! +debugger--realgud-open-in-other-window-a
(debugger-name script-filename cmd-args minibuffer-history-var &optional no-reset)
:override #'realgud:run-process
(let* ((cmd-buf (apply #'realgud-exec-shell debugger-name script-filename
(car cmd-args) no-reset (cdr cmd-args)))
(process (get-buffer-process cmd-buf)))
(cond ((and process (eq 'run (process-status process)))
(pop-to-buffer cmd-buf)
(when (boundp 'evil-emacs-state-local-map)
(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)
(when cmd-buf
(switch-to-buffer cmd-buf)
(when realgud-cmdbuf-info
(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
(cl-remove-duplicates (cons cmd-str (eval minibuffer-history-var))
:from-end t))))))
(t
(if cmd-buf (switch-to-buffer cmd-buf))
(message "Error running command: %s" (mapconcat #'identity cmd-args " "))))
cmd-buf)))
(use-package! dap-mode
:when (and (featurep! +lsp) (not (featurep! :tools lsp +eglot)))
:hook (dap-mode . dap-tooltip-mode)
:init
(setq dap-breakpoints-file (concat doom-etc-dir "dap-breakpoints")
dap-utils-extension-path (concat doom-etc-dir "dap-extension/"))
(after! lsp-mode (require 'dap-mode))
:config
(pcase-dolist (`((,category . ,modules) :after ,after :require ,libs)
+debugger--dap-alist)
(when (doom-module-p category (car modules) (cadr modules))
(dolist (lib (doom-enlist after))
(with-eval-after-load lib
(mapc #'require (doom-enlist libs))))))
(dap-mode 1)
(define-minor-mode +dap-running-session-mode
"A mode for adding keybindings to running sessions"
:init-value nil
:keymap (make-sparse-keymap)
(when (bound-and-true-p evil-mode)
(evil-normalize-keymaps)) ; if you use evil, this is necessary to update the keymaps
;; The following code adds to the dap-terminated-hook so that this minor
;; mode will be deactivated when the debugger finishes
(when +dap-running-session-mode
(let ((session-at-creation (dap--cur-active-session-or-die)))
(add-hook 'dap-terminated-hook
(lambda (session)
(when (eq session session-at-creation)
(+dap-running-session-mode -1)))))))
;; Activate this minor mode when dap is initialized
(add-hook 'dap-session-created-hook #'+dap-running-session-mode)
;; Activate this minor mode when hitting a breakpoint in another file
(add-hook 'dap-stopped-hook #'+dap-running-session-mode)
;; Activate this minor mode when stepping into code in another file
(add-hook 'dap-stack-frame-changed-hook (lambda (session)
(when (dap--session-running session)
(+dap-running-session-mode 1))))
(map! :localleader
:map +dap-running-session-mode-map
"d" #'dap-hydra))
(use-package! dap-ui
:when (featurep! +lsp)
:hook (dap-mode . dap-ui-mode)
:hook (dap-ui-mode . dap-ui-controls-mode))

View File

@@ -0,0 +1,4 @@
;;; tools/debugger/doctor.el -*- lexical-binding: t; -*-
(when (and (featurep! +lsp) (featurep! :tools lsp +eglot))
(warn! "+lsp flag is not compatible with :tools (lsp +eglot). Choose only one of (eglot or dap-mode) please"))

View File

@@ -0,0 +1,10 @@
;; -*- no-byte-compile: t; -*-
;;; tools/debugger/packages.el
(when (package! realgud :pin "3c88611c4ed59069093187c2a039b8d05cbe53e8")
(when (featurep! :lang javascript)
(package! realgud-trepan-ni :pin "0ec088ea343835e24ae73da09bea96bfb02a3130")))
(when (featurep! +lsp)
(package! dap-mode :pin "76cad34de8984f57c2b1e374e9c985cc7ec8dad0")
(package! posframe :pin "6c0e63d6b3b6638c11729c5db28019a38ff44f5b"))