this post was submitted on 20 Oct 2023
1 points (100.0% liked)

Emacs

305 readers
1 users here now

A community for the timeless and infinitely powerful editor. Want to see what Emacs is capable of?!

Get Emacs

Rules

  1. Posts should be emacs related
  2. Be kind please
  3. Yes, we already know: Google results for "emacs" and "vi" link to each other. We good.

Emacs Resources

Emacs Tutorials

Useful Emacs configuration files and distributions

Quick pain-saver tip

founded 1 year ago
MODERATORS
 

https://github.com/svaante/dape#

Given that eglot has been part of the core emacs, I believe this is a long lasting wish for a lot of emacsers that has finally been fulfilled. (a stand alone DAP implementation that does not rely on LSP-mode)

top 28 comments
sorted by: hot top controversial new old
[–] [email protected] 1 points 11 months ago (1 children)

I saw this on the mailing list, and it looks very promising. It's always nice to have more choice in this space. I did also play around with it quite a bit and I do have some feedback to the author (and anybody who would want to play around with it):

Expect to debug the dape debugger. I wanted to check it out with a bespoke software project I'm building for a client and I figured this would be a fine way to test it. I've never played around with DAP and friends before (ipdb is fine for me, thanks) so it was a bit of a learning curve as the documentation is sparse, even moreso the magic flags and parameters you need to paw off to dape and -- down the road -- the actual DAP client/server. This... this is bad and needs a lot more handholding. I struggled, and I've done Python and Emacs for two decades. And I simply could not, no matter what I did, get the microsoft adapter and dape.el to play nice with the client-server attachment facility in the dape protocol, and dape.el didn't help me much here in terms of why


nor, for that matter, did the Microsoft-provided DAP debug adapter you use. Error handling in the DAP client/server seems poor or not designed, surprise surprise, for anything but VSCode or whatever.

I could, after a fair bit of wrangling, get it to work by starting the process for me and then have it hook into whatever it needs to do to work. That does seem to work. I never did get attachment to work, rendering it useless in a webapp or even for my usual workflow of throwing down a breakpoint() and having ipdb (or whatever) pick up from there.

Other problems I've encountered is a weird way that it stores configuration options once you've told dape to connect to stuff. The UX around that needs work before it's plug-and-play.

The other criticism is that it does not, and this might be a DAP thing and not a dape thing, work with the default GDB-like shorthands (c for continue, etc.). Maybe that's just how it is; but it's little things like that.

Being able to see all the relevant variables, a la the GDB multi-window support in Emacs, is also nice. Which makes me wonder why we can't just reuse that, as there's surely man-years of work to make that stable and effective.

Still, an impressive effort, and I'm surprised how little code dape actually is. I'm sure it'll improve quickly once people start giving feedback.

[–] [email protected] 1 points 11 months ago (2 children)

Expect to debug the dape debugger

Did you use the debugpy adapter with the following configuration from the readme? (add-to-list 'dape-configs `(debugpy modes (python-ts-mode python-mode) command "python3" command-args ("-m" "debugpy.adapter") :type "executable" :request "launch" :cwd dape-cwd-fn :program dape-find-file-buffer-default))

I have tested this quite often at my day job so I am a bit surprised you bumped into issues. But thats not to say that Dape will contain warts until there is enough feedback and testing. It would be great if you could dump the contents of the dape-debug buffer into an issue on github!

DAP has some issues as well, extremely loose specification, the overwhelming majority is tested with vscode and a lot of cruff is hidden inside in the plugins for vscode. I was close to putting it in the bin at several points.

Other problems I've encountered is a weird way that it stores configuration options once you've told dape to connect to stuff. The UX around that needs work before it's plug-and-play.

Usability feedback is appreciated, the dape command tries to do a lot of stuff, maybe to much.

It models the way one would use a command line tool. For example if we run dape debugpy it executes the configuration above with all of the plist entries as the default command line arguments. If we want to overwrite any "argument" or add an "argument", lets say we wanted to run the python file with some enviroment variable then call dape with debugpy :env (:ENV "MY_ENV").

The other part is actually evaluating all of the symbols and functions in the config and adds the result into history for ease of access.

Being able to see all the relevant variables, a la the GDB multi-window support in Emacs, is also nice. Which makes me wonder why we can't just reuse that, as there's surely man-years of work to make that stable and effective.

I am regretting not looking into this when I started, even though I kinda like having one "big" buffer with all of the information, using the tried and true GUD interface would meld better with one of the goals of package of being closer to emacs. So I am looking into the possibilities.

Still, an impressive effort, and I'm surprised how little code dape actually is. I'm sure it'll improve quickly once people start giving feedback.

Thank you, it would not have been possible for me to get this far without Wireshark. A little reverse engineering is always fun :) And thanks for your feedback!

[–] [email protected] 1 points 11 months ago

