Tampilkan nomor baris jika ada kesalahan

15

Katakan bahwa emacs melempar kesalahan yang tidak saya mengerti. Atau mungkin kesalahan mengatakan "Nilai simbol sebagai variabel tidak berlaku: mode", tetapi ada banyak kemunculan simbol modesdalam kode saya, jadi saya perlu konteks. Bisakah Emacs dikonfigurasikan untuk menyebutkan nomor baris kode lisp sehingga saya bisa tahu kode apa yang menyebabkan kesalahan?

Saya telah mencoba melakukan (setq stack-trace-on-error '(buffer-read-only))dan menjalankan kode yang ada dalam upaya untuk mendapatkan jejak stack. Tidak ada jejak stack juga.

Saya juga mencoba memanggil edebug-defunfungsi saya dan melangkah melaluinya. Tidak sampai saya keluar dari fungsi kesalahan dilemparkan.

(Saya benar-benar tidak tertarik pada penyebab kesalahan tertentu yang saya hadapi saat ini seperti halnya saya dalam mengembangkan keterampilan debugging umum untuk elisp. Mohon saran tentang bagaimana saya dapat mengumpulkan nomor baris, atau sexp, atau jejak stack dari kesalahan.)

Jackson
sumber
Apakah Anda sudah mencoba non- nil debug-on-error? Bukankah itu membantu?
Drew
Nggak. Sepertinya tidak melakukan apa-apa. (Setelah saya mengaturnya untuk tkemudian melanjutkan untuk eval fungsi kesalahan melempar.)
Jackson
Mungkin yang terjadi adalah beberapa kode lain menangkap kesalahan dan hanya mencetak pesan kesalahan. Periksa juga debug-ignored-errorsapakah tidak ada kesalahan. Jika Anda mengatur debug-on-signalke non- nil, dan itu adalah kasus kode lain menangani kesalahan, Anda akan bisa mendapatkan kesalahan sebelum kode lain melakukannya.
wvxvw
Saya saat ini dalam situasi yang sama dan sedang membaca pertanyaan ini. Saya bertanya-tanya tentang stack-trace-on-error. Variabel ini tidak didokumentasikan dalam Emacs 25.1.
Matthias

Jawaban:

15

Emacs menyediakan sejumlah fasilitas debug termasuk M-x toggle-debug-on-error,, M-x toggle-debug-on-quitdebug sinyal (yang dapat digunakan dengan mengirim USR2ke Emacs dari luar), debug-on-entry(dari suatu fungsi), debug-on-message(ketika melihat kecocokan regexp tertentu dari suatu pesan) dan akhirnya, debugitu sendiri sebagai alternatif menginstruksikan fungsi dengan C-u C-M-x.

Keduanya debugdan edebugmenawarkan fungsionalitas yang cukup untuk memeriksa keadaan Emacs ketika mengevaluasi kode yang Anda minati, tekan edan masukkan ekspresi.

Namun, ketika edebugmelompat ke tempat dalam fungsi yang diinstrumentasi dan karena itu memberi Anda petunjuk di mana mencarinya (yang agak konyol karena Anda sudah tahu apa sebenarnya yang telah Anda instal), debugtidak melakukan ini sama sekali. Saya telah melakukan hack yang lebih kecil setelah menemukan bahwa setiap kali debugmengevaluasi buffer, ia memancarkan nilai titik yang terkait dengan kesalahan; dengan kata lain menggunakan informasi ini pada buffer dapat memberi Anda nomor baris di 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)))

Dengan ini pertanyaan awal dalam judul harus dijawab. Adapun masalah Anda dengan mendapatkan backtrace di tempat pertama, saya kehabisan ide berguna.

wasamasa
sumber
Terima kasih atas bantuan Anda, tetapi saya masih tidak mengerti cara mendapatkan nomor telepon. M-x debug...? Lalu apa yang harus saya tekan?
Jackson
Dengan kode ini Anda akan melihat nomor baris di backtraces yang dibuat oleh debug, Anda dapat memeriksa dengan mengunjungi file elisp yang salah, melakukan M-x toggle-debug-on-errordan M-x eval-buffer, kemudian jejak balik dengan nomor baris di posisi bermasalah harus muncul.
wasamasa
Apakah ini akan berhasil jika Anda tidak menggunakannya eval-buffer? Misalnya, jika Anda cukup menekan pintasan keyboard yang menjalankan perintah pribadi yang gagal dan membuka debugger di *Backtrace*buffer ..
Håkon Hægland
Tidak, tidak akan. Anda mendapatkan nilai fungsi simbol (yang bisa berupa daftar atau sesuatu yang dikompilasi dengan byte) dan itu cukup banyak.
wasamasa
4

Mungkin karena ini tahun 2018 sekarang, tetapi dalam kasus saya, saya hanya perlu mengaktifkan debug seperti yang disarankan wasamasa: Mx toggle-debug-on-error

Setelah ini, Mx eval-buffer pada file Elisp saya yang salah memberikan konteks dengan memberikan posisi kesalahan, seperti ini: Debugger entered--Lisp error: (invalid-read-syntax ")") eval-buffer() ; Reading at buffer position 523 [....]

Mx goto-char melompat ke posisi kesalahan: M-x goto-char 523

mistige
sumber
Temuan yang bagus! Tampaknya ini telah ditambahkan pada 2017, saat mereka mengerjakan ulang fungsi itu untuk bekerja pada daftar item backtrace.
wasamasa
1

Saya telah memperluas jawaban wasamasa untuk memasukkan informasi tambahan:

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