Programming in Emacs Lisp – Debugging After using Emacs for over 4 years, I am still feeling like scratching the surface of the functionalities of this feature-laden editor. It is a text editor with so many extensions that can do almost anything you want with flexibility and customizability.
Debug utility allows one to inspect under the hood and to trace the changes of variable and functions. It is also the best way to learn the language, in general.
There are two ways to debug elisp code: debug and edebug.
These are 4 common entry points (ways to use it):
- M-x debug-on-entry followed by a function you want to enter using the debugger.
- M-x toggle-debug-on-error – Enter the debugger when when an error is raised.
- ~ M-x toggle-debug-on-quit ~– Enter the debugger when the user hits C-g.
Place explicit calls to function debug at particular places (breakpoints) in your code, to enter the debugger at those places:
You step through the debugger using d, or ~c ~to skip over the details of a particular evaluation.
Useful Setting for debug
(setq debug-on-error t)
(setq debug-on-quit t)
(global-set-key (kbd "C-c C-b")
(lambda () (interactive)
(setq debug-on-error (if debug-on-error nil t))
(message (format "debug-on-error : %s" debug-on-error))))
Edebug – the Source Level Debugger
Edebug, one of the best debugging tools, is a wonderful tool to debug and learn elisp. And it is a Source Level Debugger edebug – Programming in Emacs Lisp.
Normally, you would install the definition by positioning your cursor after the function’s closing parenthesis and typing C-x C-e ( eval-last-sexp) or else by positioning your cursor within the definition and typing C-M-x ( eval-defun).
In order to use Edebug to debug Lisp code, you must first instrument the code. Instrumenting code inserts additional code into it, to invoke Edebug at the proper places.
When you invoke command C-M-x ( eval-defun) with a prefix argument on a function definition, it instruments the definition before evaluating it. (This does not modify the source code itself.) If the variable edebug-all-defs is non-nil, that inverts the meaning of the prefix argument: in this case, C-M-x instruments the definition unless it has a prefix argument. The default value of edebug-all-defs is nil. The command M-x edebug-all-defs toggles the value of the variable edebug-all-defs.
More on instrumenting.
First, setup keybinding if not already.
;;find-function (format "message" format-args)or edebug
(global-set-key (kbd "C-h C-f") 'find-function)
(global-set-key (kbd "C-M-x") 'eval-defun)
The following is the steps to edebug:
- eval-buffer or function-to-debug (not necessary if everything’s already defined).
- Invoke C-u C-M-x on function-to-debug to instrument it – turn on edebug on function-to-debug; or M-x edebug-defun <RET>. Run M-x eval-defun in the function body to undo edebug-defun.
- Invoke M-x function-to-debug or some other function calls the function-to-debug, and you’ll be taken immediately into edebug, with point right before the (function-to-debug) expression.
- In edebug, with point right before a function call, you can hit i to instrument and step into that function, even if it was not prevously instrumented; o to step out.
Press SPC to step through the code, e to evaluate expressions (you can use this to find the values of numbers), h to continue until the specified point, b to set a breakpont, g to execute until a breakpoint, and q to stop debugging.
The following is a screencast of edebug in action.
Comparison of key strokes of debug and edebug
|engage||C-h f then C-u C-M-x||embed (debug) or M-x debug-on-entry RET triangle-bugged RET|
|step out sexp||o|
|disengage||C-h f then C-M-x||remove (debug)|