エラー時に行番号を表示


15

emacsが私には理解できないエラーを投げるとします。または、「変数としてのシンボルの値はvoid:モードです」というエラーが表示される場合もありますがmodes、コードにはシンボルが多数出現するため、コンテキストが必要です。Emacsを設定して、Lispコードの行番号を指定して、エラーの原因となっているコードを知ることができますか?

私がやって試してみました(setq stack-trace-on-error '(buffer-read-only))とスタックトレースを取得するための努力の犯したコードを実行しました。スタックトレースもありません。

またedebug-defun、関数を呼び出して、ステップスルーすることも試みました。エラーがスローされるのは、関数から抜け出すまでではありません。

(私は現在、elispの一般的なデバッグスキルを開発しているので、現在直面している特定のエラーの原因にはあまり興味がありません。行番号、sexp、またはスタックトレースを取得する方法についてアドバイスしてください。エラー。)


すでに非試してみましたnil debug-on-errorか?それは役に立ちませんか?
ドリュー

いや。それは何もしないようです。(tエラーを設定してからエラースロー機能の評価に進みます。)
ジャクソン

おそらく何が起こるかは、他のコードがエラーをキャッチし、エラーメッセージを出力するだけです。またdebug-ignored-errors、エラーがリストされていないことも確認してください。debug-on-signalnon- nilに設定し、他のコードがエラーを処理した場合、他のコードが処理する前にエラーを取得できます。
wvxvw

私は現在、同様の状況にあり、この質問を読んでいました。私はスタックトレースオンエラーについて疑問に思っています。この変数はEmacs 25.1には記載されていません。
マティアス

回答:


15

Emacsは含むデバッグ設備の良い量を提供M-x toggle-debug-on-errorM-x toggle-debug-on-quit(送信で使用することができる信号に、デバッグUSR2外部からのEmacsに)debug-on-entry、(関数の)をdebug-on-message、最後に(メッセージの特定の正規表現の一致を見たとき)とdebugの代替としての地位をと機能をインストルメントしますC-u C-M-x

両方ともdebug、興味のあるコードを評価するときにEmacs edebug状態を検査しe、式を入力して入力するのに十分な機能を提供します。

ただし、edebugインスツルメントされた関数内の場所にジャンプして、どこを見るべきかを示す手掛かりを提供しますが(インスツルメントしたものを正確に知っているため、これはちょっと馬鹿げています)、debugこれはまったく行われません。debugバッファを評価するたびに、エラーに関連するポイントの値を出力することを発見した後、小さなハックを実行しました。言い換えれば、バッファでこの情報を使用すると、バックトレースで行番号を取得できます!

(with-eval-after-load 'debug
  (defun debugger-setup-buffer (debugger-args)
    "Initialize the `*Backtrace*' buffer for entry to the debugger.
That buffer should be current already."
    (setq buffer-read-only nil)
    (erase-buffer)
    (set-buffer-multibyte t)        ;Why was it nil ?  -stef
    (setq buffer-undo-list t)
    (let ((standard-output (current-buffer))
          (print-escape-newlines t)
          (print-level 8)
          (print-length 50))
      (backtrace))
    (goto-char (point-min))
    (delete-region (point)
                   (progn
                     (search-forward "\n  debug(")
                     (forward-line (if (eq (car debugger-args) 'debug)
                                       2    ; Remove implement-debug-on-entry frame.
                                     1))
                     (point)))
    (insert "Debugger entered")
    ;; lambda is for debug-on-call when a function call is next.
    ;; debug is for debug-on-entry function called.
    (pcase (car debugger-args)
      ((or `lambda `debug)
       (insert "--entering a function:\n"))
      ;; Exiting a function.
      (`exit
       (insert "--returning value: ")
       (setq debugger-value (nth 1 debugger-args))
       (prin1 debugger-value (current-buffer))
       (insert ?\n)
       (delete-char 1)
       (insert ? )
       (beginning-of-line))
      ;; Debugger entered for an error.
      (`error
       (insert "--Lisp error: ")
       (prin1 (nth 1 debugger-args) (current-buffer))
       (insert ?\n))
      ;; debug-on-call, when the next thing is an eval.
      (`t
       (insert "--beginning evaluation of function call form:\n"))
      ;; User calls debug directly.
      (_
       (insert ": ")
       (prin1 (if (eq (car debugger-args) 'nil)
                  (cdr debugger-args) debugger-args)
              (current-buffer))
       (insert ?\n)))
    ;; After any frame that uses eval-buffer,
    ;; insert a line that states the buffer position it's reading at.
    (save-excursion
      (let ((tem eval-buffer-list))
        (while (and tem
                    (re-search-forward "^  eval-\\(buffer\\|region\\)(" nil t))
          (beginning-of-line)
          (insert (format "Error at line %d in %s: "
                          (with-current-buffer (car tem)
                            (line-number-at-pos (point)))
                          (with-current-buffer (car tem)
                            (buffer-name))))
          (pop tem))))
    (debugger-make-xrefs)))

これにより、タイトルの元の質問に回答する必要があります。そもそもバックトレースを取得する際の問題については、私は有用なアイデアがありません。


あなたの助けをありがとう、しかし私はまだ行番号を取得する方法を理解していません。M-x debug...?それから私は何を押しますか?
ジャクソン

このコードを使用すると、によって行われたバックトレースの行番号が表示されますdebug、あなたは、障害のあるのelispファイルを訪問することにより確認することができますM-x toggle-debug-on-errorM-x eval-buffer、その後、問題のある位置の行番号のバックトレースがポップアップする必要があります。
wasamasa

使用しない場合、これは機能しますeval-bufferか?たとえば、プライベートコマンドを実行するキーボードショートカットを押すだけで失敗し、デバッガーが*Backtrace*バッファーで開かれた場合。
HåkonHægland15年

いいえ、できません。シンボルの関数値(リストまたはバイトコンパイルされたもののいずれか)を取得しますが、これでほぼ完了です。
-wasamasa

4

たぶん2018年だからかもしれませんが、私の場合は、wasamasaが示唆したようにデバッグをオンにするだけでした:Mx toggle-debug-on-error

この後、エラーのあるElispファイルのMx eval-bufferは、次のようにエラーの位置を提供することでコンテキストを提供しました。 Debugger entered--Lisp error: (invalid-read-syntax ")") eval-buffer() ; Reading at buffer position 523 [....]

Mx goto-charはエラー位置にジャンプします。 M-x goto-char 523


素敵な発見!これは2017年にバックトレース項目のリストで機能するようにその機能を作り直したときに追加されたようです。
wasamasa

1

追加情報を含めるためにwasamasaの回答を拡張しました。

(save-excursion
  (let ((tem eval-buffer-list))
    (while (and tem
                (re-search-forward "^  eval-\\(buffer\\|region\\)(" nil t))
      (beginning-of-line)
      (insert (apply 'format "Error at line %d, column %d (point %d) in %s\n"
                     (with-current-buffer (car tem)
                       (list (line-number-at-pos (point))
                             (current-column)
                             (point)
                             (buffer-name)))))
      (pop tem))))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.