I just tried the example configuration (for python) from github and the dap works perfectly fine to me, everything works as expected except the only one thing: post-run cleanup.

I do notice that there are some leak problems: the debugpy process will not exit even when the debug session terminated, keeping high CPU usage even after emacs exits.

It is a tricky problem and not easily reproduce, I will try to dive into this problem more to make it as reproducible as possible.

Besides, the go debugger (delve) works perfectly to me with the example configuration.

[–] [email protected] 1 points 11 months ago

Did you use the debugpy adapter with the following configuration from the readme?

Of course.

DAP has some issues as well, extremely loose specification, the overwhelming majority is tested with vscode and a lot of cruff is hidden inside in the plugins for vscode. I was close to putting it in the bin at several points.

Yes, indeed.

[–] [email protected] 1 points 11 months ago (1 children)

That's a very good idea. We've moved away from god libraries that do everything like Helm or LSP and I'm here for it. I don't have anything against those, they are amazing and useful but any time I wanted to modify a small thing in my config or wanted to try another lib, it just wasn't readily possible and I like having smaller build parts.

[–] [email protected] 1 points 11 months ago

That's not fair regarding LSP imo. It's an excellent LSP client mode.

[–] [email protected] 1 points 11 months ago (1 children)

There goes my Friday productivity 😎 All the languages I care about are already supported too!

While deliberately not supporting launch.json makes sense the configuration looks quite friendly to adding that functionality separately.

Thank you for working on such a desirable and challenging feature for emacs users who don't use lsp mode

[–] [email protected] 1 points 11 months ago

I am not the author of this plugin😂 just want to share this exciting news with Redditers

[–] [email protected] 1 points 11 months ago

There is typo in the read.me

