Wie kann ich eine in einem Use-Package-Block definierte Funktion edebuggen?


7

Hier ist ein Mindestarbeitsbeispiel, um das Problem zu demonstrieren. Sie müssen das use-packagePaket installiert haben:

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

Wenn ich versuche, der dummy/functionVerwendung eine Edebug-Instrumentierung hinzuzufügen M-x edebug-defun, wird der Edebug sofort gestartet, als ob ich es bereits getan hätte M-x dummy/function. Ich muss das durch Schlagen beenden q. Aber wenn ich es tatsächlich tue M-x dummy/function, sehe ich nicht, dass der Edebug aktiviert wird.

Gibt es etwas an dem use-packageWrapper, das mit der Edebug-Instrumentierung in Konflikt gerät? Wie kann es behoben werden?


Ich weiß nicht, wie das Use-Package funktioniert, aber dummy/functionbehebt das Definieren auf oberster Ebene (dh außerhalb des Use-Package) das unmittelbare Problem? Ich habe die Verwendung anonymer Lambda-Funktionen zugunsten benannter Funktionen eingestellt, um ähnliche Probleme bei Mode-Hooks zu lösen.
Tyler

@ Ja, Funktionen, die außerhalb des use-packageWrappers definiert sind, können problemlos edebuggt werden. Ich möchte alles, was mit Paket X (use-package X ..)zu tun hat, einpacken, einschließlich meiner benutzerdefinierten Funktionen, die sich auf X beziehen. Wenn jedoch ein Fehler in diesen Funktionen auftritt, muss ich meine Code-Organisation überdenken.
Kaushal Modi

Wenn Sie der Meinung sind, dass das gesuchte Verhalten angegeben werden sollte, dies jedoch nicht der Fall ist, sollten Sie eine Emacs-Verbesserungsanforderung einreichen : M-x report-emacs-bug. Seien Sie bereit, ein einfaches Rezept bereitzustellen, das von beginnt emacs -Q.
Drew

1
Ich denke, edebug-defundebuggt das Top-Level-Formular, das in diesem Fall (use-package ...)eher das Selbst als das Defun ist, das Sie an das use-packageMakro übergeben. Können Sie edebug-on-entryden Namen der von Ihnen definierten Funktion verwenden und angeben?
Glucas

1
FWIW, ich benutze den regulären Emacs-Debugger debug, nicht edebug. Zum Beispiel M-x debug-on-entry. HTH.
Drew

Antworten:


9

Wenn Sie es aufrufen edebug-defun, debuggt das Formular der obersten Ebene, in diesem Fall (use-package ...).

Sie können debug-on-entryeine benannte Funktion debuggen.


4
  1. Markiere den entsprechenden Defun und rufe C-x nn( narrow-to-region) auf
  2. C-u C-M-x( edebug-defun)
  3. C-x nw( widen)

Wenn Sie es mögen, Dinge schnell zu erledigen , ist dies eine lispige Abkürzung N xe W.


1
Dies funktioniert nicht, da es narrow-to-defunsich auf dieselbe (use-package ...)Form beschränkt, die es edebug-defunfindet. Es funktioniert jedoch, wenn Sie zuerst den Defun markieren und verwenden narrow-to-region.
Glucas

Ja das meinte ich. Ich benutze eigentlich nicht narrow-to-defun. lispy‚s Nwählt Region und fordert narrow-to-region.
abo-abo

3

edebug-defun

Vielen Dank an @ abo-abo für den Tipp, zuerst den Defun zu markieren.

Hier ist eine schnelle Möglichkeit zum Aktivieren / Deaktivieren edebug-defun. Dies wird verwendet search-backward-regexp, um den defun- oder defmacro-Namen korrekt zu edebug-instrumentieren oder auszuwerten, unabhängig davon, ob er im use-packageWrapper definiert ist oder nicht.

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

Verwendung - Mit dem Punkt an einer beliebigen Stelle im Funktions- / Makrokörper wird der Aufruf für diese Entität modi/toggle-edebug-defunaktiviert oder deaktiviert edebug.

debug-on-entry

Dank @glucas und @Drew habe ich mir eine bequeme Möglichkeit zum Umschalten ausgedacht debug-on-entry. Dies verwendet auch den gleichen Ansatz wie oben, um den Namen defun / defmacro zu analysieren.

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

Verwendung - Wenn sich der Punkt an einer beliebigen Stelle im Funktionskörper befindet, wird durch Aufrufen die Funktion für diese Funktion modi/toggle-debug-defunaktiviert oder abgebrochen debug-on-error.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.