Показати номер рядка про помилку


15

Скажіть, що emacs видає помилку, яку я не розумію. Або, можливо, помилка говорить "Значення символу як змінної є недійсним: режими", але 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-signalне- nil, і це був випадок, коли інший код обробив помилку, ви зможете отримати помилку до того, як зробив інший код.
wvxvw

Зараз я перебуваю в подібній ситуації і читав це запитання. Мені цікаво про стек-трасування на помилку. Ця змінна не задокументована в Emacs 25.1.
Маттіас

Відповіді:


15

Emacs забезпечує велику кількість налагоджувальних засобів, включаючи M-x toggle-debug-on-error, M-x toggle-debug-on-quitналагодження сигналу (який може бути використаний при надсиланні USR2на Emacs ззовні), debug-on-entry(функції), debug-on-message(коли бачимо певну відповідність повторної передачі повідомлення) і, нарешті, debugсам як альтернативу до інструментування функції з C-u C-M-x.

І те, debugі edebugпропонують достатню функціональність для перевірки стану Emacs під час оцінки коду, який вас цікавить, натисніть 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-errorа M-x eval-bufferпотім з'явиться зворотний трек з номером рядка в проблемному положенні.
wasamasa

Чи буде це працювати, якщо ви не використовуєте eval-buffer? Наприклад, якщо просто натиснути комбінацію клавіш, яка виконує приватну команду, яка не працює і відкриває налагоджувач у *Backtrace*буфері.
Håkon Hægland,

Ні, не буде. Ви отримуєте значення функції символу (який може бути списком або складеним байтом), і це майже все.
wasamasa

4

Може, тому, що зараз 2018 рік, але в моєму випадку мені довелося лише ввімкнути налагодження, як запропонував wasamasa: Mx toggle-debug-on-error

Після цього Mx eval-буфер у моєму несправному файлі Elisp дав контекст, надавши позицію помилки, як це: 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))))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.