File: README.org

package info (click to toggle)
emacs-dape 0.25.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 420 kB
  • sloc: lisp: 5,608; makefile: 32
file content (279 lines) | stat: -rw-r--r-- 12,662 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#+title: Dape - Debug Adapter Protocol for Emacs
#+author: Daniel Pettersson
#+property: header-args    :results silent
#+language: en

#+html: <a href="https://elpa.gnu.org/packages/dape.html"><img alt="GNU ELPA" src="https://elpa.gnu.org/packages/dape.svg"/></a>

=Dape= is a debug adapter client for Emacs. The debug adapter protocol, much like its more well-known counterpart, the language server protocol, aims to establish a common API for programming tools. However, instead of functionalities such as code completions, it provides a standardized interface for debuggers.

To begin a debugging session, invoke the ~dape~ command. In the minibuffer prompt, enter a debug adapter configuration name from ~dape-configs~.

For complete functionality, make sure to enable ~eldoc-mode~ in your source buffers and ~repeat-mode~ for more pleasant key mappings.

* Features
+ Batteries included support (~describe-variable~ ~dape-configs~)
+ Log breakpoints
+ Conditional breakpoints
+ Variable explorer
+ Variable watch
+ Variable hover with ~eldoc~
+ REPL
+ gdb-mi.el like interface
+ Memory editor with ~hexl~
+ Disassembly viewer
+ Integration with ~compile~
+ Debug adapter configuration ergonomics
+ No external dependencies outside of core Emacs

