Mostrar número de línea en caso de error


15

Digamos que emacs arroja algún error que no entiendo. O tal vez el error dice "El valor del símbolo como variable es nulo: modos", pero hay muchas apariciones del símbolo modesen mi código, por lo que necesito algo de contexto. ¿Se puede configurar Emacs para mencionar el número de línea del código lisp para que yo pueda saber qué código está causando el error?

Intenté hacerlo (setq stack-trace-on-error '(buffer-read-only))y ejecuté el código perpetrador en un esfuerzo por obtener un seguimiento de la pila. No hay rastro de pila tampoco.

También he intentado llamar edebug-defuna mi función y recorrerla. No es hasta que salgo de la función que se produce el error.

(Realmente no estoy tan interesado en la causa del error particular que estoy enfrentando actualmente como en el desarrollo de habilidades generales de depuración para elisp. Por favor, infórmeme sobre cómo puedo obtener un número de línea, un sexp o un seguimiento de pila de un error.)


¿Ya probaste no- nil debug-on-error? ¿Eso no ayuda?
Dibujó

No Eso no parece hacer nada. (Después de configurarlo ty luego proceder a evaluar una función de lanzamiento de errores)
Jackson

Probablemente lo que sucede es que algún otro código detecta el error y simplemente imprime el mensaje de error. También verifique que debug-ignored-errorsno enumere ningún error. Si establece debug-on-signalen non- nil, y fue el caso en que el otro código manejó el error, podrá obtener el error antes que el otro código.
wvxvw 01 de

Actualmente estoy en una situación similar y estaba leyendo esta pregunta. Me pregunto sobre stack-trace-on-error. Esta variable no está documentada en Emacs 25.1.
Matthias

Respuestas:


15

Emacs proporciona una buena cantidad de recursos de depuración que incluyen M-x toggle-debug-on-error, M-x toggle-debug-on-quitdepurar la señal (que se puede usar enviando USR2a Emacs desde el exterior), debug-on-entry(de una función), debug-on-message(cuando se ve una coincidencia específica de expresión regular de un mensaje) y, finalmente, debugcomo alternativa para instrumentar una función con C-u C-M-x.

Ambos debugy edebugofrecen suficiente funcionalidad para inspeccionar el estado de Emacs al evaluar el código que le interesa, presione ee ingrese una expresión.

Sin embargo, mientras edebugsalta al lugar en la función instrumentada y, por lo tanto, le da una pista sobre dónde mirar (lo cual es un poco tonto ya que ya sabe exactamente qué ha instrumentado), debugno hace esto en absoluto. Realicé un truco más pequeño después de descubrir que cada vez que debugevalúa un búfer, emite el valor del punto asociado con el error; en otras palabras, ¡usar esta información en el búfer puede darle un número de línea en la traza inversa!

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

Con esto, la pregunta original en el título debe ser respondida. En cuanto a su problema para obtener un seguimiento en primer lugar, no tengo ideas útiles.


Gracias por su ayuda, pero todavía no entiendo cómo obtener el número de línea. M-x debug...? Entonces, ¿qué presiono?
Jackson

Con este código, verá un número de línea en las trazas hacia atrás realizadas debug, puede verificar visitando un archivo elisp defectuoso, haciendo M-x toggle-debug-on-errory M-x eval-buffer, luego, debería aparecer una traza hacia atrás con un número de línea en la posición problemática.
wasamasa

¿Funcionará esto si no lo usas eval-buffer? Por ejemplo, si solo presiona un método abreviado de teclado que ejecuta un comando privado que falla y abre el depurador en el *Backtrace*búfer ..
Håkon Hægland

No, no lo hará. Obtiene el valor de la función del símbolo (que puede ser una lista o algo compilado por bytes) y eso es todo.
wasamasa

4

Tal vez porque ahora es 2018, pero en mi caso, solo tuve que activar la depuración como sugirió wasamasa: Mx toggle-debug-on-error

Después de esto, Mx eval-buffer en mi archivo defectuoso de Elisp dio contexto al proporcionar la posición del error, así: Debugger entered--Lisp error: (invalid-read-syntax ")") eval-buffer() ; Reading at buffer position 523 [....]

Mx goto-char salta a la posición de error: M-x goto-char 523


Buen hallazgo! Parece que esto se agregó en 2017, cuando volvieron a trabajar esa función para trabajar en una lista de elementos de rastreo.
wasamasa

1

He extendido la respuesta de wasamasa para incluir información adicional:

(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))))
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.