(setq dape--debug-on '(io info error std-server)

It is missing a ")".

[–] [email protected] 1 points 11 months ago

I till have to find time to test it but glanced through it on Monday, it is pretty awesome to have, this plus eglot is all someone needs imo.

[–] [email protected] 1 points 11 months ago

Yes, yes, yes!

(And sorry for the noise)

[–] [email protected] 1 points 11 months ago

I like right at the top vscode-js-debug is a supported adapter. It's been a while since vscode-js-debug has worked in dap-mode.

I am now excited to try dape out to see how well it works.

[–] [email protected] 1 points 11 months ago (1 children)

Author here, if you have any suggestions or bump into any issues please open a ticket. I have some extra free time on my hands a couple of months going forward.

[–] [email protected] 1 points 11 months ago

Very excited to see this package! I have not tried it out yet but I just wanted to say thanks for your work on it!

[–] [email protected] 1 points 11 months ago (2 children)

Tried using dape recently with Go and managed to get it to debug Go tests. Sharing the snippet incase its helpful for others (requires go treesitter).

  (setq treesit-go-tests-query (treesit-query-compile 'go
                                                      '((function_declaration
                                                         name: (identifier) @testname
                                                         parameters: (parameter_list :anchor (parameter_declaration type: (pointer_type) @type :anchor))
                                                         (:match "*testing.\\(T\\|M\\)" @type) (:match "^Test.+$" @testname)) @parent)))
  (defun jake/query-go-test-nodes ()
    (when (treesit-ready-p 'go)
      (treesit-query-capture (treesit-buffer-root-node) treesit-go-tests-query)))

  (defun jake/completing-read-go-tests ()
    (let* ((test-matches (jake/query-go-test-nodes))
           (test-name-matches (cl-remove-if-not (lambda (match) (eq (car match) 'testname)) test-matches))
           (test-names (mapcar (lambda (match) (treesit-node-text (cdr match))) test-name-matches)))
      (completing-read "Test:" test-names nil t)))


  (defun jake/dape--select-go-test-args ()
    (when-let* ((test-name (jake/completing-read-go-tests))
                (test-regexp (concat "^" test-name "$")))
      (if test-name
          `["-test.run" ,test-regexp]
        (error "No test selected"))))

  (defun jake/file-relative-dir ()
    "Return the file directory relative to dape's cwd. This is used by Delve debugger."
    (concat "./" (file-relative-name default-directory (funcall dape-cwd-fn))))

;; inside your dape-config
(add-to-list 'dape-configs
               `(test
                 modes (go-mode go-ts-mode)
                 command "dlv"
                 command-cwd dape-cwd-fn
                 command-args ("dap" "--listen" "127.0.0.1:55878")
                 host "127.0.0.1"
                 port 55878
                 :type "go"
                 :name "debug test"
                 :request "launch"
                 :mode "test"
                 :cwd dape-cwd-fn
                 :program jake/file-relative-dir
                 :args jake/dape--select-go-test-args))
[–] [email protected] 1 points 11 months ago

Compared to gud, it's a lot of config, it's also nasty that it looks like you have to code the program path to your config.

but, it's a great effort in any case, both from you and the plugin author. Configuration snippets like this help a lot of people.

[–] [email protected] 1 points 11 months ago

(defun go-func-name-at-point ()

(interactive)

(save-excursion

(end-of-line)

(beginning-of-defun)

(when (re-search-forward "^func[[:space:]]+\\([[:alnum:]_]+\\)" nil t)

(match-string 1))))

(setq treesit-go-tests-query

(treesit-query-compile

'go

'((function_declaration

name: (identifier) u/testname

parameters: (parameter_list :anchor (parameter_declaration type: (pointer_type) u/type :anchor))

(:match "*testing.\\(T\\|M\\)" u/type) (:match "^Test.+$" u/testname)) u/parent)))

(defun vmacs-query-go-test-nodes ()

(when (treesit-ready-p 'go)

(treesit-query-capture (treesit-buffer-root-node) treesit-go-tests-query)))

(defvar vmacs-go-tests-hist nil)

(defun vmacs-completing-read-go-tests ()

(let* ((test-matches (vmacs-query-go-test-nodes))

(test-name-matches (cl-remove-if-not (lambda (match) (eq (car match) 'testname)) test-matches))

(test-names (mapcar (lambda (match) (treesit-node-text (cdr match))) test-name-matches)))

(completing-read "Test:" test-names nil t nil vmacs-go-tests-hist (go-func-name-at-point))))

(defun vmacs-dape--select-go-args ()

(if (string-suffix-p "_test.go" (buffer-name))

(when-let* ((test-name (vmacs-completing-read-go-tests))

(test-regexp (concat "^" test-name "$")))

(if test-name

`["-test.run" ,test-regexp]

(error "No test selected")))

(if current-prefix-arg

(vconcat (split-string (read-shell-command "args: " nil

(if (equal (car compile-history) "")

'(compile-history . 1)

'compile-history))))

[])))

;; https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv_dap.md

(defun vmacs-dape-test-p ()

(if (string-suffix-p "_test.go" (buffer-name))

"test" "debug"))

(defun vmacs-dape-relative-dir ()

"Return the file directory relative to dape's cwd. This is used by Delve debugger."

(if (string-suffix-p "_test.go" (buffer-name))

(concat "./" (file-relative-name

default-directory (funcall dape-cwd-fn)))

(funcall dape-cwd-fn)))

;; inside your dape-config

(add-to-list 'dape-configs

`(delve

modes (go-mode go-ts-mode)

command "dlv"

command-cwd dape-cwd-fn

command-args ("dap" "--listen" "127.0.0.1:55878")

host "127.0.0.1"

port 55878

:type "go"

:name "go-debug"

:request "launch"

:mode vmacs-dape-test-p

:cwd dape-cwd-fn

:program vmacs-dape-relative-dir

:args vmacs-dape--select-go-args))

[–] [email protected] 1 points 11 months ago (3 children)

How would you attach a DAP python debugger to a running instance of (i)Python? Is there some import debugpy; debugpy.start() command or similar?

[–] [email protected] 1 points 11 months ago (1 children)

There is

In python:

import debugpy
debugpy.listen(5678) # debugpy will open 5678

Then add the following configuration to dape

(add-to-list 'dape-configs
`(debugpy-attach
  modes ()
  host "localhost"
  port ,(lambda () (read-number "Port: "))
  :type "debugpy"
  :request "attach"))

Supposedly there is a way to attach by pid with python3 -m debugpy --listen localhost:5678 --pid 12345, but that failed, both on osx and linux.

[–] [email protected] 1 points 11 months ago (1 children)

Yes, I also tried to use --pid to attach to a python process, and failed too.

[–] [email protected] 1 points 10 months ago

Did you either succeed with debugpy.listen()? Is that suitable to call interactively then quit (like iPDB)?

[–] [email protected] 1 points 11 months ago (1 children)

I believe this is out of the scope of the DAP protocol, I believe even VSCode cannot do it based on my understanding.

If you want to debug a running session, just use ipdb or pdb.

[–] [email protected] 2 points 11 months ago (2 children)

No it isn't. DAP can definitely do this. It can even attach to a PID.

This is what I complained about it in my post: I could not get dape to work with this.

[–] [email protected] 1 points 11 months ago

I see, thanks for correcting me.

I see that this post https://github.com/Microsoft/vscode-python/issues/1078 suggested that debugpy can already attach to a local Python process.

[–] [email protected] 1 points 11 months ago (1 children)

I see, thanks for correcting me.

I see that this post https://github.com/Microsoft/vscode-python/issues/1078 suggested that debugpy can already attach to a local Python process.

[–] [email protected] 1 points 11 months ago

Seems like in-process debuggers like iPDB are far more practical for interactive debugging of long running shells.

[–] [email protected] 1 points 11 months ago

Currently Dape does not come with any debug adapter configuration.

I hope there will be a separated package (maybe maintained by another one) for the templates, or a continuously updated wiki so dape will be easier to use.