emacs: how do I use edebug on code that is defined in a macro?

emacs, lisp

Solution

According to `(elisp)Top > Debugging > Edebug > Edebug and Macros` you have to tell Edebug how to debug a macro by defining it with `debug` statements or by using `def-edebug-spec`. This tells it what parameters should be evaluated and which shouldn't. So it can be done. In fact it looks as if `c-lang-defconst` already been fitted for `edebug`. Here is the definition in case you were interested:

(def-edebug-spec c-lang-defconst
  (&define name [&optional stringp] [&rest sexp def-form]))

However, if you just want to see what the body evaluates to, then the way to do that is to use something like `macro-expand-last-sexp` below to see the result. Position your cursor after the sexp you want expanded (as you would for `C-x C-e`) and run `M-x macro-expand-last-sexp RET`. This will show you what it gets expanded to. You may run into troubles if you try to expand something like `,(....)` so you may have to copy that sexp somewhere else and delete the `,` or `,@`.

(defun macro-expand-last-sexp (p)
  "Macro expand the previous sexp.  With a prefix argument
insert the result into the current buffer and pretty print it."
  (interactive "P")
  (let*
      ((sexp (preceding-sexp))
       (expanded (macroexpand sexp)))
    (cond ((eq sexp expanded)
           (message "No changes were found when macro expanding"))
          (p
           (insert (format "%S" expanded))
           (save-excursion
             (backward-sexp)
             (indent-pp-sexp 1)
             (indent-pp-sexp)))
          (t
           (message "%S" expanded)))))

I guess it depends on exactly what you are trying to do.

Problem

I don't even know the proper terminology for this lisp syntax, so I don't know if the words I'm using to ask the question, make sense. But the question makes sense, I'm sure. So let me just show you. cc-mode (cc-fonts.el) has things called "matchers" which are bits of code that run to decide how to fontify a region of code. That sounds simple enough, but the matcher code is in a form I don't completely understand, with backticks and comma-atsign and just comma and so on, and furthermore it is embedded in a c-lang-defcost, which itself is a macro. I don't know what to call all that, but I want to run edebug on that code. Look: ``` (c-lang-defconst c-basic-matchers-after "Font lock matchers for various things that should be fontified after generic casts and declarations are fontified. Used on level 2 and higher." t `(;; Fontify the identifiers inside enum lists. (The enum type ;; name is handled by `c-simple-decl-matchers' or ;; `c-complex-decl-matchers' below. ,@(when (c-lang-const c-brace-id-list-kwds) `((,(c-make-font-lock-search-function (concat "\\<\\(" (c-make-keywords-re nil (c-lang-const c-brace-id-list-kwds)) "\\)\\>" ;; Disallow various common punctuation chars that can't come ;; before the '{' of the enum list, to avoid searching too far. "[^\]\[{}();,/#=]*" "{") '((c-font-lock-declarators limit t nil) (save-match-data (goto-char (match-end 0)) (c-put-char-property (1- (point)) 'c-type 'c-decl-id-start) (c-forward-syntactic-ws)) (goto-char (match-end 0))))))) ``` I am reading up on lisp syntax to figure out what those things are and what to call them, but aside from that, how can I run edebug on the code that follows the comment that reads `;; Fontify the identifiers inside enum lists.` ? I know how to run edebug on a defun - just invoke `edebug-defun` within the function's definition, and off I go. Is there a corresponding thing I need to do to edebug the cc-mode matcher code forms? What does `def-edebug-spec` do, and would I use it here? If so, how?

Original source