Zeilennummer bei Fehler anzeigen

15

Angenommen, Emacs wirft einen Fehler auf, den ich nicht verstehe. Oder vielleicht lautet der Fehler "Der Wert des Symbols als Variable ist ungültig: Modi", aber das Symbol kommt modesin meinem Code häufig vor, sodass ich einen gewissen Kontext benötige. Kann Emacs so konfiguriert werden, dass die Zeilennummer des Lisp-Codes angegeben wird, damit ich weiß, welcher Code den Fehler verursacht?

Ich habe es versucht (setq stack-trace-on-error '(buffer-read-only))und den Tätercode ausgeführt, um einen Stack-Trace zu erhalten. Auch kein Stack-Trace.

Ich habe auch versucht, edebug-defunmeine Funktion aufzurufen und durchzugehen. Erst wenn ich die Funktion verlasse, wird der Fehler ausgelöst.

(Ich interessiere mich nicht so sehr für die Ursache des Fehlers, mit dem ich gerade konfrontiert bin, wie für die Entwicklung allgemeiner Debugging - Fähigkeiten für elisp. Bitte geben Sie an, wie ich eine Zeilennummer, ein Sexp oder eine Stack - Ablaufverfolgung von einem erstrahlen lassen kann Error.)

Jackson
quelle
Hast du schon nicht probiert nil debug-on-error? Hilft das nicht?
Drew
Nee. Das scheint nichts zu tun. (Nachdem ich es auf gesetzt habe tund dann fortfahre, eine Fehlerwurffunktion zu evaluieren.)
Jackson,
Wahrscheinlich wird der Fehler von einem anderen Code abgefangen und nur die Fehlermeldung ausgegeben. Überprüfen Sie auch, dass debug-ignored-errorskeine Fehler aufgelistet sind. Wenn Sie debug-on-signalauf non- setzen nilund der andere Code den Fehler behandelt hat, können Sie den Fehler vor dem anderen Code abrufen.
wvxvw
Ich bin derzeit in einer ähnlichen Situation und habe diese Frage gelesen. Ich frage mich über Stack-Trace-on-Error. Diese Variable ist in Emacs 25.1 nicht dokumentiert.
Matthias

Antworten:

15

Emacs bietet eine gute Menge an Debug - Einrichtungen , einschließlich M-x toggle-debug-on-error, M-x toggle-debug-on-quitDebug auf Signal (das durch das Senden verwendet werden kann , USR2von außen nach Emacs), debug-on-entry(einer Funktion), debug-on-messageund schließlich (wenn eine bestimmte regexp Übereinstimmung einer Nachricht zu sehen), debugsich als Alternative zur Instrumentierung einer Funktion mit C-u C-M-x.

Beide debugund edebugbieten genügend Funktionen, um den Status von Emacs zu überprüfen, wenn Sie den Code, an dem Sie interessiert sind, auswerten, edrücken und einen Ausdruck eingeben.

Während jedoch die edebugSprünge an den Ort in der instrumentierten Funktion und damit Ihnen einen Anhaltspunkt gibt , wo man suchen (die Art von dumm ist , da Sie bereits wissen , was genau haben Sie instrumentiert), debugtun dies nicht überhaupt. Ich habe einen kleineren Hack ausgeführt, nachdem ich festgestellt habe, dass immer dann, wenn debugein Puffer ausgewertet wird, der Wert des mit dem Fehler verbundenen Punkts ausgegeben wird. Mit anderen Worten, wenn Sie diese Informationen im Puffer verwenden, erhalten Sie eine Zeilennummer in der Rückverfolgung!

(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)))

Damit soll die ursprüngliche Frage im Titel beantwortet werden. Was das Problem betrifft, überhaupt einen Backtrace zu bekommen, habe ich keine nützlichen Ideen mehr.

Wasamasa
quelle
Vielen Dank für Ihre Hilfe, aber ich verstehe immer noch nicht, wie ich die Zeilennummer bekomme. M-x debug...? Was drücke ich dann?
Jackson
Mit diesem Code werden Sie eine Zeilennummer in Backtraces sehen, die durch debugSie durch den Besuch eine fehlerhafte elisp Datei überprüfen können, tun M-x toggle-debug-on-errorund M-x eval-bufferdann ein Backtrace mit einer Zeilennummer an der problematischen Position sollte erscheinen.
Wasamasa
Funktioniert das, wenn Sie es nicht benutzen eval-buffer? Zum Beispiel, wenn Sie nur eine Tastenkombination drücken, die einen privaten Befehl *Backtrace*
ausführt
Nein, das wird es nicht. Sie erhalten den Funktionswert des Symbols (das entweder eine Liste oder etwas Byte-kompiliertes sein kann) und das wars auch schon.
Wasamasa
4

Vielleicht, weil es jetzt 2018 ist, aber in meinem Fall musste ich nur das Debuggen einschalten, wie von Wasamasa vorgeschlagen: Mx toggle-debug-on-error

Danach gab Mx eval-buffer in meiner fehlerhaften Elisp-Datei den Kontext an, indem er die Position des Fehlers wie folgt angab: Debugger entered--Lisp error: (invalid-read-syntax ")") eval-buffer() ; Reading at buffer position 523 [....]

Mx goto-char springt zur Fehlerposition: M-x goto-char 523

mistige
quelle
Nizza zu finden! Es scheint, dass dies im Jahr 2017 hinzugefügt wurde, als diese Funktion überarbeitet wurde, um an einer Liste von Rückverfolgungselementen zu arbeiten.
Wasamasa
1

Ich habe die Antwort von wasamasa um zusätzliche Informationen erweitert:

(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))))
Jackson
quelle