Emacs Lisp 디버깅 팁

Emacs Lisp 패키지에서 이상한 오류가 발생한 적이 있습니까? 미니 버퍼에 "잘못된 유형 인수"또는 이와 유사한 것이 있습니까? 언뜻 보기에 이것들은 다소 비밀스러워 보입니다. 그들은 어디에서 왔니? 스택 추적을 얻을 수 있습니까? 함수는 어떤 인수로 호출됩니까? 오늘은 이러한 질문에 답하는 방법을 알려드리겠습니다!

스택 추적 표시



이상한 "잘못된 유형 인수"오류 또는 이전에 미니버퍼에 인쇄된 유사한 오류 중 하나를 받았을 것입니다. 추가 정보가 있는지 확인하기 위해 *Messages* -버퍼로 이동했을 수도 있습니다. 대신 스택 추적을 볼 수 있다는 것을 알고 계셨습니까? 그런 다음 오류로 이어지는 함수가 호출되는 것을 볼 수 있습니다!

활성화하는 방법에는 여러 가지가 있습니다. 가장 일반적인 방법은 오류가 발생했을 때 디버거에 들어가도록 Emacs를 설정하는 것입니다. 변수debug-on-error를 설정하여 이를 수행할 수 있습니다.
true로 변경(구성에서 또는 스크래치 버퍼에서 바로 실행):

  (setq debug-on-error t)


나는 보통 M-x 대신 M-x toggle-debug-on-error 를 사용하여 필요에 따라 켜는 것을 선호합니다.

the lsp-mode codebase 의 함수를 사용하여 간단한 예를 보여드리겠습니다. 숙련된 프로그래머라면 문제를 바로 알아차릴 수 있지만 어떻게 디버깅할지 살펴보겠습니다. result-data 라는 결과를 가져오려는 해시 테이블을 얻었다고 가정하겠습니다. 스크래치 버퍼에서 실행하면 항상 스택 추적이 표시되므로 M-x를 사용하여 호출할 대화형 함수를 만들어 보겠습니다.

  (defun my-lsp-mode-fun ()
    (interactive)
    (let* ((my-key "key")
           (my-data (lsp-get result-data my-key)))
      ;; ... do something with the data ...
      ))


debug-on-error를 켜지 않고 호출하면 미니버퍼와 메시지 버퍼에 오류Wrong type argument: symbolp, "key"가 표시됩니다. 여러분 중 일부는 문자열이 아니라 기호를 기대한다는 것을 이미 알고 있을 것입니다. 오류 시 디버그를 켜고 다시 실행하면 훨씬 더 명확해집니다.

  Debugger entered--Lisp error: (wrong-type-argument symbolp "key")
    symbol-name("key")
    lsp-keyword->string("key")
    lsp-get(#<hash-table equal 0/65 0x47fa6ca9> "key")
    (let* ((my-key "key") (my-data (lsp-get result-data my-key))))
    my-lsp-mode-fun()
    funcall-interactively(my-lsp-mode-fun)
    call-interactively(my-lsp-mode-fun record nil)
    command-execute(my-lsp-mode-fun record)
    helm-M-x-execute-command(my-lsp-mode-fun)
    helm-execute-selection-action-1()
    helm-execute-selection-action()
    helm-internal((((name . "Emacs Commands history") ...truncated....
    helm-M-x(nil)
    funcall-interactively(helm-M-x nil)
    call-interactively(helm-M-x nil nil)
    command-execute(helm-M-x)



(가독성을 높이기 위해 일부 데이터가 잘렸습니다.)

Emacs가 수행하는 모든 작업의 ​​스택 추적을 얻는 것을 볼 수 있습니다. 패키지를 직접 만들지 않더라도 문제를 보고할 때 문제 추적기에 정보를 제공하는 데 매우 유용할 수 있습니다(예: 패키지 Github 저장소).

메시지 패턴에서 신호에 이르기까지 오류를 토글하는 몇 가지 다른 방법이 있습니다. 이에 대한 자세한 내용을 읽을 수 있습니다on the documentation pages.

함수 호출 추적



알아야 할 또 다른 유용한 문제 해결 팁은 함수 호출/호출을 추적하는 것입니다. 때때로 우리는 특정 함수가 호출되는 인수를 확인하고 실행될 때마다 이에 대한 알림을 받기를 원합니다. 이것은 =trace-function= 명령( M-x trace-function , 추적하려는 함수의 이름이 뒤따름)을 사용하여 수행됩니다.

위의 코드 예제를 재사용하고 lsp-get 추적해 봅시다. 대화형 함수를 한 번 호출하면 다음과 같은 데이터가 포함된 *trace-output*라는 버퍼가 표시됩니다.

  ======================================================================
  1 -> (lsp-get #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8125 data ()) "key")
  1 <- lsp-get: !non-local\ exit!



더 많이 호출하면 더 많은 데이터로 버퍼가 채워집니다. 원하는 만큼 많은 기능을 추적할 수 있습니다. 함수 추적을 완료하면 untrace-function를 호출하고 추적을 중지할 함수를 선택할 수 있습니다.

패키지를 개발할 때 이 기능이 매우 유용하다는 것을 알았습니다. 패키지 외부의 함수를 호출할 때(즉, 다른 패키지나 Emacs Lisp에 내장된 함수) 함수가 어떻게 작동하는지 추적할 수 있는 것은 매우 유용합니다. 여기에는 인수가 무엇인지 뿐만 아니라 언제 또는 호출되는지가 포함됩니다.

좋은 웹페이지 즐겨찾기