With ~(setq dape-buffer-window-arrangement 'right)~:
[[https://raw.githubusercontent.com/svaante/dape/resources/right_0_25_0.png]]
And with ~(setq dape-buffer-window-arrangement 'gud)~ + =corfu= as ~completion-in-region-function~:
[[https://raw.githubusercontent.com/svaante/dape/resources/gud_0_25_0.png]]
With "rich" REPL output:
[[https://raw.githubusercontent.com/svaante/dape/resources/repl_0_25_0.png]]
With =minibuffer= adapter configuration hints:
[[https://raw.githubusercontent.com/svaante/dape/resources/minibuffer_0_25_0.png]]

* Configuration
=Dape= includes pre-defined debug adapter configurations for various programming languages. Refer to ~dape-configs~ for more details. If =dape= doesn't include a configuration suitable for your needs, you can implement your own.

#+begin_src emacs-lisp
  (use-package dape
    :preface
    ;; By default dape shares the same keybinding prefix as `gud'
    ;; If you do not want to use any prefix, set it to nil.
    ;; (setq dape-key-prefix "\C-x\C-a")

    :hook
    ;; Save breakpoints on quit
    ;; (kill-emacs . dape-breakpoint-save)
    ;; Load breakpoints on startup
    ;; (after-init . dape-breakpoint-load)

    :custom
    ;; Turn on global bindings for setting breakpoints with mouse
    ;; (dape-breakpoint-global-mode +1)

    ;; Info buffers to the right
    ;; (dape-buffer-window-arrangement 'right)
    ;; Info buffers like gud (gdb-mi)
    ;; (dape-buffer-window-arrangement 'gud)
    ;; (dape-info-hide-mode-line nil)

    ;; Projectile users
    ;; (dape-cwd-function #'projectile-project-root)

    :config
    ;; Pulse source line (performance hit)
    ;; (add-hook 'dape-display-source-hook #'pulse-momentary-highlight-one-line)

    ;; Save buffers on startup, useful for interpreted languages
    ;; (add-hook 'dape-start-hook (lambda () (save-some-buffers t t)))

    ;; Kill compile buffer on build success
    ;; (add-hook 'dape-compile-hook #'kill-buffer)
    )

  ;; For a more ergonomic Emacs and `dape' experience
  (use-package repeat
    :custom
    (repeat-mode +1))

  ;; Left and right side windows occupy full frame height
  (use-package emacs
    :custom
    (window-sides-vertical t))
#+end_src

* Differences with dap-mode
Dape has no dependencies outside of core Emacs packages, and tries to use get as much out of them possible.

Dape takes a slightly different approach to configuration.
+ =Dape= does not support ~launch.json~ files, if per project configuration is needed use ~dir-locals~ and ~dape-command~.
+ =Dape= enhances ergonomics within the minibuffer by allowing users to modify or add PLIST entries to an existing configuration using options. For example ~dape-config :cwd default-directory :program "/home/user/b.out" compile "gcc -g -o b.out main.c"~.
+ No magic, no special variables like =${workspaceFolder}=. Instead, functions and variables are resolved before starting a new session.
+ Tries to envision how debug adapter configurations would be implemented in Emacs if vscode never existed.

* Supported debug adapters
In theory all debug adapters should be compatible with =Dape=.

** Javascript - vscode-js-*
1. Install =node=
2. Visit https://github.com/microsoft/vscode-js-debug/releases/ and download the asset =js-debug-dap-<version>.tar.gz=
3. Unpack ~mkdir -p ~/.emacs.d/debug-adapters && tar -xvzf js-debug-dap-<version>.tar.gz -C ~/.emacs.d/debug-adapters~

For more information see [[https://github.com/microsoft/vscode-js-debug/blob/main/OPTIONS.md][OPTIONS.md]].

** Go - dlv
See [[https://github.com/go-delve/delve/tree/master/Documentation/installation][delve installation]].
For more information see [[https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv_dap.md][documentation]].

** C, C++, Rust, and more - GDB
Ensure that your GDB version is 14.1 or newer.
For further details, consult the [[https://sourceware.org/gdb/current/onlinedocs/gdb.html/Debugger-Adapter-Protocol.html][documentation]].

** C, C++ and Rust - codelldb
1. Download latest =vsix= [[https://github.com/vadimcn/codelldb/releases][release]] for your platform =codelldb-<platform>-<os>.vsix=
2. Unpack ~mkdir -p ~/.emacs.d/debug-adapters && unzip codelldb-<platform>-<os>.vsix -d ~/.emacs.d/debug-adapters/codelldb~

See [[https://github.com/vadimcn/codelldb/blob/v1.10.0/MANUAL.md][manual]] for more information.

** C and C++ - cpptools
Download latesnd unpack =vsix= file with your favorite unzipper.

1. Download latest =vsix= [[https://github.com/microsoft/vscode-cpptools/releases][release]] for your platform =cpptools-<platform>-<os>.vsix=
2. Unpack ~mkdir -p ~/.emacs.d/debug-adapters && unzip cpptools-<os>-<platform>.vsix -d ~/.emacs.d/debug-adapters/cpptools~
3. Then ~chmod +x ~/.emacs.d/debug-adapters/cpptools/extension/debugAdapters/bin/OpenDebugAD7~
4. And ~chmod +x ~/.emacs.d/debug-adapters/cpptools/extension/debugAdapters/lldb-mi/bin/lldb-mi~

See [[https://code.visualstudio.com/docs/cpp/launch-json-reference][options]].

** C, C++ and Rust - lldb-dap
1. Install [[https://github.com/helix-editor/helix/wiki/Debugger-Configurations#install-debuggers][lldb-dap]] for your platform

*** Example for MacOS using homebrew

1. Install the =llvm= keg: =brew install llvm=
2. Prepend the =llvm= path to the =PATH= variable (=$(brew --prefix --installed llvm)/bin=)
3. =M-x dape= and pass in arguments of interest
  - To pass arguments, use =:args ["arg1" "arg2" ..]=
  - To pass environment variables, use =:env ["RUST_LOG=WARN" "FOO=BAR"]=
  - To use a different program instead of =a.out= (e.g., for Rust), use =:program "target/debug/<crate_name>"=

** Python - debugpy
Install debugpy with pip ~pip install debugpy~

See [[https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings][options]].

** Godot
Configure debug adapter port under "Editor" > "Editor Settings" > "Debug Adapter".

** Dart - flutter
See for installation https://docs.flutter.dev/get-started/install

** C# - netcoredbg
See https://github.com/Samsung/netcoredbg for installation

** Ruby - rdbg
Install with ~gem install debug~.

See https://github.com/ruby/debug for more information

** Java - JDTLS with Java Debug Server plugin
See https://github.com/eclipse-jdtls/eclipse.jdt.ls for installation of JDTLS.
See https://github.com/microsoft/java-debug for installation of the Java Debug Server plugin.
The Java config depends on Eglot running JDTLS with the plugin prior to starting Dape.
Either globally extend ~eglot-server-programs~ as follows to have JDTLS always load the plugin:
#+begin_src emacs-lisp
  (add-to-list 'eglot-server-programs
               '((java-mode java-ts-mode) .
                 ("jdtls"
                  :initializationOptions
                  (:bundles ["/PATH/TO/java-debug/com.microsoft.java.debug.plugin/target/com.microsoft.java.debug.plugin-VERSION.jar"]))))
#+end_src

Alternatively, set the variable ~eglot-workspace-configuration~ in the file =.dir-locals.el= in a project's root directory, to have JDTLS load the plugin for that project:
#+begin_src emacs-lisp
;; content of /project/.dir-locals.el
((nil . ((eglot-workspace-configuration
          . (:jdtls (:initializationOptions
                     (:bundles ["/PATH/TO/java-debug/com.microsoft.java.debug.plugin/target/com.microsoft.java.debug.plugin-VERSION.jar"])))))))
#+end_src

** PHP - Xdebug
1. Install and setup =Xdebug= see [[https://github.com/xdebug/vscode-php-debug][instructions]]
2. Install =node=
3. Download latest =vsix= [[https://github.com/xdebug/vscode-php-debug/releases][release]] of DAP adapter for =Xdebug= =php-debug-<version>.vsix=
4. Unpack ~mkdir -p ~/.emacs.d/debug-adapters && unzip php-debug-<version>.vsix -d ~/.emacs.d/debug-adapters/php-debug~

** OCaml - ocamlearlybird
Install with ~opam install earlybird~.
1. Point =:program= to bytecode file
2. Place breakpoints inside of =_build/default/*=

See [[https://github.com/hackwaly/ocamlearlybird][ocamlearlybird]] for more information.

** Bash - bash-debug
1. Install =node=
2. Download latest =vsix= [[https://github.com/rogalmic/vscode-bash-debug/releases][release]] of DAP adapter =bash-debug-<version>.vsix=
3. Unpack ~mkdir -p ~/.emacs.d/debug-adapters && unzip bash-debug-<version>.vsix -d ~/.emacs.d/debug-adapters/bash-debug~

See [[https://github.com/rogalmic/vscode-bash-debug][bash-debug]] for more information.

** Other untested adapters
If you find a working configuration for any other debug adapter please submit a PR.

See [[https://microsoft.github.io/debug-adapter-protocol/implementors/adapters/][microsofts list]] for other adapters, your mileage will vary.

* Contribute
=dape= is subject to the same copyright assignment policy as GNU Emacs.

Any legally [[https://www.gnu.org/prep/maintain/html_node/Legally-Significant.html#Legally-Significant][significant]] contributions can only be merged after the author has completed their paperwork.
See [[https://www.fsf.org/licensing/contributor-faq][Contributor's Frequently Asked Questions (FAQ)]] for more information.

* Performance

Some minor gains to performance in the debugger can be achieved in changing Emacs configuration values for process interaction and garbage collection.

** =gc-cons-threshold=

This variable controls the frequency of garbage collection in Emacs.
Too high a value will lead to increased system memory pressure and longer stalls, and too low a value will result in extra interruptions and context switches (poor performance).

According to [[https://www.reddit.com/r/emacs/comments/brc05y/comment/eofulix/][GNU Emacs Maintainer Eli Zaretskii]]:

: My suggestion is to repeatedly multiply gc-cons-threshold by 2 until you stop seeing significant improvements in
: responsiveness, and in any case not to increase by a factor larger than 100 or somesuch. If even a 100-fold increase
: doesn't help, there's some deeper problem with the Lisp code which produces so much garbage, or maybe GC is not the
: reason for slowdown.

Abiding the upper end of that advice, you can try to set =gc-cons-threshold= to 100x the original value:

#+begin_src elisp
  (setq gc-cons-threshold 80000000) ;; original value * 100
#+end_src

** =read-process-output-max=

The default =read-process-output-max= of 4096 bytes may inhibit performance to some degree, also.

*** Linux

On Linux, you should be able to set it up to about =1mb=.
To check the max value, check the output of:

#+begin_src sh
  cat /proc/sys/fs/pipe-max-size
#+end_src

To set it:

#+begin_src elisp
  (setq read-process-output-max (* 1024 1024)) ;; 1mb
#+end_src

*** Mac OS

For Mac OS, there isn't an easy way to see the operating system pipe-max-size.
It's probably about =64kb=.

#+begin_src elisp
  (setq read-process-output-max (* 64 1024)) ;; 64k
#+end_src

*** Windows

There doesn't seem to be a limit for Windows.
You can try =1mb=.

#+begin_src elisp
  (setq read-process-output-max (* 1024 1024)) ;; 1mb
#+end_src

* Bugs and issues
Before reporting any issues ~(setq dape-debug t)~ and take a look at =*dape-repl*= buffer. Please share your =*dape-repl*= and =*dape-connection events*= in the buffer contents with the bug report.
The =master= branch is used as an development branch and releases on elpa should be more stable so in the mean time use elpa if the bug is a breaking you workflow.

* Acknowledgements
Big thanks to João Távora for the input and jsonrpc; the project wouldn't be where it is without João.