Emacs dap-mode debug with eglot-mode

[Richard Jo]

2023/09/24

dap-mode debug with eglot-mode

최근에 회사에서 typescript로 block-listener 어플리케이션을 debugging을 해야할 일이 생겼다. emacs예서 debugging 자주 사용하는 플러그인 dap-mode를 주로 사용한다.

https://github.com/emacs-lsp/dap-mode

MS에서 debug-server와 debug-client (ex: vscode, vim, emacs, sublime…)들이 표준화된 방식으로 통신할 수 있는 방식으로 DAP(Debug Adapter Protocol)을 만들었다.

당연히 MS에서 만든 vscode에서는 이 DAP을 사용한다.

emacs내에서도 독립적으로 DAP을 사용하는 mode가 존재했으면 좋겠지만 불행히도 그렇지는 못한것 같다.

dap-mode란 플러그인이 존재하는데, dap-client의 모든 기능을 emacs-lisp으로 다 구현한 것이 아닌

vscode의 DAP 확장 플러그인을 호출하는 방식 같았다.

그렇기 때문에 dap-mode를 설정시 아래와 같이 .emacs.d 내부에 vscode 플러그인이 설치된 디렉토리가 존재하게 된다.

$ pwd
/Users/jongyoungcha/.emacs.d/.extension/vscode

언제나 처럼 typescipt를 디버깅하려 template를 만들고 dap-debug를 수행하는데

(dap-register-debug-template "typescript-debugging-launch"
                             (list :type "node"
                                   :request "launch"
                                   :program "${workspaceFolder}/src/main.ts"
                                   :outFiles ["${workspaceFolder}/dist/*.js"]
                                   :name "typescript-debugging-launch"))

이제 main.ts에서 dap-debug 수행 후 typescript-debugging-launch를 수행하는데 실패가 떨어진다.

Messages 버퍼를 보니 왜 실패했는지 상세한 정보를 열람 할 수 있었다.

Received:
{
  "seq": 5,
  "type": "response",
  "request_seq": 2,
  "command": "launch",
  "success": null,
  "message": "Attribute 'program' does not exist ('{path}').",
  "body": {
    "error": {
      "id": 2007,
      "format": "Attribute 'program' does not exist ('{path}').",
      "variables": {
        "path": "/src/main.ts"
      }
    }
  }
}
Debug session process exited with status: killed: 9

body.variables.path를 보니 ${workspaceFolder}값을 인식하지 못하고 있는것 같다.

해당 플러그인의 repository관리자는 현재 lsp-mode와 함께 dap-mode를 관리하고 있다.

emacs raddit에서 dap-mode 는 lsp-mode와 intergated 해서 동작한다는 정보를 본적이 있다.

그리고 최근에 나는 lsp 기능을 emacs built-in mode인 eglot 모드로 변경했다.

혹시나 해서 lsp 모드를 활성화 한수 다시 수행해 보았는데 잘된다…

그렇다면 단지 dap-mode template에서 ${workspaceFolder}와 같은 reserved variable을 사용하기 위해서

lsp-mode와 eglot을 같이 홣성화 하기에는 리소스 소모가 너무 크다…

어쩔 수 없이 ${workspaceFolder} 부분을 제거한 하드 코딩된 템플릿을 만든다.

(dap-register-debug-template "typescript-debugging-hard"
                             (list :type "node"
                                   :request "launch"
                                   :program "/Users/jongyoungcha/work/mdl-explorer-block-event-listener/src/main.ts"
                                   :outFiles ["/Users/jongyoungcha/work/mdl-explorer-block-event-listener/dist/*.js"]
                                   :name "typescript-debugging-hard"))

dap-mode를 자주 사용할 경우 eglot이 아닌 lsp-mode와 함께 사용하길 권한다.

같은 committer가 관리 하기 때문에 같이 연동되어 동작한다.

아니면 위에처럼 ${workspaceFolder}와 같은 변수가 없는 dap-mode template를 만들어야 한다.