Edebug User Manual

A Source Level Debugger for GNU Emacs Lisp

Edition 1.2, March 1992

by Daniel LaLiberte, liberte@cs.uiuc.edu

Copyright © 1991, 1992 Daniel LaLiberte



This is edition 1.2 of the Edebug User Manual for edebug Version 2.6, February 1991.



Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.

Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that this permission notice may be stated in a translation approved by this author.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1 Edebug

Edebug is a source level debugger for GNU Emacs Lisp that provides the following features:

It isn’t necessary to read all of this document, or even most of it, in order to make use of edebug. You should minimally read sections Installation, Using Edebug, and Edebug Modes; the rest can be read as needed.

This manual assumes you are familiar with Emacs Lisp, as described in the GNU Emacs Lisp Reference Manual. You might want to review the chapters on Evaluation and Debugging.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.1 Installation

Put ‘edebug.el’ in some directory in your load-path and byte-compile it.

Put the following forms in your ‘.emacs’ file.

(define-key emacs-lisp-mode-map "\C-xx" 'edebug-defun)
(autoload 'edebug-defun "edebug")

If you wish to change the default edebug global command prefix, include the following.

(setq edebug-global-prefix "\C-xX") ; or whatever you want

[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.2 Using Edebug

To use edebug you must be editing an Emacs Lisp buffer using emacs-lisp-mode, or its equivalent, since the Emacs Lisp syntax table must be present.

The following commands are described in this section.

C-xx

(edebug-defun) Evaluates the function or macro at or after point setting it up for use by edebug. Unlike eval-defun it always prints edebug: name in the minibuffer and a prefix argument has a different effect as described below. If a syntax error is found, point is left at the error and mark is set to the original point.

?

(edebug-help) Display the help message for edebug-mode.

a

(abort-recursive-edit) Abort the edebug recursive edit. This only aborts one level as opposed to all the way to the top level.

q

(top-level) Exit all recursive editing levels to the top level command loop.

r

(edebug-previous-result) Redisplay the result of the previous expression in the echo area.

To use edebug, simply evaluate a defun or defmacro with edebug-defun (C-xx) when the point is in or before the definition. The next time your function or macro is called, edebug will be called. From now on, discussion about using edebug with functions includes macros, unless otherwise specified. Like eval-defun, edebug-defun evaluates function definitions, but adds edebug calls to the lambda expression.

To restore a function to normal operation after the definition has been evaluated with edebug-defun, simply reevaluate it with one of the commands that evaluate definitions (e.g., eval-defun (M-C-x), eval-current-buffer, or if the buffer is unchanged, load-library). However, the behavior of most of these evaluating functions can also be modified by edebug, as described in Evaluating defuns.

Implementation note: Recall that a defun is the source code definition of a function and evaluation of a definition puts the lambda expression for the function in the function cell of the symbol naming the function. After evaluating a defun with edebug-defun, the lambda expression stored in the function symbol’s function cell contains a call to the function edebug-enter at the top level and individual calls to the function edebug-before and edebug-after for each expression that may be evaluated in the function.

When you call your function explicitly or via another function, edebug will be called, but it may or may not stop execution depending on what the current edebug mode is. Some edebug modes only update the display to indicate the progress of the evaluation without stopping execution. The default initial edebug mode is step which does stop execution. The edebug modes are described in detail below (see section Edebug Modes).

Each time edebug updates the display to indicate the progress of the evaluation, the buffer that the function is defined in is displayed temporarily. Also point is moved (temporarily) to the expression in the function about to be evaluated (or just evaluated) and an overlay arrow is displayed at the left end of the line containing point. If the point is not visible in the window, the window start is changed (semi-permanently!) so that point is visible, while trying to display as much of the following code as possible. See The Outside Context for more details on how the Emacs display is affected by edebug.

In the example below, the definition of the fac function has been evaluated with edebug-defun (by positioning point within the definition and hitting C-xx) and the expression (fac 3) has been evaluated. The arrow on the first line indicates that edebug has been entered. To indicate that you are stopped before the first expression, the cursor would be on the first left parenthesis of that line.

(defun fac (n)
=>(if (< 0 n)
      (* n (fac (1- n)))
    1))

When execution is stopped, you are in edebug in a recursive edit with point in the buffer defining the function, as described above. This buffer, called the edebug buffer, is made read-only and the edebug-mode minor mode is activated. Several commands are available in addition to the standard emacs-lisp-mode bindings. Try the ? command (edebug-help) for a list of edebug commands. From the edebug recursive edit, you are permitted to call functions that invoke edebug again recursively. At any time in edebug, you can quit to the top level with q (top-level) or abort one recursive edit level with a (abort-recursive-edit).

Places within a function that edebug may stop, called stop points, are before and after expressions that are not self-evaluating, i.e. list forms and symbols. However, edebug does not stop before symbols (i.e., variables) unless edebug-stop-before-symbols is non-nil, since it is not usually useful to do so. When stopped after an expression, edebug displays the result of the expression in the minibuffer. Use the r command (edebug-previous-result) to see that result again. You can control the way in which expression results are printed by using the ‘custom-print’ package (see section Printing).

Edebug knows about all the special forms, interactive forms with expressions, anonymous lambda expressions, and embedded defun or defmacro calls. It cannot know what a macro will do with the arguments of a macro call so you must tell it; see section Macro Calls for the details. You can use the same mechanism to tell edebug that some function arguments should be functions.

Continuing the example of the fac function, the user may step through the execution of the function (with <SPC>) stopping in edebug at the stop points which are marked with a period:

(defun fac (n)
=>.(if .(< 0 n.).
      .(* n. .(fac (1- n.).).).
    1).)

Whenever a function evaluated with edebug-defun is active, the Emacs debugger named by the variable debugger is set to edebug-debug, so it is not necessary to set it yourself. (Currently there is no option to turn off this feature.) If an error occurs and debug-on-error is non-nil, edebug will display the error and move point to the last known stop point. This applies to quit signals too, if debug-on-quit is non-nil. But in any case, if no function that was evaluated with edebug-defun is currently active, debug is run normally. Note that you can also get a full backtrace inside of edebug (see Miscellaneous).


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.3 Evaluating defuns

There are a couple other ways to evaluate a defun for edebug besides calling edebug-defun directly. The variable edebug-all-defuns affects the behavior of several commands defined by Emacs. eval-defun (M-C-x) is redefined by ‘edebug.el’ to use edebug-defun if edebug-all-defuns is non-nil, or alternatively, if you supply a prefix argument. But if edebug-all-defuns is non-nil and you also supply a prefix argument, edebug-defun will not be used. In other words, the prefix argument of eval-defun reverses the effect of edebug-all-defuns. The default value of edebug-all-defuns is nil. Call the function edebug-all-defuns to toggle the value of the variable edebug-all-defuns.

Note that this version of eval-defun evaluates whatever top level form it finds, as it normally does, but only defuns (and defmacros) are evaluated with edebug-defun.

eval-region is redefined to use edebug-defun when evaluating defuns (if edebug-all-defuns is non-nil). The prefix argument for eval-region has the normal behavior since it is used by other functions (including the standard functions eval-defun, eval-print-last-sexp, and eval-last-sexp). If an error occurs during the evaluation, point is left after the expression in error. Also, this eval-region does not use narrow-to-region to limit the scope of evaluation, and consequently there is a small difference in how white space is handled after an expression when the output is inserted in the buffer.

eval-current-buffer is redefined to use eval-region, since the standard version does not, thus gaining all the benefits of the new eval-region.

Note that loading does not invoke edebug-defun, since the load functions are subroutines that use the internal eval-region rather than the redefined one supplied by ‘edebug.el’. This could be considered a feature since loading a file does not also visit the file which would be necessary if edebug were to be invoked on one of the functions defined in the file.

See Evaluation for discussion of other evaluation functions available inside of edebug.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.4 Edebug Modes

While your function is being evaluated, edebug is in one of several modes. The current mode is called the edebug mode, not to be confused with major or minor modes. The current edebug mode determines how edebug displays the progress of the evaluation, whether it stops at each stop point, or continues to the next breakpoint, for example.

Each time you enter edebug, you will be in the same mode you specified the previous time you were in edebug. The exception is when edebug is first entered for each recursive edit level; then the mode is changed to the value in the global variable edebug-initial-mode, which defaults to step mode. In the case of a command where the interactive form has an expression argument, the expression is evaluated before the function is really entered, so the edebug mode defaults to edebug-initial-mode both for this expression and for the first expression in the function body. (In fact, this repeated resetting to the initial mode also occurs each time your function is called non-recursively before returning to the command level which invoked the function.)

Below is a table of the keys which change the edebug mode. For each key, the mode is set and the recursive edit is exited; what happens next depends on which mode you selected, which code your function executes, and whether a breakpoint is hit. You can also set the edebug mode when edebug is not running (or in a non-edebug buffer) by hitting C-xX (default value of edebug-global-prefix) followed by the same key as used inside of edebug. Most of the other edebug commands are available in the same manner.

<SPC>

(edebug-step-through) Step mode stops at the next stop point encountered.

t

(edebug-trace) Trace mode pauses one second at each edebug stop point.

T

(edebug-Trace-fast) Trace with zero pause time at each stop point.

c

(edebug-continue) Continue after pausing for one second at each breakpoint.

C

(edebug-Continue-fast) Continue with zero pause time at each breakpoint.

g

(edebug-go) Go until a breakpoint. See section Breakpoints.

G

(edebug-Go-nonstop) Go non-stop ignoring breakpoints. This is the fastest way to execute code that has edebug calls in it, but this mode of execution is still interruptible; see below.

S

(edebug-stop) Stop executing at the first stop point encountered, regardless of the mode. This command does not change the mode and does not continue execution; it is intended to be used to interrupt execution.

To execute edebugged code more rapidly, use commands farther down in the list. For example, Go-nonstop mode is alot faster that trace mode since it ignores breakpoints. The continue modes do not stop at breakpoints, but merely pause at them.

While executing or tracing, you can interrupt the execution by hitting one of the edebug command characters, at which time the command is acted on. For example, hitting <SPC> will stop execution at the first stop point because input is pending, but will then step to the next stop point. Alternatively, S is bound to edebug-stop which does nothing but stop. If your function happens to read input, a character you hit intending to interrupt execution may be read by the function instead, so be careful in the neighborhood of the read call. Also see the discussion of errors and quit signals in Using Edebug.

Keyboard macros invoked within edebug will not work across edebug calls, so you must enter each edebug command separately. (It doesn’t seem worth it to save and restore keyboard macro definitions and executions between calls to edebug in such a way that it doesn’t affect any outside command processing, and it may not be possible in any case.)


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.5 Miscellaneous

Some miscellaneous commands are described here.

f

(edebug-forward-sexp) Proceed from the current point to the sexp found by first doing forward-sexp and then switching to go mode. If a prefix argument is supplied, do forward-sexp that many times. If there are not enough sexps for forward-sexp, call edebug-step-out instead. Be careful that the sexp found by forward-exp will be executed; this will not always be the case in a condition-case, for example. A temporary breakpoint is set at the stop point, so it will be used and cleared whenever execution reaches it. See Breakpoints for the details on breakpoints.

Notice that we do the forward-sexp starting at the current point rather than the stop point, thus providing more flexibility. If you want to start the search at the stop point, first do edebug-where (w).

o

(edebug-step-out) Proceed from the current point to the end of the containing sexp. If the containing sexp is the top level defun, go to the end of the last sexp instead, or if that is the same point, then step out of the function. Therefore this command does not exit the currently executing function unless you are positioned after the last sexp of the function.

Like edebug-forward-sexp, this command switches to go mode to get to the containing sexp. The only situation in which the containing sexp will not be reached by edebug is if a non-local exit by-passes it.

i

(edebug-step-in) Step into the function about to be called. Use this command before any of the arguments of the function call are evaluated since otherwise it will be too late. One side effect of using edebug-step-in is that the next time the stepped-into function is called, edebug will be called there as well. (I may try to fix this in the future.)

h

(edebug-goto-here) Proceed to the stop point near the current point. A temporary breakpoint is used. See Breakpoints for details on how the stop point is found.

d

(edebug-backtrace) A debug-like backtrace is displayed. All calls to edebug functions are removed to clean up the display. This backtrace does not function like the standard backtrace so you cannot specify which frames to stop at, etc. - but it is better than nothing. The backtrace buffer is killed automatically when you continue execution.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.6 Breakpoints

The purpose of breakpoints is to let you specify significant places in your code where you would like edebug to stop or pause execution. Breakpoints may be set at any stop points as defined in Using Edebug, even before symbols. Edebug will stop or pause at a breakpoint except when the edebug mode is Go-nonstop. For setting and unsetting breakpoints, the stop point that is affected is at or after the current point. The following commands are related to breakpoints:

b

(edebug-set-breakpoint) Set a breakpoint at the stop point at or after the current point. With prefix-arg, the breakpoint is temporary.

u

(edebug-unset-breakpoint) Unset or clear a breakpoint at the stop point at or after the current point.

x

(edebug-set-conditional-breakpoint) Set a conditional breakpoint. You are asked for the conditional expression. With prefix-arg, the breakpoint is temporary.

B

(edebug-next-breakpoint) Move point to the next breakpoint in the current function definition.

While in edebug, you can set a breakpoint with b (edebug-set-breakpoint) and unset (or clear) it with u (edebug-unset-breakpoint). First move point to a position at or before the desired edebug stop point, then hit the key to change the breakpoint. Unsetting a breakpoint that has not been set does nothing.

Reevaluating the defun with edebug-defun clears all breakpoints in the function. (Let me know if you would like breakpoints preserved; I could use marks for breakpoints instead of relying on the offsets >from the beginning of the defun.)

A conditional breakpoint is set with x (edebug-set-conditional-breakpoint). When you set a conditional breakpoint you will be asked for an expression which is evaluated each time the breakpoint is reached. Edebug will only stop at a conditional breakpoint if the condition evaluates to non-nil. But conditional breakpoints are not even checked if the edebug mode is Go-nonstop.

For both conditional and unconditional breakpoints, the breakpoint can be made into a temporary breakpoint if you give a prefix arg to the command. After breaking at a temporary breakpoint, it is automatically cleared.

To find out where your breakpoints are, use the B (edebug-next-breakpoint) command which moves point to the next breakpoint in the function following point, or to the first breakpoint if there are no following breakpoints. (Note that this command does not continue execution - it just moves the point.)


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.7 Views

If the function you are debugging modifies the Emacs window environment, you may wish to check the outside window configuration as it was before edebug was called, since edebug itself also modifies the window environment (see Outside Window Configuration for how edebug tries to restore it). The following commands relate to views in general.

v

(edebug-view-outside) View the outside window configuration.

p

(edebug-bounce-point) Bounce to the point in the outside current buffer, and return after one second.

w

(edebug-where) Move point back to the current stop point.

W

(edebug-toggle-save-windows) Toggle the edebug-save-windows variable. Each time you toggle it, the inside and outside window configurations become the same as the current configuration. By turning this off and on again, edebug thereafter restores the outside window configuration to the current configuration.

You can view the outside window configuration with v (edebug-view-outside) or bounce to the current point in the current buffer with p (edebug-bounce-point), even if it is not normally displayed. After moving point or changing buffers, you may wish to pop back to the stop point with w (edebug-where) from an edebug window or C-xXw in any window.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.8 Evaluation

This section describes commands related to the explicit and automatic evaluation of expressions in edebug. Edebug attempts to make such evaluations while inside of edebug appear that they are occuring outside of edebug, as if edebug had not been invoked. Almost everything about the outside context is restored (see section The Outside Context for the details). But M-ESC (eval-expression) still evaluates expressions normally (in the current context) since that is occasionally needed. Also supported is an evaluation list window where expressions may be evaluated interactively or automatically.

You can control the way in which expression results are printed by using the ‘custom-print’ package (see section Printing).

e

(edebug-eval-expression) Evaluates an expression in the outside context of your function, rather than in the edebug context as M-ESC does. (These commands are therefore consistent with the same commands in the standard debugger.)

C-xC-e

(edebug-eval-last-sexp) Like eval-last-sexp except in the outside context.

E

(edebug-visit-eval-list) Jump to an evaluation list window in which several other commands apply, described below. The evaluation list is reevaluated each time the edebug display is updated (including tracing) and the results are displayed in a temporary buffer ‘*edebug*’.

The following commands apply to the evaluation list which is displayed in the ‘*edebug*’ buffer. All the lisp-interaction-mode commands are also available.

LFD

(edebug-eval-print-last-sexp) Similar to eval-print-last-sexp but in the outside context.

C-xC-e

(edebug-eval-last-sexp) Similar to eval-last-sexp but in the outside context.

C-cC-u

(edebug-update-eval-list) Build a new evaluation list from the first expression of each group, reevaluate and redisplay. Groups are separated by a line starting with a comment.

C-cC-d

(edebug-delete-eval-item) Delete the evaluation list group that point is in.

C-cC-w

(edebug-where) Jump back to the edebug buffer at the current stop point.

In the evaluation list window, type in expressions and evaluate them with LFD (edebug-eval-print-last-sexp) or C-xC-e (edebug-eval-last-sexp), just as you would for lisp interaction mode but the evaluation is done in the outside context. (Note: eval-region is not redefined to evaluate in the outside context; it is only redefined to use edebug-defun when it encounters a defun - see Evaluating defuns.)

The expressions you enter interactively, and their results, will be lost when you continue execution of your function unless you add them to the evaluation list. To add any number of expressions to the evaluation list use C-cC-u (edebug-update-eval-list). This builds a new list from the first expression of each "group", where groups are separated by a line starting with a comment.

When the evaluation list is redisplayed, each expression is displayed followed by the result of evaluating it, and a comment line. If an error occurs during an evaluation, the error message is displayed in a string as if it were the result. Therefore expressions that use undefined variables will not interrupt your debugging. Here is an example of what the evaluation list window looks like after several expressions have been added to it.

(current-buffer)
#<buffer *scratch*>
;---------------------------------------------------------------
(point-min)
1
;---------------------------------------------------------------
(point-max)
2
;---------------------------------------------------------------
edebug-outside-point-max
"Symbol's value as variable is void: edebug-outside-point-max"
;---------------------------------------------------------------
(recursion-depth)
0
;---------------------------------------------------------------
this-command
eval-last-sexp
;---------------------------------------------------------------

You can delete the group that point is positioned in with C-cC-d (edebug-delete-eval-item), or use normal editing commands to modify the text as much as you want (e.g. delete-region). Be sure to update the evaluation list with C-cC-u before you continue evaluation of your function or quit to the top level, unless you want your changes to be lost. Also be sure to separate each "group" with a comment before updating, otherwise the wrong expressions may end up in the list.

You can return to the source code buffer (the edebug buffer) with C-cC-w which is equivalent to C-xXw. The *edebug* buffer is killed when you continue execution of your function, and recreated next time it is needed.

If you are concerned with exactly how the evaluation is done, you may need to know that the evaluation of expressions occurs in one of two slightly different outside contexts. If the evaluation list is non-empty when edebug is entered, the context used to evaluate it is closest to the true outside context since nothing much has changed when the evaluation is done. However, when you evaluate expressions within edebug using the above described interactive commands or when you update the evaluation list, as much of the outside context is restored as possible, but not everything (see section The Outside Context). One way to observe the difference is to look at the recursion-depth.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.9 Printing

If the results of your expressions contain circular references to other parts of the same structure, the standard Emacs print subroutines may fail to print with an error, "Apparently circular structure being printed". If you only use cdr circular lists (where cdrs of lists point back; what is the right term here?), you can limit the length of printing with print-length and edebug does this for you when printing out the previous result. But car circular lists and circular vectors generate the above mentioned untrappable error in Emacs version 18. Version 19 will support print-level, but it is often useful to get a better print representation of circular structures.

To handle printing of structures more generally, you can use the ‘custom-print’ package which supports print-level, print-circle, and further customizations via custom-print-list and custom-print-vector. See the documentation strings of these variables for more details. There are two main ways to use this package. First, you may replace prin1, princ, and some subroutines that use them by calling install-custom-print-funcs so that any use of these functions in lisp code will be affected. Second, you could call the custom routines directly, thus only affecting the printing that requires them. Edebug uses the second method, as described next.

To load the package and activate custom printing only for edebug, simply use the command edebug-install-custom-print-funcs. This sets the function cells of edebug-prin1, edebug-print, edebug-prin1-to-string, and edebug-format to the symbol names of the corresponding custom versions. Therefore, any changes you make to the custom functions or to the variables controlling custom printing take effect immediately. Notice you still need to set print-level or print-circle. To restore the standard print functions, use edebug-reset-print-funcs.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10 The Outside Context

This section is useful for those who need to know more precisely what edebug is doing that might affect editing and the context of expression evaluation. For the most part, edebug operates transparently and there should be no apparent difference running with edebug, except for debugging itself. If you find any variation with what is described here, please let me know.

An important distinction is made between the outside context which exists before edebug is invoked, and the inside context which exists while edebug is active. Most of the outside context is saved and restored each time you enter and exit from edebug. In addition, most evaluations you do within edebug (see Evaluation) occur in the same outside context which is temporarily restored for the evaluation.

Described in this section are the aspects of the outside context that are saved and restored including things as diverse as window configurations, current buffer status, and variable values. These aspects are divided into three sections, corresponding to the degree to which edebug has affected the outside context. The first section, immediately following this, is for those things that are affected any time edebug is called even if the display is not updated. The second section is for when edebug must update the display. The third section is for when edebug stops execution and enters a recursive edit. Finally, the few unavoidable side effects of using edebug are described.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10.1 Just Checking

The following are saved and restored when edebug is called even if the display is not updated. One reason there is anything at all to save and restore is that the call to edebug-enter must remain active while your function is active, and this impacts the Lisp stack. The other reason is that execution may be interrupted at any time unless the edebug mode is Go-nonstop, but an executing keyboard macro should not interrupt execution.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10.2 Outside Window Configuration

One important aspect of the outside context is the outside window configuration. A full description of window configurations may be found in the GNU Emacs Lisp Reference Manual. If you are running ‘epoch’, the concept of a window configuration is generalized to include the set of current screens, though if you create or destroy screens while in edebug, this effect will not be reversed.

When you exit from edebug (each time you continue execution, in fact), the window configuration outside of edebug is restored to what it was before edebug was entered. But since Emacs delays screen update until needed, if you then reenter edebug before a screen update is required, it will appear that you never left; that is, the outside window configuration will not be displayed even though it was in effect. If your function completes normally, the outside window configuration will finally be displayed when you return to the command level, or any time a screen update is forced by some other means (e.g. sit-for).

The window configuration, as defined by Emacs, does not include which buffer is current or where point and mark are in the current buffer, but edebug saves and restores these also. Note that the outside window configuration restored by edebug may not be fully consistent with the real outside context since the selected window may not yet have been displayed but edebug may have forced screen update.

If the display needs to be updated by edebug, e.g. a trace mode is active, the following are saved and restored. However, if an error or quit signal occurs, some of these are intensionally not restored for user convenience.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10.3 Recursive Edit

If edebug stops execution and enters a recursive-edit, the following additional things are saved and restored.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.10.4 Side Effects

Many other things may be changed by the user explicitly while in the edebug recursive edit if they are not protected against change as described above, and this may be considered a feature in most cases. However, some possibly undesirable side effects of using edebug remain, most of which are unavoidable:


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.11 Macro Calls

This section describes a mechanism you may use to tell edebug how the arguments of macro calls should be evaluated. The same mechanism may be used for special forms and some function calls.

To edebug your macro calls, you must specify how the arguments may be evaluated. In the general case, not all macro arguments will be evaluated. But if it so happens that all your macro arguments are evaluatable (i.e. they may eventually be evaluated either explicitly in the macro body or when the resulting expansion is evaluated), then you can set the edebug-eval-macro-args option to non-nil. On the other hand, if you don’t want any of your macro arguments to be evaluated by edebug then you can ensure they will not be wrapped in edebug calls by setting edebug-eval-macro-args to nil (the default).

In the more likely case that some macro arguments are to remain unevaluated (e.g. a symbol) and some may be evaluated, you can specify an edebug-form-spec for each macro. Implementation note: edebug uses edebug-form-specs for special forms and some function calls as well as macro calls. You can do the same, but there is not really much point, except for functions that take function arguments.

Use the macro def-edebug-form-spec to define a specification for a function or macro which is stored in the edebug-form-spec property of the symbol naming the function or macro. The first argument is the symbol name and the second argument is the specification which may be one of five kinds of values. First, if a specification for a symbol is nil or undefined, then depending on the value of edebug-eval-macro-args, all the arguments will be treated as evaluatable (if it’s non-nil) or unevaluatable (if it’s nil).

If the specification is a quoted function (symbol or lambda expression), then this function is called to process the arguments of the calling form.

As a convenience, def-edebug-form-spec may be given t or 0 as its second argument. If it is t, then all arguments are treated as evaluatable; if it is 0 (not nil), then all arguments are treated as unevaluateable. Implementation note: these values are actually converted by def-edebug-form-spec to the functions edebug-forms and edebug-sexps respectively.

Finally, if the edebug-form-spec is a list, then the elements of the list describe the types of the arguments of a calling form. The list is processed left to right, in the same order as the arguments of the calling form, and the elements constrain the types of corresponding arguments and specify whether they may be evaluated. Each element may be one of the following:

symbolp

An unevaluated symbol.

integerp

An unevaluated number.

stringp

An unevaluated string.

vectorp

An unevaluated vector.

atom

An unevaluated number, string, symbol, or vector.

sexp

An unevaluated sexp (atom or list); the argument may be nil or () but it must not be missing.

form

An evaluated sexp.

function

A function argument may be a quoted (using quote or function) symbol or lambda expression or a form (that should evaluate to a function or lambda expression). The body of an anonymous function will be treated as evaluateable.

other

Any other symbol should be the name of a function; this function is called on the argument as a predicate, and an error is signaled if the predicate fails. You could use this to check whether a literal is of a certain custom type.

(...)

A sublist of the same format as the top level, processed recursively. The actual argument must be a list as well. Special case: if the car of the element is quote, the actual argument must match the quoted sexp, usually a symbol (see example of for macro below).

[...]

A sublist of the same format as the top level, processed recursively. It is processed like (...) except the matched arguments are inserted in-line into the arguments matched by the containing list, somewhat analogous to @, in backquoted expressions. This may be used for grouping to build complex elements out of the primitives provided.

&optional

All following elements in the specification list at this level may or may not match arguments; as soon as one does not match, processing of the specification list terminates. To get only one specification item to be optional, use [...].

&rest

All following elements in the specification list at this level are repeated in order zero or more times. Allowing more than one &rest element is an extension of the normal meaning of &rest. All the &rest elements need not be used in every repetition, however. Only one &rest may appear at the same level of a specification list, and &rest must not be followed by &optional. To specify that only some types arguments are to be repeated until failure, followed by some other types of arguments, use [...].

&or

Each of the following elements in the specification list at this level are alternatives, processed left to right until one succeeds. To group two or more list elements as one alternative, bracket them in [...]. Only one &or may appear in a list, and it may not be followed by &optional or &rest. One of the alternatives must match, unless the &or is preceeded by &optional or &rest.

If a failure to match occurs, this does not necessarily mean a syntax error will be signalled; instead, backtracking will take place until all alternatives have been exhausted. &optional elements need not match at all of course, but evenually every element of the argument list must be matched or an error will be signalled. Non-optional elements in the specification unused when the argument list has been completely matched will also cause backtracking, or ultimately a syntax error.

The combination of backtracking, &optional, &rest, &or, and [...] for grouping provides the equivalent of regular expressions. The (...) lists require balanced parentheses, which is the only context free (finite state with stack) construct supported. Dotted pair notation is not yet supported, but let me know if you need it.

I am considering writing a compiler for edebug-form-spec list forms that would generate elisp code to process arguments the same way edebug-interpret-form-spec now does it but alot faster. Suggestions appreciated.

Here are some examples of using edebug-form-spec. A let form looks like: (let (bindings ...) forms ...), where each of the bindings is either a symbol or (symbol value-form). The edebug-form-spec for a let form is defined as follows:

(def-edebug-form-spec let
  '((&rest
    &or symbolp (symbolp &optional form))
   &rest form))

A for loop macro is defined in the GNU Emacs Lisp Reference Manual (reference needed), and ‘cl.el’ defines case and do macros. Here are their edebug-form-specs.

(def-edebug-form-spec for
  '(symbolp 'from form 'to form 'do &rest form))

