Afficher le numéro de ligne en cas d'erreur


15

Disons qu'emacs génère une erreur que je ne comprends pas. Ou peut-être que l'erreur indique "La valeur du symbole en tant que variable est vide: modes", mais il y a beaucoup d'occurrences du symbole modesdans mon code, j'ai donc besoin d'un peu de contexte. Emacs peut-il être configuré pour mentionner le numéro de ligne du code lisp afin que je puisse savoir quel code est à l'origine de l'erreur?

J'ai essayé de le faire (setq stack-trace-on-error '(buffer-read-only))et j'ai exécuté le code en question dans le but d'obtenir une trace de pile. Pas de trace de pile non plus.

J'ai également essayé d'appeler edebug-defunma fonction et de la franchir. Ce n'est que lorsque je quitte la fonction que l'erreur est levée.

(Je ne suis vraiment pas aussi intéressé par la cause de l'erreur particulière que je rencontre actuellement que par le développement de compétences générales de débogage pour elisp. Veuillez me conseiller sur la façon dont je peux faire briller un numéro de ligne, ou un sexp, ou une trace de pile à partir d'un Erreur.)


Avez-vous déjà essayé non nil debug-on-error? Cela ne vous aide-t-il pas?
Drew

Nan. Cela ne semble rien faire. (Après l'avoir réglé sur t, puis procéder à l'évaluation d'une fonction de lancement d'erreur.)
Jackson

Ce qui se passe probablement, c'est qu'un autre code intercepte l'erreur et imprime simplement le message d'erreur. Vérifiez également que la debug-ignored-errorsliste ne contient aucune erreur. Si vous définissez debug-on-signalsur non nil, et que c'était le cas que l'autre code a traité l'erreur, vous pourrez obtenir l'erreur avant que l'autre code ne le fasse.
wvxvw

Je suis actuellement dans une situation similaire et lisais cette question. Je me pose des questions sur stack-trace-on-error. Cette variable n'est pas documentée dans Emacs 25.1.
Matthias

Réponses:


15

Emacs fournit une bonne quantité de fonctionnalités de débogage, y compris M-x toggle-debug-on-error, le M-x toggle-debug-on-quitdébogage sur le signal (qui peut être utilisé en envoyant USR2à Emacs de l'extérieur), debug-on-entry(d'une fonction), debug-on-message(en voyant une correspondance d'expression rationnelle spécifique d'un message) et enfin, debuglui - même comme alternative l'instrumentation d'une fonction avec C-u C-M-x.

Les deux debuget edebugoffrent des fonctionnalités suffisantes pour inspecter l' état d'Emacs pour évaluer le code qui vous intéresse, frappé eet entrez une expression.

Cependant, tout en edebugsautant à la place dans la fonction instrumentée et vous donne donc un indice où chercher (ce qui est un peu idiot puisque vous savez déjà exactement ce que vous avez instrumenté), debugne le fait pas du tout. J'ai retiré un petit hack après avoir découvert que chaque fois debugqu'un tampon est évalué, il émet la valeur de point associée à l'erreur; en d'autres termes, l'utilisation de ces informations sur le tampon peut vous donner un numéro de ligne dans le backtrace!

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

Avec cela, il faut répondre à la question originale dans le titre. Quant à votre problème avec l'obtention d'une trace en premier lieu, je suis à court d'idées utiles.


Merci pour votre aide, mais je ne comprends toujours pas comment obtenir le numéro de ligne. M-x debug...? Alors sur quoi dois-je appuyer?
Jackson

Avec ce code, vous verrez un numéro de ligne dans les debugtraces créées par , vous pouvez vérifier en visitant un fichier elisp défectueux, en faisant M-x toggle-debug-on-erroret M-x eval-buffer, puis une trace avec un numéro de ligne à la position problématique devrait apparaître.
wasamasa

Est-ce que cela fonctionnera si vous n'utilisez pas eval-buffer? Par exemple, si vous appuyez simplement sur un raccourci clavier qui exécute une commande privée qui échoue et ouvre le débogueur dans le *Backtrace*tampon.
Håkon Hægland

Non, ce ne sera pas le cas. Vous obtenez la valeur de fonction du symbole (qui peut être une liste ou quelque chose de compilé en octets) et c'est à peu près tout.
wasamasa

4

Peut-être parce que c'est 2018 maintenant, mais dans mon cas, je n'ai eu qu'à activer le débogage comme l'a suggéré wasamasa: Mx toggle-debug-on-error

Après cela, Mx eval-buffer sur mon fichier Elisp défectueux a donné le contexte en fournissant la position de l'erreur, comme ceci: Debugger entered--Lisp error: (invalid-read-syntax ")") eval-buffer() ; Reading at buffer position 523 [....]

Mx goto-char saute à la position d'erreur: M-x goto-char 523


Belle trouvaille! Il semble que cela ait été ajouté en 2017, à l'époque où ils ont retravaillé cette fonction pour travailler sur une liste d'éléments de trace.
wasamasa

1

J'ai étendu la réponse de wasamasa pour inclure des informations supplémentaires:

(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))))
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.