all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Alan Mackenzie <acm@muc.de>
To: 73880@debbugs.gnu.org
Cc: Dmitry Gutov <dmitry@gutov.dev>, acm@muc.de
Subject: bug#73880: Master: emacs-lisp-mode: Tab completion for a function position fails in a `let' form.
Date: Sun, 20 Oct 2024 10:54:22 +0000	[thread overview]
Message-ID: <ZxThXkYlqGuZ17xk@MAC.fritz.box> (raw)
In-Reply-To: <ZxOvbMAB2oW-qCLG@MAC.fritz.box>

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@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.

Dmitry, could you check the patch is OK, please, before I commit it.
Thanks!



diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 2f931daedc7..3233447a996 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -760,7 +760,8 @@ elisp-completion-at-point
                                                (forward-sexp)
                                                (intern-soft
                                                 (buffer-substring pt (point))))))))
-                            (error nil))))
+                            (error nil)))
+                         (parent-end (point)))
                      (pcase parent
                        ;; FIXME: Rather than hardcode special cases here,
                        ;; we should use something like a symbol-property.
@@ -784,18 +785,35 @@ elisp-completion-at-point
                         (list t (elisp--completion-local-symbols)
                               :predicate (lambda (sym)
                                            (get sym 'error-conditions))))
-                       ((and (or ?\( 'let 'let* 'cond 'cond* 'bind*)
-                             (guard (save-excursion
-                                      (goto-char (1- beg))
-                                      (when (eq parent ?\()
-                                        (up-list -1))
-                                      (forward-symbol -1)
-                                      (or
-                                       (looking-at
-                                        "\\_<\\(let\\*?\\|bind\\*\\)\\_>")
-                                       (and (not (eq parent ?\())
+                       ((or
+                         (and (or 'let 'let*)
+                              (guard (save-excursion
+                                       (goto-char parent-end)
+                                       (forward-comment (point-max))
+                                       (let ((bindings-end
+                                              (condition-case nil
+                                                  (progn (forward-list)
+                                                         (point))
+                                                (error (point-max)))))
+                                         (and
+                                          (< beg bindings-end)
+                                          (progn
+                                            (goto-char (1- beg))
+                                            (forward-symbol -1)
                                             (looking-at
-                                             "\\_<cond\\*?\\_>"))))))
+                                             "\\_<let\\*?\\_>")))))))
+                         (and (or ?\( 'cond 'cond* 'bind*)
+                              (guard (save-excursion
+                                       (goto-char (1- beg))
+                                       (when (eq parent ?\()
+                                         (up-list -1))
+                                       (forward-symbol -1)
+                                       (or
+                                        (looking-at
+                                         "\\_<\\(let\\*?\\|bind\\*\\)\\_>")
+                                        (and (not (eq parent ?\())
+                                             (looking-at
+                                              "\\_<cond\\*?\\_>")))))))
                         (list t (elisp--completion-local-symbols)
                               :predicate #'elisp--shorthand-aware-boundp
                               :company-kind (lambda (_) 'variable)
diff --git a/test/lisp/progmodes/elisp-mode-tests.el b/test/lisp/progmodes/elisp-mode-tests.el
index 591c32a8271..45714b3e7d9 100644
--- a/test/lisp/progmodes/elisp-mode-tests.el
+++ b/test/lisp/progmodes/elisp-mode-tests.el
@@ -109,6 +109,14 @@ elisp--test-completions
         (should (member "backup-inhibited" comps))
         (should-not (member "backup-buffer" comps))))))
 
+(ert-deftest elisp-completes-functions-after-empty-let-bindings ()
+  (with-temp-buffer
+    (emacs-lisp-mode)
+    (insert "(let () (ba")
+    (let ((comps (elisp--test-completions)))
+      (should (member "backup-buffer" comps))
+      (should-not (member "backup-inhibited" comps)))))
+
 (ert-deftest elisp-completes-functions-after-let-bindings-2 ()
   (with-temp-buffer
     (emacs-lisp-mode)


-- 
Alan Mackenzie (Nuremberg, Germany).





  reply	other threads:[~2024-10-20 10:54 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-19 13:09 bug#73880: Master: emacs-lisp-mode: Tab completion for a function position fails in a `let' form Alan Mackenzie
2024-10-20 10:54 ` Alan Mackenzie [this message]
2024-10-26  1:50   ` Dmitry Gutov
2024-10-26 14:35     ` Alan Mackenzie
2024-10-27  1:44       ` Dmitry Gutov
2024-10-28 12:12         ` Alan Mackenzie
2024-10-29  0:15           ` Dmitry Gutov
2024-10-26 22:09     ` Alan Mackenzie
2024-10-27  1:29       ` Dmitry Gutov
2024-10-28 11:19         ` Alan Mackenzie

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZxThXkYlqGuZ17xk@MAC.fritz.box \
    --to=acm@muc.de \
    --cc=73880@debbugs.gnu.org \
    --cc=dmitry@gutov.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.