branch: externals/vertico
commit 95d0d4c9aa0d13e4333cec0fdfdf19487e282a28
Author: Daniel Mendler <m...@daniel-mendler.de>
Commit: Daniel Mendler <m...@daniel-mendler.de>

    Guard Vertico hooks to automatically show stack traces
---
 CHANGELOG.org |  5 +++++
 README.org    | 20 +++-----------------
 vertico.el    | 35 +++++++++++++++++++++++++++++------
 3 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/CHANGELOG.org b/CHANGELOG.org
index 8d15a5967c..4d6e1a23de 100644
--- a/CHANGELOG.org
+++ b/CHANGELOG.org
@@ -2,6 +2,11 @@
 #+author: Daniel Mendler
 #+language: en
 
+* Development
+
+- Guard Vertico hooks to automatically print stack traces in order to ease
+  debugging.
+
 * Version 2.1 (2025-04-19)
 
 - =vertico-flat-format=: Customizable =:spacer= string.
diff --git a/README.org b/README.org
index 9e8381e57b..2fa61ce9ed 100644
--- a/README.org
+++ b/README.org
@@ -502,23 +502,9 @@ assignment to the FSF.
 
 * Debugging Vertico
 
-When you observe an error in the =vertico--exhibit= post command hook, you 
should
-install an advice to enforce debugging. This allows you to obtain a stack trace
-in order to narrow down the location of the error. The reason is that post
-command hooks are automatically disabled (and not debugged) by Emacs. Otherwise
-Emacs would become unusable, given that the hooks are executed after every
-command.
-
-#+begin_src emacs-lisp
-(setq debug-on-error t)
-
-(defun force-debug (func &rest args)
-  (condition-case e
-      (apply func args)
-    ((debug error) (signal (car e) (cdr e)))))
-
-(advice-add #'vertico--exhibit :around #'force-debug)
-#+end_src
+Vertico will automatically print a stack trace to the =*Messages*= buffer when 
an
+error is detected. The stack trace allows you to narrow down the exact code
+location which caused the error.
 
 * Problematic completion commands
 
diff --git a/vertico.el b/vertico.el
index efab3dca23..6c97e9a3d4 100644
--- a/vertico.el
+++ b/vertico.el
@@ -463,14 +463,37 @@ The value should lie between 0 and vertico-count/2."
         (put-text-property beg next 'face (remq face (ensure-list val)) obj))
       (setq beg next))))
 
+(defun vertico--debug (&rest _)
+  "Debugger used by `vertico--guard'."
+  (require 'backtrace)
+  (declare-function backtrace-to-string "backtrace")
+  (declare-function backtrace-get-frames "backtrace")
+  (let ((inhibit-message t))
+    (message "Vertico detected an error:\n%s"
+             (backtrace-to-string (backtrace-get-frames #'vertico--debug))))
+  (let (message-log-max)
+    (message "%s %s"
+             (propertize "Vertico detected an error:" 'face 'error)
+             (substitute-command-keys "Press \\[view-echo-area-messages] to 
see the stack trace")))
+  nil)
+
+(defmacro vertico--guard (&rest body)
+  "Guard BODY showing a stack trace on error."
+  `(condition-case nil
+       (let ((debug-on-error t)
+             (debugger #'vertico--debug))
+         ,@body)
+     ((debug error) nil)))
+
 (defun vertico--exhibit ()
   "Exhibit completion UI."
-  (let ((buffer-undo-list t)) ;; Overlays affect point position and undo list!
-    (vertico--update 'interruptible)
-    (vertico--prompt-selection)
-    (vertico--display-count)
-    (vertico--display-candidates (vertico--arrange-candidates))
-    (vertico--resize)))
+  (vertico--guard
+   (let ((buffer-undo-list t)) ;; Overlays affect point position and undo list!
+     (vertico--update 'interruptible)
+     (vertico--prompt-selection)
+     (vertico--display-count)
+     (vertico--display-candidates (vertico--arrange-candidates))
+     (vertico--resize))))
 
 (defun vertico--goto (index)
   "Go to candidate with INDEX."

Reply via email to