Emacs和Emacs Lisp的故障排除技巧

16

我已经是一名使用Emacs的用户4年了,但是当涉及到自定义Emacs和处理Elisp代码时,我仍然是个新手。最近,我开始将Emacs作为我的Ruby开发环境进行自定义,并从StackOverflow的朋友那里学习了一些技巧。 例如,有人在这里告诉我可以使用C-u C-M-x来让一个函数启用edebug并逐步执行代码。我还发现,在Emacs中大多数命令和模式都提供了很多钩子(函数、正则表达式或可自定义变量),它们会提供任何新手需要的大部分内容。
现在我还想进一步了解更多你过去使用并认为有用的技巧和提示。

6个回答

14
 (setq debug-on-error t)
 (setq debug-on-quit t)

这些工具有助于您在调试深层问题时使用。您已经发现了 edebug(这是我解决其他人代码问题的首选工具)。describe-function 通常会给出链接到加载它的 .el 文件(以及行号)。这对于跳转到问题源代码非常有用。我经常这样做,复制函数,添加一些 message 调用,然后重新评估 C-x C-e,使其运行而不是原来的。

更新: 这是我从 John Wiegley 的一个 演讲中学到的小技巧。

(global-set-key (kbd "C-c C-d")
        (lambda () (interactive)
          (setq debug-on-error (if debug-on-error nil t))
          (message (format "debug-on-error : %s" debug-on-error))))

您可以通过一个按键轻松切换debug-on-error


2
关于编辑,toggle-debug-on-error 默认已经存在 :) - phils
当编写自己的代码比搜索现有代码更容易时,就说出这句话吧。 :) 加1并感谢。 - Noufal Ibrahim

6

C-x Esc Esc命令可以让你浏览M-x命令的历史记录,但是它会显示elisp代码。

IELM是emacs lisp的repl。

Speedbar是浏览.el文件的绝佳方式,我经常使用C-h i(浏览elisp手册)和使用speedbar来浏览节点树中的主题。

在info浏览器中,C-s / C-r增量搜索实际上会搜索页面断点之后的内容。

我经常运行M-:来测试一小段代码,而无需切换到我的*ielm*缓冲区。

对于特别棘手的代码,我会在桌面上创建一个快捷方式,以运行emacs -q -l development-init.el(这对于处理缓冲区和外部进程的低级操作非常方便,这种操作很容易挂起emacs或导致segv错误)。


2

如果要修改你的 .emacs 文件,一定要保留一个 Emacs 进程,并通过启动第二个 Emacs 进程(使用 --debug-init)测试更改。这样,如果出现问题,你仍然可以在另一个编辑器中工作。


1

我的初始化文件对调试工具进行了注释:

;;;; * Debugging, Tracing, and Profiling

;; M-: (info "(elisp) Debugging") RET

;; Standard debugger:
;; M-x debug-on-entry FUNCTION
;; M-x cancel-debug-on-entry &optional FUNCTION
;; debug &rest DEBUGGER-ARGS
;; M-x toggle-debug-on-error
;; M-x toggle-debug-on-quit
;; setq debug-on-signal
;; setq debug-on-next-call
;; setq debug-on-event
;; setq debug-on-message REGEXP

;; Edebug -- a source-level debugger for Emacs Lisp
;; M-x edebug-defun (C-u C-M-x) Cancel with eval-defun (C-M-x)
;; M-x edebug-all-defs -- Toggle edebugging of all definitions
;; M-x edebug-all-forms -- Toggle edebugging of all forms
;; M-x edebug-eval-top-level-form

;; Tracing:
;; M-x trace-function FUNCTION &optional BUFFER
;; M-x untrace-function FUNCTION
;; M-x untrace-all

;; Timing and benchmarking:
;; (benchmark-run &optional REPETITIONS &rest FORMS)

;; Emacs Lisp Profiler (ELP)
;; M-x elp-instrument-package
;; M-x elp-instrument-list
;; M-x elp-instrument-function
;; M-x elp-reset-*
;; M-x elp-results
;; M-x elp-restore-all
;;
;; "There's a built-in profiler called ELP. You can try something like
;; M-x elp-instrument-package, enter "vc", and then try finding a file
;; Afterwards, M-x elp-results will show you a profile report.
;; (Note that if the time is instead being spent in non-vc-related
;; functions, this technique will not show it, but you can instrument
;; further packages if you like.)" https://dev59.com/juo6XIcBkEYKwwoYSClJ#6732810

;; CPU & Memory Profiler ('Native Profiler')
;; M-x profiler-start
;; M-x profiler-report
;; M-x profiler-reset
;; M-x profiler-stop
;; M-x profiler-*

;; Dope ("DOtemacs ProfilEr. A per-sexp-evaltime profiler.")
;; https://raw.github.com/emacsmirror/dope/master/dope.el
;; M-x dope-quick-start will show a little introduction tutorial.

;; Spinning:
;; Set debug-on-quit to t
;; When the problem happens, hit C-g for a backtrace.

1

就我而言,我更喜欢(推荐)debug而不是edebug,但这可能只是品味问题。

除了Noufal提到的debug-on-*变量之外,您还可以通过M-x debug-on-entry进入给定函数的调试器。

您还可以在代码中的断点处放置显式调用debug(debug)(debug nil sexp-to-print)


0

欢迎来到启蒙的第一步。;)

首先,几个简单的快速提示:

(add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)

这将为您提供有关迷你缓冲区的小提示。它非常方便!这个技巧不是关于故障排除,而是让编写变得容易,但仍然有效。

从MELPA获取erefactor包,并查看它的功能。我注意到在对函数执行C-x C-e后,它会通过elint运行结果。这样可以节省很多麻烦。

emacs starter kit中的此钩子非常棒。它会删除任何无效的.elc文件。如果不小心处理,旧的elc文件可能会成为一个真正的问题。相反,请查看auto-compile。

(add-hook 'emacs-lisp-mode-hook 'starter-kit-remove-elc-on-save)

(defun starter-kit-remove-elc-on-save ()
  "If you're saving an elisp file, likely the .elc is no longer valid."
  (make-local-variable 'after-save-hook)
  (add-hook 'after-save-hook
            (lambda ()
              (if (file-exists-p (concat buffer-file-name "c"))
                  (delete-file (concat buffer-file-name "c"))))))

最后,当你编辑Lisp、Emacs Lisp或Scheme时,请确保尝试使用Paredit。它非常棒。

个人认为删除 .elc 文件是一个可怕的想法。像 byte-recompile-directory 这样的工具只有在存在相应(但过时)的 .elc 文件时才会编译文件,因此删除该文件实际上可能会阻止重新编译!相反,我非常强烈地建议在文件过期时自动重新编译文件。我曾经使用 after-save-hook 来运行 (when (file-exists-p (byte-compile-dest-file buffer-file-name)) (byte-compile-file buffer-file-name)),但现在我真的很喜欢 auto-compile,它可以处理几乎所有情况。 - phils
说实话,我宁愿使用慢一点的Elisp也不要用不一致的。 - Jonathan Arkell
当然,但如果.elc文件在必要时自动重新编译,那么你就可以兼顾一致性和速度。认真看看自动编译吧。 - phils
是的,自动编译看起来很不错。 - Jonathan Arkell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接