Como edebug uma função definida em um bloco de pacote de uso?

7

Aqui está um exemplo de trabalho mínimo para demonstrar o problema, você precisará ter o use-packagepacote instalado:

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

Quando tento adicionar a instrumentação edebug ao dummy/functionuso M-x edebug-defun, ele inicia o edebug corretamente como se eu já tivesse feito M-x dummy/function. Eu tenho que parar com isso q. Mas quando eu realmente faço M-x dummy/function, não vejo o edebug sendo ativado.

Existe algo sobre o use-packagewrapper que mexe com a instrumentação edebug? Como pode ser consertado?

Kaushal Modi
fonte
Não sei como o pacote de uso funciona, mas a definição dummy/functionno nível superior (ou seja, fora do pacote de uso) corrige o problema imediato? Parei de usar funções lambda anônimas em favor de funções nomeadas para lidar com tipos semelhantes de problemas nos ganchos de modo.
Tyler
@ Sim, as funções definidas fora do use-packagewrapper podem ser editadas com perfeição. Gostaria de invólucro de tudo relacionado ao pacote X interior (use-package X ..), incluindo as minhas funções personalizadas relacionadas com X. Mas se edebug dessas funções é um problema, então eu precisaria repensar minha organização código ..
Kaushal Modi
Se você acha que o comportamento que você está procurando deve ser fornecido, mas não é, considerar a apresentação de uma solicitação de melhoria Emacs: M-x report-emacs-bug. Esteja preparado para fornecer uma receita simples que comece emacs -Q.
Drew
11
Eu acho que edebug-defundepura o formulário de nível superior, que neste caso é o (use-package ...)próprio, e não o desafiador que você está passando para a use-packagemacro. Você pode usar edebug-on-entrye dar o nome da função que você definiu?
glucas
11
FWIW, eu uso o depurador Emacs comum debug, não edebug. Por exemplo M-x debug-on-entry,. HTH.
Drew

Respostas:

9

Quando você o chama edebug-defun, depura o formulário de nível superior, que neste caso é (use-package ...).

Você pode usar debug-on-entrypara depurar uma função nomeada.

glucas
fonte
4
  1. Marque o defun apropriado e chame C-x nn( narrow-to-region)
  2. C-u C-M-x( edebug-defun)
  3. C-x nw( widen)

Se você gosta de fazer as coisas rapidamente, atalho lispy para isso é N xe W.

abo-abo
fonte
11
Isso não funciona porque se narrow-to-defunrestringe à mesma (use-package ...)forma edebug-defunencontrada. No entanto, ele funciona se você marcar o desfunho primeiro e usá-lo narrow-to-region.
glucas
Sim, foi o que eu quis dizer. Na verdade, eu não uso narrow-to-defun. lispy's Nseleciona região e chamadas narrow-to-region.
abo-abo 23/01
3

edebug-defun

Agradecemos a @ abo-abo pela dica para marcar o primeiro desunião.

Aqui está uma maneira rápida de ativar / desativar edebug-defun. Isso usa search-backward-regexppara edebug-instrumentar ou avaliar o nome defun ou defmacro corretamente, esteja ele definido no use-packagewrapper ou não.

;; 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))))

Uso - Com o ponto em qualquer lugar no corpo da função / macro, a chamada modi/toggle-edebug-defunserá ativada ou desativada edebugpara essa entidade.

debug-on-entry

Graças a @glucas e @Drew, criei uma maneira conveniente de alternar debug-on-entry. Isso também usa a mesma abordagem acima para analisar o nome defun / defmacro.

;; 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)))))

Uso - Com o ponto em qualquer lugar no corpo da função, a chamada modi/toggle-debug-defunativará ou cancelará o debug-on-errorpara essa função.

Kaushal Modi
fonte