(def-edebug-form-spec case
  '(form &rest (sexp form)))

(def-edebug-form-spec do
  '((&rest &or symbolp (symbolp &optional form form))
    (form &rest form)
    &rest body))

Finally, the functions mapcar, mapconcat, mapatoms, apply, and funcall all take function arguments, and edebug defines specifications like the following one for apply.

(def-edebug-form-spec apply '(function &rest form))

Note that backquote (`) is a macro that results in an expression that is not necessarily evaluated. It is often used to simplify the definition of a macro where the result of the macro call is evaluated, but edebug does not know when this is the case. So do not be surprised when you cannot step through your backquoted code. 23 On the other hand, one could wrap the backquoted expression in a special function, say edebug-`, which would mean that the result of the backquote form will, in fact, be evaluated. Then edebug could wrap evaluateable expressions within the backquoted expression in edebug calls. Is it worth it?


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.12 Options

User Option: edebug-all-defuns

Default nil. If non-nil, all defuns and defmacros evaluated will use edebug. eval-defun without prefix arg and eval-region will use edebug-defun.

If nil, eval-region evaluates normally, but eval-defun with prefix arg uses edebug-defun. eval-region is called by eval-defun, eval-last-sexp, and eval-print-last-sexp.

You may wish to make this variable local to each elisp buffer by calling (make-local-variable 'edebug-all-defuns) in your emacs-lisp-mode-hook. You can use the function edebug-all-defuns to toggle its value.

User Option: edebug-eval-macro-args

Default nil. If non-nil, edebug will assume that all macro call arguments for macros that have no edebug-form-spec may be evaluated, otherwise it will not. To specify exceptions for macros that have some arguments evaluated and some not, you should specify an edebug-form-spec (see section Macro Calls).

User Option: edebug-stop-before-symbols

Default nil. Non-nil causes edebug to stop before symbols as well as after. This option is used when the edebug-defun is called, not when edebugging, so set the option before using edebug-defun.

User Option: edebug-save-windows

Default t. If non-nil, save and restore window configuration on edebug calls. It takes some time to save and restore, so if your program does not care what happens to the window configurations, it is better to set this variable to nil.

User Option: edebug-save-point

Default t. If non-nil, save and restore the point and mark in source code buffers.

User Option: edebug-save-displayed-buffer-points

Default nil. If non-nil, save and restore the points of all buffers, displayed or not.

Saving and restoring buffer points is necessary if you are debugging code that changes the point of a buffer which is displayed in a non-selected window. If edebug or the user then selects the window, the buffer’s point will be changed to the window’s point.

Saving and restoring is an expensive operation since it visits each window and each displayed buffer twice for each edebug call, so it is best to avoid it if you can.

User Option: edebug-initial-mode

Default 'step. Global initial mode for edebug, if non-nil. This is used when edebug is first entered for each recursive-edit level. Possible values are nil (meaning use the current edebug-mode), 'step, 'go, 'Go-nonstop, 'trace, 'Trace-fast, 'continue, and 'Continue-fast.

User Option: edebug-trace

Default nil. Non-nil if edebug should show a trace of function entry and exit. Tracing output is displayed in a buffer named ‘*edebug-trace*’, one function entry or exit per line, indented by the recursion level. You can customize by replacing functions edebug-print-trace-entry and edebug-print-trace-exit.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

1.13 Todo List

Send me your suggestions and priorities.

If you are interested in running edebug on functions in edebug.el, I find it easiest to first copy edebug.el into another file, say fdebug.el, and replace all strings "edebug" with "fdebug", then evaluate the fdebug buffer and run edebug on functions in fdebug.el.


[ << ] [ < ] [ Up ] [ > ] [ >> ]         [Top] [Contents] [Index] [ ? ]

Index


[Top] [Contents] [Index] [ ? ]

Table of Contents


[Top] [Contents] [Index] [ ? ]

About This Document

This document was generated on May 19, 2025 using texi2html 5.0.

The buttons in the navigation panels have the following meaning:

Button Name Go to From 1.2.3 go to
[ << ] FastBack Beginning of this chapter or previous chapter 1
[ < ] Back Previous section in reading order 1.2.2
[ Up ] Up Up section 1.2
[ > ] Forward Next section in reading order 1.2.4
[ >> ] FastForward Next chapter 2
[Top] Top Cover (top) of document  
[Contents] Contents Table of contents  
[Index] Index Index  
[ ? ] About About (help)  

where the Example assumes that the current position is at Subsubsection One-Two-Three of a document of the following structure:


This document was generated on May 19, 2025 using texi2html 5.0.