Skip to content
jixiuf edited this page Mar 28, 2024 · 40 revisions

You will find documentation and adapter installation details in the README.org.

dape-dwim

(defun dape-dwim()
  "Call `dape' with default config if dape session not exists,
call `dape-quit' if dape session exists"
  (interactive)
  (require 'dape)
  (if (or (dape--live-connection 'parent t)
          (get-buffer-window "*dape-repl*" t))
      (progn
        (call-interactively #'dape-quit)
        (message "dape quit now!"))
    (if current-prefix-arg
        (call-interactively #'dape)
      (let ((cfg (cl-loop for (key . config) in dape-configs
                          when (and (dape--config-mode-p config)
                                    (dape--config-ensure config))
                          collect (dape--config-eval key config))))
        (when cfg (dape (car cfg)))))))

Debug Configurations

On this page you will find useful dape configurations.

Feel free to add useful configurations!

Ruby - rdbg

Remote attach via docker-compose

NB: Once you have the configuration implemented as defined below, you can trigger dape from within the container within the context of a TRAMP connection. Use C-x C-f /docker:<container_name>:/path/to/project to enter the container, then run M-x dape.

Rails Server (with Puma)

Ensure your target ruby service is setup like so in your docker-compose.yml:

rails-app:
 image: rails-app:latest
 command: rdbg --port 5678 -c -- rails server -b 0.0.0.0
 environment:
   - RUBY_DEBUG_OPEN=true
   - RUBY_DEBUG_HOST=0.0.0.0
   # Allows rails to initialise, only stopping when a breakpoint is hit
   - RUBY_DEBUG_NONSTOP=true
   # Needed to stop puma making workers which all attempt to open rdbg 
   # on the same port
   - WEB_CONCURRENCY=0 
 ports:
   - "5678:5678" # For remote debugging RAILS with debug.rb

Use the following dape-config to attach to the process:

(add-to-list 'dape-configs
             `(rdbg-attach-local-source
               prefix-local "~/code/ruby-app/"
               prefix-remote "/usr/app/"
               port 5678
               :request "attach"
               :localfs t))

RSpec (with rspec-mode)

In order to setup rspec-mode correctly, it is necessary to run rdbg on a different port to the rails server instance. By using a custom wrapper function, we can add in the necessary environment variables, and spin up a fresh instance for the Rspec run:

(defun jjh/rspec--compose-default-wrapper (_compose compose-service command)
  "Function for wrapping a command for execution inside a compose
environment. By adding the port manually here, we keep it out of the
rails service - keeping it free for just rspec. We also name it so
it's easy to find."
  (format "docker-compose -f %s run -it --rm --name ruby-app-rspec -e 'RUBY_DEBUG_PORT=5680' -p 5680:5680 %s sh -c \"%s\""
          rspec-docker-file-name compose-service command))

(setq rspec-docker-wrapper-fn #'jjh/rspec--compose-default-wrapper)

It’s important to set the debug gem to require: false so we can control when the port is opened. Update the Gemfile:

gem "debug", require: false

In the spec_helper.rb, require the debug gem:

# For debugging
require "debug/open_nonstop"

You can then trigger the rspec tests with a custom dape-config entry:

(add-to-list 'dape-configs
             `(rdbg-attach-rspec
               prefix-local "~/code/app/"
               prefix-remote "/usr/app/"
               port 5680
               :request "attach"
               :localfs t))

Python - debugpy

Remote attach

Make sure that remote application imports and starts debugpy.

import debugpy
# Port does not matter just needs to match port in config
# dape debugpy-remote-attach
debugpy.listen(("0.0.0.0", 5678))
(add-to-list 'dape-configs
 `(debugpy-remote-attach
   modes (python-mode python-ts-mode)
   host (lambda () (read-string "Host: " "localhost"))
   port (lambda () (read-number "Port: "))
   :request "attach"
   :type "python"
   :pathMappings [(:localRoot (lambda ()
                                (read-directory-name "Local source directory: "
                                                     (funcall dape-cwd-fn)))
                   :remoteRoot (lambda ()
                                 (read-string "Remote source directory: ")))]
   :justMyCode nil
   :showReturnValue t))

Thanks to @Gavinok for contributing.

Go - dlv

Unit test at point

(add-to-list 'dape-configs
             `(delve-unit-test
               modes (go-mode go-ts-mode)
               ensure dape-ensure-command
               fn dape-config-autoport
               command "dlv"
               command-args ("dap" "--listen" "127.0.0.1::autoport")
               command-cwd dape-cwd-fn
               port :autoport
               :type "debug"
               :request "launch"
               :mode (lambda () (if (string-suffix-p "_test.go"   (buffer-name)) "test" "debug"))
               :cwd dape-cwd-fn
               :program (lambda () (if (string-suffix-p "_test.go"   (buffer-name))
                                       (concat "./" (file-relative-name default-directory (funcall dape-cwd-fn)))
                                     (funcall dape-cwd-fn)))
               :args (lambda ()
                       (require 'which-func)
                       (if (string-suffix-p "_test.go"   (buffer-name))
                           (when-let* ((test-name (which-function))
                                       (test-regexp (concat "^" test-name "$")))
                             (if test-name `["-test.run" ,test-regexp]
                               (error "No test selected")))
                         []))))

