refactor!(debugger): replace realgud with dape

BREAKING CHANGE: Anyone used to realgud will find it missing as of this
commit. It's been replaced with Dape (see
https://github.com/svaante/dape).

This change was made because realgud's implementation was archaic and
over-complicated, dap-mode requires lsp-mode (and has a lot of moving
parts and points of failure), and dape is straight-forward by
comparison; to set up and use. Note that dap-mode and dap-ui is now
deprecated and will be removed in the future, but still remains behind
the +lsp flag for backwards compatibility, at least until v3.

This also adds a '<leader> d' prefix for debugger commands (except for
vanilla users, who already have dape's prefix on 'C-x C-a')
This commit is contained in:
Henrik Lissner
2025-04-20 21:25:12 -04:00
parent ed85328f57
commit b4bd368485
6 changed files with 87 additions and 421 deletions

View File

@ -482,6 +482,34 @@
:desc "Delete trailing newlines" "W" #'doom/delete-trailing-newlines
:desc "List errors" "x" #'+default/diagnostics)
;;; <leader> d --- debugger
(:when (modulep! :tools debugger)
(:prefix-map ("d" . "debugger")
"d" #'dape
"p" #'dape-pause
"c" #'dape-continue
"n" #'dape-next
"s" #'dape-step-in
"o" #'dape-step-out
"r" #'dape-restart
"i" #'dape-info
"R" #'dape-repl
"m" #'dape-memory
"M" #'dape-disassemble
"l" #'dape-breakpoint-log
"e" #'dape-breakpoint-expression
"h" #'dape-breakpoint-hits
"b" #'dape-breakpoint-toggle
"B" #'dape-breakpoint-remove-all
"t" #'dape-select-thread
"S" #'dape-select-stack
">" #'dape-stack-select-down
"<" #'dape-stack-select-up
"x" #'dape-evaluate-expression
"w" #'dape-watch-dwim
"D" #'dape-disconnect-quit
"q" #'dape-quit))
;;; <leader> f --- file
(:prefix-map ("f" . "file")
:desc "Open project editorconfig" "c" #'editorconfig-find-current-editorconfig
@ -687,7 +715,7 @@
:desc "Tags search" "m" #'org-tags-view
:desc "View search" "v" #'org-search-view)
:desc "Default browser" "b" #'browse-url-of-file
:desc "Start debugger" "d" #'+debugger/start
:desc "Start a debugger" "d" #'+debugger/start
:desc "New frame" "f" #'make-frame
:desc "Select frame" "F" #'select-frame-by-name
:desc "REPL" "r" #'+eval/open-repl-other-window

View File

@ -4,213 +4,64 @@
#+since: 2.0.0
* Description :unfold:
Introduces a code debugger to Emacs, powered by [[doom-package:realgud]] or [[doom-package:dap-mode]] (LSP).
This document will help you to configure [[doom-package:dap-mode]] [[https://emacs-lsp.github.io/dap-mode/page/configuration/#native-debug-gdblldb][Native Debug(GDB/LLDB)]] as
there is still not *enough* documentation for it.
Turns Emacs into a debug adapter client, powered by [[doom-package:dape]]. The debug
adapter protocol aims to establish a standardized interface and API for
debuggers.
** Maintainers
/This module has no dedicated maintainers./ [[doom-contrib-maintainer:][Become a maintainer?]]
** Module flags
- +lsp ::
Enable support for [[https://microsoft.github.io/debug-adapter-protocol/][Debug Adapter Protocol]] (DAP) debuggers.
*(This flag is deprecated)* Installs [[doom-package:dap-mode]] and
[[doom-package:dap-ui]]. Requires [[doom-module::tools lsp]] (not compatible with
Eglot).
** Packages
- [[doom-package:realgud]]
- [[doom-package:realgud-trepan-ni]] if [[doom-module::lang javascript]]
- [[doom-package:dape]]
- if [[doom-module:+lsp]]
- [[doom-package:dap-mode]]
- [[doom-package:posframe]]
** Hacks
- Enables ~gdb-many-windows-mode~ in ~gdb-mode~ by default
- Patches [[doom-package:realgud]] to open in a popup window. This causes realgud
bindings to focus the command window.
- Closes [[doom-package:realgud]]'s command buffer after the session ends.
/No hacks documented for this module./
** TODO Changelog
# This section will be machine generated. Don't edit it by hand.
/This module does not have a changelog yet./
* TODO Installation
#+begin_quote
󱌣 /This module's prerequisites documentation is incomplete./ [[doom-contrib-module:][Complete it?]]
#+end_quote
* Installation
[[id:01cffea4-3329-45e2-a892-95a384ab2338][Enable this module in your ~doom!~ block.]]
Make sure all of these pre-requirements is in your ~$PATH~:
- =nodejs=
- =lldb= and =lldb-mi= (optional)
- =gdb= (optional), requires =unzip=
Then check out the [[https://github.com/svaante/dape?tab=readme-ov-file#supported-debug-adapters][install instructions for the debug adapters]] you want to work
with.
If you are getting an error like ~Searching for program no such file or
directory "node"~, then you need [[github:nodejs/node][nodejs]] ([[github:emacs-lsp/dap-mode/issues/79][emacs-lsp/dap-mode#79]]).
** Realgud debuggers
*** lldb and lldb-mi
This is optional if you want to debug with [[https:lldb.llvm.org][LLDB]]. Install lldb and [[github:lldb-tools/lldb-mi][lldb-mi]].
*** gdb
This is optional if you want to debug with [[https:www.gnu.org/software/gdb/][GDB]]. Install gdb.
You will need ~unzip~ for ~dap-gdb-lldb-setup~. It downloads a VS-Code extension
and it needs to extract compressed downloaded file.
You need this if you are having ~"wrong-type-argument stringp nil"~ error when
calling ~dap-gdb-lldb-setup~. [[github:emacs-lsp/dap-mode/issues/313][See emacs-lsp/dap-mode#313]]
** DAP debuggers
*** dap-cpptools
- Languages: C, C++, Rust
- Documentation
- [[https://code.visualstudio.com/docs/cpp/cpp-debug][adapter]]
- [[https://emacs-lsp.github.io/dap-mode/page/configuration/#vscode-cpptools][dap-mode configuration]]
Run =M-x dap-cpptools-setup= to setup the adapter before using it the first
time.
*** dap-gdb-lldb
- Languages: C, C++, Rust
- Documentation
- [[https://github.com/WebFreak001/code-debug][adapter]]
- [[https://emacs-lsp.github.io/dap-mode/page/configuration/#native-debug-gdblldb][dap-mode configuration]]
Install the vscode extension using =M-x dap-gdb-lldb-setup= before using it the
first time.
*** dap-lldb
- Languages: C, C++, Rust
- Documentation
- [[https://github.com/llvm/llvm-project/tree/main/lldb/tools/lldb-vscode][adapter]]
- [[https://emacs-lsp.github.io/dap-mode/page/configuration/#lldb][dap-mode configuration]]
Needs [[https://github.com/llvm/llvm-project/tree/main/lldb/tools/lldb-vscode][lldb-vscode]]. Install LLDB from your package manager. For example:
- *Arch Linux:* ~$ pacman -S lldb~
- *Fedora:* ~$ dnf install lldb~
*** dap-python
- Languages: Python
- Documentation:
- [[https://github.com/microsoft/debugpy/][adapter]]
- [[https://emacs-lsp.github.io/dap-mode/page/configuration/#python][dap-mode configuration]]
By default, DAP expects [[https://github.com/Microsoft/ptvsd][ptvsd]] as the Python debugger, but [[https://github.com/microsoft/debugpy][debugpy]] is
recommended. See [[*Configuration][Configuration]].
*installing ptvsd and debugpy:*
#+begin_src sh
$ pip3 install ptvsd --user
$ pip3 install debugpy --user
#+end_src
#+begin_src emacs-lisp
;; in $DOOMDIR/config.el
(after! dap-mode
(setq dap-python-debugger 'debugpy))
#+end_src* TODO Usage
* Usage
Start a debugging session with ~M-x +debugger/start~ (bound to [[kbd:][SPC o d]] in evil).
You'll be prompted to select a debugger preset if this is the first time you've
used it. Otherwise, it will use the last preset automatically. Use the
universal/prefix argument to invoke this prompt again: [[kbd:][SPC u SPC o d]] or [[kbd:][C-u C-c
o d]]. The last used configuration is stored for each project individually.
~M-x +debugger/start-last~ starts the last used debug configuration, if it
exists, and prints a message otherwise instead of offering a selection.
Once the session is started, it can be terminated by ~M-x +debugger/quit~ or by
using the mode-specific way.
** TODO realgud
#+begin_quote
󱌣 Instructions for realgud haven't been written yet. [[doom-contrib-module:][Write some?]]
 Dape's documentation will instruct you to install debug adapters to
=$EMACSDIR/debug-adapters/=, but Doom uses =$DOOMDIR/debug-adapters/= instead!
Alter [[var:][dape-adapter-dir]] to change this.
#+end_quote
** dap-mode
*** How to add a debug configuration
1. Call ~dap-gdb-lldb-setup~ function.
2. Use ~dap-debug-edit-template~ to configure debugging settings for your
project. [[github:WebFreak001/code-debug/blob/master/package.json#L72][Available settings can be inspected here.]] Call ~eval-buffer~ to save
your settings. *Don't save the file!*
3. Call ~dap-debug~, select a configuration and start debugging.
* Usage
Start the debugger with ~M-x +debugger/start~ (bound to [[kbd:][<leader> o d]]). You'll be
prompted to enter a debugger configuration to launch (use [[kbd:][<up>]]/[[kbd:][<down>]] to
traverse your history of debugger configs).
*** dap-mode with ~+lsp~
Intuitive and powerful debugging.
- Breakpoints
- REPL
- *local variable view:* Allows you to browse variables in the current stack
frame.
- *expressions:* Add expressions to either watch variables or generic
expressions.
** Keybindings
*** General
| Keybind | Description |
|---------+--------------------------|
| [[kbd:][SPC o d]] | Start a debugger session |
*** dap-mode
When a dap-mode session is running, the following mappings are active:
| Keybind | Description |
|---------+----------------------------------|
| [[kbd:][SPC m d]] | Open a hydra for session control |
The hydra is defined as follows:
#+begin_src emacs-lisp
(map! :map dap-mode-map
:leader
:prefix ("d" . "dap")
;; basics
:desc "dap next" "n" #'dap-next
:desc "dap step in" "i" #'dap-step-in
:desc "dap step out" "o" #'dap-step-out
:desc "dap continue" "c" #'dap-continue
:desc "dap hydra" "h" #'dap-hydra
:desc "dap debug restart" "r" #'dap-debug-restart
:desc "dap debug" "s" #'dap-debug
;; debug
:prefix ("dd" . "Debug")
:desc "dap debug recent" "r" #'dap-debug-recent
:desc "dap debug last" "l" #'dap-debug-last
;; eval
:prefix ("de" . "Eval")
:desc "eval" "e" #'dap-eval
:desc "eval region" "r" #'dap-eval-region
:desc "eval thing at point" "s" #'dap-eval-thing-at-point
:desc "add expression" "a" #'dap-ui-expressions-add
:desc "remove expression" "d" #'dap-ui-expressions-remove
:prefix ("db" . "Breakpoint")
:desc "dap breakpoint toggle" "b" #'dap-breakpoint-toggle
:desc "dap breakpoint condition" "c" #'dap-breakpoint-condition
:desc "dap breakpoint hit count" "h" #'dap-breakpoint-hit-condition
:desc "dap breakpoint log message" "l" #'dap-breakpoint-log-message)
#+end_src
Once the session is started, it can be terminated by ~M-x +debugger/quit~.
* TODO Configuration
#+begin_quote
󱌣 This module has no configuration documentation yet. [[doom-contrib-module:][Write some?]]
#+end_quote
The default debugger configs can be found in [[var:dape-configs]].
* Troubleshooting
- There is a known issue with the ~+debugger/start~ command, which is bound to
[[kbd:][SPC o d]] right now. It prints "No debugging session to quit" no matter what.
/There are no known problems with this module./ [[doom-report:][Report one?]]
* Frequently asked questions
/This module has no FAQs yet./ [[doom-suggest-faq:][Ask one?]]
** Setting breakpoints in realgud does not work outside a session
This currently is not supported by realgud.
* TODO Appendix
#+begin_quote
󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]]

View File

@ -1,134 +1,25 @@
;;; 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."
(defun +debugger/start ()
"Start a debugger in the current project and buffer."
(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))
(call-interactively
(if (and (modulep! +lsp)
(bound-and-true-p lsp-mode)
(require 'dap-mode nil t))
#'dap-debug
#'dape)))
;;;###autoload
(defun +debugger/quit ()
"Quit the active debugger, if any."
"Quit the active debugger session."
(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"))
(if-let* ((conn (and (modulep! +lsp)
(require 'dap-mode nil t)
(dap--cur-session))))
(dap-disconnect conn)
(if-let* ((conn (and (featurep 'dape)
(dape--live-connection 'parent t))))
(dape-quit conn)
(user-error "No debugger session to quit"))))

View File

@ -1,34 +0,0 @@
;; tools/debugger/autoload/evil.el -*- lexical-binding: t; -*-
;;;###if (modulep! :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

@ -1,21 +1,5 @@
;;; 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)
@ -29,86 +13,32 @@
((:lang javascript +lsp)
:after (js2-mode typescript-mode)
:require (dap-node dap-chrome dap-firefox ,@(if (featurep :system 'windows) '(dap-edge)))))
"TODO")
"An alist mapping Doom modules to major mode and DAP packages.")
;;
;;; Packages
;;;###package gdb
(setq gdb-show-main t
gdb-many-windows t)
(use-package! projectile-variable
(use-package! dape
: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))
:preface
(setq dape-adapter-dir (file-name-concat doom-user-dir "debug-adapters/"))
:config
(set-popup-rule! "^\\*\\(?:trepanjs:\\(?:g\\|zsh\\|bash\\)db\\|pdb \\)"
:size 20 :select nil :quit nil)
(set-debug-variable! 'dape-debug t)
(setq dape-buffer-window-arrangement 'right
dape-inlay-hints t
dape-cwd-function #'projectile-project-root)
(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))))
;; Mode-line serves no purpose in REPL window.
(add-hook 'dape-repl-mode-hook #'hide-mode-line-mode)
;; 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)))
;; Persist breakpoints after closing DAPE.
(dape-breakpoint-global-mode +1)
(add-hook 'dape-start-hook #'dape-breakpoint-load 0)
(add-hook 'dape-stopped-hook #'dape-breakpoint-save 'append))
;; DEPRECATED
(use-package! dap-mode
:when (modulep! +lsp)
:when (modulep! :tools lsp -eglot)
@ -156,6 +86,7 @@
"d" #'dap-hydra))
;; DEPRECATED
(use-package! dap-ui
:when (modulep! +lsp)
:when (modulep! :tools lsp -eglot)

View File

@ -1,10 +1,9 @@
;; -*- no-byte-compile: t; -*-
;;; tools/debugger/packages.el
(when (package! realgud :pin "365063ea8ce8ec6a852cb388088d84147421c3c2")
(when (modulep! :lang javascript)
(package! realgud-trepan-ni :pin "0ec088ea343835e24ae73da09bea96bfb02a3130")))
(package! dape :pin "c7a1f1abdbbcdb9135a73c00c58ef2f0a949f87c")
;; DEPRECATED
(when (modulep! +lsp)
(package! dap-mode :pin "56e92dd86b526c191275cf7813208baad14e0c5d")
(package! posframe :pin "12f540c9ad5da09673b2bca1132b41f94c134e82"))