Subject: bug#61274: 29.0.60; dabbrev-capf signals errors

From: Eli Zaretskii <[email-masked]>
Date: Sat, 04 Feb 2023 15:16:42 +0200

> Cc: [email-masked]
> From: Daniel Mendler <[email-masked]>
> Date: Sat, 04 Feb 2023 12:03:26 +0100
> 
> The completion-at-point-function `dabbrev-capf' sometimes signals
> errors. It would be good if the function would not do that but return
> nil if no completions are found, such that the next Capf from the list
> of completion functions gets its chance to run.
> 
> 1. Start emacs -Q
> 2. Evaluate (require 'dabbrev).
> 3. Evaluate (setq completion-at-point-functions '(dabbrev-capf)) in the
> scratch buffer.
> 4. Type `x M-TAB` in the scratch buffer. I observe the following error:
> 
> Debugger entered--Lisp error: (wrong-type-argument stringp nil)
>   dabbrev--goto-start-of-abbrev()
>   dabbrev--abbrev-at-point()
>   dabbrev-capf()
>   completion--capf-wrapper(dabbrev-capf all)
>   completion-at-point()
>   funcall-interactively(completion-at-point)
>   command-execute(completion-at-point)
> 
> Furthermore if no completions are found `dabbrev-capf' signals an error.
> The messages buffer will then contain:
> 
> Scanning for dabbrevs...done
> completion--some: No dynamic expansion for "xyz" found

The patch below fixes the error.

Regarding "No dynamic expansion" error: what did you expect to happen
instead and why?  IOW, what is the expected result of having
dabbrev-capf alone in completion-at-point-functions, and then typing
"x M-TAB"?

diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el
index a4b4d07..deba082 100644
--- a/lisp/dabbrev.el
+++ b/lisp/dabbrev.el
@@ -400,6 +400,8 @@ dabbrev-completion
 
 (defun dabbrev-capf ()
   "Dabbrev completion function for `completion-at-point-functions'."
+  (or (stringp dabbrev--abbrev-char-regexp)
+      (dabbrev--reset-global-variables))
   (let* ((abbrev (dabbrev--abbrev-at-point))
          (beg (progn (search-backward abbrev) (point)))
          (end (progn (search-forward abbrev) (point)))