8

Here is a minimum working example to demonstrate the problem, you will need to have the use-package package installed:

(use-package ido
  :config
  (progn
    (defun dummy/function ()
      (interactive)
      (message "I am in the dummy function."))))

When I try to add edebug instrumentation to the dummy/function using M-x edebug-defun, it starts the edebug rightaway as if I already did M-x dummy/function. I have to quit that by hitting q. But then when I actually do M-x dummy/function, I don't see the edebug activating.

Is there something about the use-package wrapper that messes with the edebug instrumentation? How can it be fixed?

Kaushal Modi
  • 25,203
  • 3
  • 74
  • 179
  • I don't know how use-package works, but does defining `dummy/function` at top-level (i.e., outside of use-package) fix the immediate problem? I've stopped using anonymous lambda functions in favor of named functions to deal with similar sorts of problems in mode-hooks. – Tyler Jan 22 '15 at 20:47
  • @Yes, functions defined outside the `use-package` wrapper can be edebugged fine. I would like to wrapper everything related to package X inside `(use-package X ..)`, including my custom functions related to X. But if edebug of those functions is an issue, then I would need to rethink my code organization.. – Kaushal Modi Jan 22 '15 at 21:02
  • If you think the behavior you are looking for should be provided but is not, consider filing an Emacs enhancement request: `M-x report-emacs-bug`. Be prepared to provide a simple recipe that starts from `emacs -Q`. – Drew Jan 22 '15 at 21:24
  • @Drew I sure will do once I figure out if it is an issue with the `use-package` package or emacs. If the function is outside `use-package` wrapper, edebug works fine. – Kaushal Modi Jan 22 '15 at 21:26
  • 1
    I think `edebug-defun` debugs the top-level form, which in this case is the `(use-package ...)` itself rather than the defun you are passing in to the `use-package` macro. Can you use `edebug-on-entry` and give the name of the function you've defined? – glucas Jan 22 '15 at 21:42
  • 1
    FWIW, I use the regular Emacs debugger, `debug`, not `edebug`. For example, `M-x debug-on-entry`. HTH. – Drew Jan 22 '15 at 22:01
  • Ask Wiegley. He should be able to tell you how to use `use-package`, including how to debug such problems. ;-) – Drew Jan 22 '15 at 22:03
  • @glucas I think you meant `debug-on-entry` and yes that works! Thanks! That can serve as an answer. Thanks @Drew, I used `debug-on-entry` and that serves my purpose. – Kaushal Modi Jan 22 '15 at 22:25

3 Answers3

9

When you call edebug-defun it debugs the top-level form, which in this case is (use-package ...).

You can use debug-on-entry to debug a named function.

glucas
  • 20,175
  • 1
  • 51
  • 83
6
  1. Mark the appropriate defun and call C-x nn (narrow-to-region)
  2. C-u C-M-x (edebug-defun)
  3. C-x nw (widen)

If you like doing things quickly, lispy shortcut for this is N xe W.

abo-abo
  • 13,943
  • 1
  • 29
  • 43
  • 1
    This doesn't work because `narrow-to-defun` narrows to the same `(use-package ...)` form that `edebug-defun` finds. However it does work if you mark the defun first and use `narrow-to-region`. – glucas Jan 23 '15 at 15:04
  • Yes, that's what I meant. I don't actually use `narrow-to-defun`. `lispy`'s `N` selects region and calls `narrow-to-region`. – abo-abo Jan 23 '15 at 15:20
3

edebug-defun

Thanks to @abo-abo for the tip to mark the defun first.

Here is a quick way to enable/disable edebug-defun. This uses search-backward-regexp to edebug-instrument or eval the defun or defmacro name correctly, whether it is defined in use-package wrapper or not.

;; Edebug a defun or defmacro
(defvar modi/fns-in-edebug nil
  "List of functions for which `edebug' is instrumented.")

(defconst modi/fns-regexp (concat "(\\s-*"
                                  "\\(defun\\|defmacro\\)\\s-+"
                                  "\\(?1:\\(\\w\\|\\s_\\)+\\)\\_>") ; word or symbol char
  "Regexp to find defun or defmacro definition.")

(defun modi/toggle-edebug-defun ()
  (interactive)
  (let (fn)
    (save-excursion
      (search-backward-regexp modi/fns-regexp)
      (setq fn (match-string 1))
      (mark-sexp)
      (narrow-to-region (point) (mark))
      (if (member fn modi/fns-in-edebug)
          ;; If the function is already being edebugged, uninstrument it
          (progn
            (setq modi/fns-in-edebug (delete fn modi/fns-in-edebug))
            (eval-region (point) (mark))
            (setq-default eval-expression-print-length 12)
            (setq-default eval-expression-print-level  4)
            (message "Edebug disabled: %s" fn))
        ;; If the function is not being edebugged, instrument it
        (progn
          (add-to-list 'modi/fns-in-edebug fn)
          (setq-default eval-expression-print-length nil)
          (setq-default eval-expression-print-level  nil)
          (edebug-defun)
          (message "Edebug: %s" fn)))
      (widen))))

Usage - With the point anywhere in the function/macro body, calling modi/toggle-edebug-defun will enable or disable edebug for that entity.

debug-on-entry

Thanks to @glucas and @Drew, I have cooked up a convenient way to toggle debug-on-entry. This also uses the same approach as above to parse the defun/defmacro name.

;; Debug on entry
(defvar modi/fns-in-debug nil
  "List of functions for which `debug-on-entry' is instrumented.")

(defun modi/toggle-debug-defun ()
  (interactive)
  (let (fn)
    (save-excursion
      (search-backward-regexp modi/fns-regexp)
      (setq fn (match-string 1)))
    (if (member fn modi/fns-in-debug)
        ;; If the function is already being debugged, cancel its debug on entry
        (progn
          (setq modi/fns-in-debug (delete fn modi/fns-in-debug))
          (cancel-debug-on-entry (intern fn))
          (message "Debug-on-entry disabled: %s" fn))
      ;; If the function is not being debugged, debug it on entry
      (progn
        (add-to-list 'modi/fns-in-debug fn)
        (debug-on-entry (intern fn))
        (message "Debug-on-entry: %s" fn)))))

Usage - With the point anywhere in the function body, calling modi/toggle-debug-defun will enable or cancel the debug-on-error for that function.

Kaushal Modi
  • 25,203
  • 3
  • 74
  • 179