GNU bug report logs -
#73880
Master: emacs-lisp-mode: Tab completion for a function position fails in a `let' form.
Previous Next
Reported by: Alan Mackenzie <acm <at> muc.de>
Date: Sat, 19 Oct 2024 13:10:02 UTC
Severity: normal
Done: Dmitry Gutov <dmitry <at> gutov.dev>
Bug is archived. No further changes may be made.
Full log
View this message in rfc822 format
Hello, Dmitry.
On Sat, Oct 26, 2024 at 04:50:15 +0300, Dmitry Gutov wrote:
> Hi Alan!
> Sorry about the late response.
No problem!
> On 20/10/2024 13:54, Alan Mackenzie wrote:
> > Hello, Dmitry and Emacs.
> > On Sat, Oct 19, 2024 at 13:09:00 +0000, Alan Mackenzie wrote:
> >> Hello, Emacs.
> >> In a recent master version, for example this commit:
> >> commit 5340fdaade1f8fe7af08293619cca89ae0796fcf (HEAD -> master, origin/master, origin/HEAD)
> >> Author: Alan Mackenzie <acm <at> muc.de>
> >> Date: Wed Oct 16 13:17:26 2024 +0000
> >> CC Mode: Fix dodgy lisp `let' form.
> >> , start emacs -Q, followed by entering the following incomplete form:
> >> (defun foo ()
> >> (let (
> >> )
> >> (match-b
> >> With point after match-b, type M-TAB. This should complete to
> >> match-beginning or show that function as a completion option. Instead
> >> it signals the error "No match". This is a bug.
> >> It would seem the completion function elisp-completion-at-point thinks
> >> it is completing a variable symbol rather than a function symbol.
> > This is indeed the case. The following patch fixes this by checking
> > that the symbol being completed begins within the binding list. It also
> > adds a test into elisp-mode-tests.el.
> The test looks good, but for the fix itself maybe we could have
> something shorter.
I wasn't happy with the length of my patch, either. But ....
> Could you try the below one-liner? It seems like the problem is the
> (forward-symbol -1) skipping over the empty parens.
Yes.
I haven't tried it out your patch yet, but surely it will fail when there
are comments in the `let' form. For that matter, forward-symbol doesn't
handle comments, either.
> This satisfies the test, at least.
OK.
I've just looked at another form which doesn't work optimally, namely:
`(let (match-b
.. Here a M-TAB ought to signal "No match", but instead offers the two
functions. If the backquote is removed, it works as it should.
elisp-completion-at-point seems to be an approximate function which works
most of the time. To make it work all the time would involve
incorporating a substantial bit of the byte-compiler into it. So I don't
know if it's worth doing that.
But the `(let\*? form is so common (~469 occurrences in Emacs) it might
be worth fixing.
> BTW, I had to move the corresponding piece of code to a separate
> function to debug it. Too bad edebug doesn't know how to jump into the
> 'guard' clauses.
Yes, I had that problem, too. Looking at the edebug spec for pcase, it
seems that guard is meant to be handled, and probably is at the top
level. But inside an `and' or `or' clause, it isn't.
The documentation (on elisp page "Specification List") says that edebug
specs are capable of handling "recursive processing of forms" amongst
other things, so I think it should be possible, though not necessarily
easy. Are you going to raise a bug report for this or should I? ;-)
> diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
> index 2f931daedc7..eab9b2d8ede 100644
> --- a/lisp/progmodes/elisp-mode.el
> +++ b/lisp/progmodes/elisp-mode.el
> @@ -789,7 +789,7 @@ elisp-completion-at-point
> (goto-char (1- beg))
> (when (eq parent ?\()
> (up-list -1))
> - (forward-symbol -1)
> + (skip-syntax-backward " w_")
> (or
> (looking-at
> "\\_<\\(let\\*?\\|bind\\*\\)\\_>")
--
Alan Mackenzie (Nuremberg, Germany).
This bug report was last modified 204 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.