The point can be anywhere in function TestDemo, then call dape and “Run adapter: delve-unit-test” it will execute go test -test.run TestDemo.

func TestDemo(t *testing.T) {
   t.Error("hello")
}

Thanks to @jixiuf for contributing.

Swift IOS

Setup

Follow the steps in the README.org on how to install codelldb in section “C, C++ and Rust - codelldb”

Add the following configuration to your init.el:

(add-to-list 'dape-configs
             `(ios
               modes (swift-mode)
               command-cwd dape-command-cwd
               command ,(file-name-concat dape-adapter-dir
                                          "codelldb"
                                          "extension"
                                          "adapter"
                                          "codelldb")
               command-args ("--port" :autoport
                             "--settings" "{\"sourceLanguages\":[\"swift\"]}"
                             "--liblldb" "/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/LLDB")
               port :autoport
               simulator-id "iPhone 15 Pro"
               app-bundle-id "com.yourcompany.ProductName"
               fn (dape-config-autoport
                   ,(lambda (config)
                      (with-temp-buffer
                        (let* ((command
                                (format "xcrun simctl launch --wait-for-debugger --terminate-running-process %S %S"
                                        (plist-get config 'simulator-id)
                                        (plist-get config 'app-bundle-id)))
                               (code (call-process-shell-command command nil (current-buffer))))
                          (dape--repl-message (format "* Running: %S *" command))
                          (dape--repl-message (buffer-string))
                          (save-match-data
                            (if (and (zerop code)
                                     (progn (goto-char (point-min))
                                            (search-forward-regexp "[[:digit:]]+" nil t)))
                                (plist-put config :pid (string-to-number (match-string 0)))
                              (dape--repl-message (format "* Running: %S *" command))
                              (dape--repl-message (format "Failed to start simulator:\n%s" (buffer-string)))
                              (user-error "Failed to start simulator")))))
                      config))
               :type "lldb"
               :request "attach"
               :cwd "."))

Debug

Start simulator:

open -n "Simulator"

Compile program, see xcodebuild (could use compile flag in dape)

Debug Jest unit test

(contributed by @timcharper)

The following configuration can be used to run an entire file of jest tests (works as of dape 0.5.0).

(defun dape-jest/find-file-buffer-default ()
  "Read filename at project root, defaulting to current buffer. Return vector of jest args to run said file"
  (let ((file (dape-buffer-default)))
    (if file
        `["--runInBand" "--no-coverage" ,file]
      (user-error "No file found"))))

(defun dape-jest/ensure (config)
  "Ensure node is available, jest is installed, that the dapDebugServer is installed"

  (dape-ensure-command config)
  (let ((cwd (dape-cwd))
        (js-debug-file (expand-file-name
                        (dape--config-eval-value (car (plist-get config 'command-args)))
                        (dape--config-eval-value (plist-get config 'command-cwd))))
        (node-jest-file (expand-file-name
                        (dape--config-eval-value (plist-get config :program))
                        (dape--config-eval-value (plist-get config :cwd)))))
    (unless (file-exists-p js-debug-file)
      (user-error "Debug server file %S does not exist" js-debug-file))
    (unless (file-exists-p node-jest-file)
      (user-error "Jest executable not found at %S" node-jest-file))))


(add-to-list 'dape-configs
             `(jest
               modes (js-mode js-ts-mode typescript-mode)
               ensure dape-jest/ensure
               command "node"
               command-cwd dape-command-cwd
               command-args (,(expand-file-name
                               (file-name-concat dape-adapter-dir
                                                 "js-debug"
                                                 "src"
                                                 "dapDebugServer.js"))
                             :autoport)
               port :autoport
               fn dape-config-autoport
               :type "pwa-node"
               :cwd dape-cwd
               :env (:VAR1 "some value" :VAR2 "another value")
               :program "node_modules/.bin/jest"
               :args dape-jest/find-file-buffer-default
               :outputCapture "console"
               :sourceMapRenames t
               :pauseForSourceMap nil
               :autoAttachChildProcesses t
               :console "internalConsole"
               :outputCapture "std"
               :killBehavior "forceful"))

Embedded jlink debugging with cortex-debug

https://github.com/svaante/dape-cortex-debug

Clone this wiki locally