all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Daniel Mendler via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: Eli Zaretskii <eliz@gnu.org>,
	74616@debbugs.gnu.org, Juri Linkov <juri@linkov.net>
Subject: bug#74616: 30.0.92; tmm always displays the *Completions* buffer
Date: Sun, 08 Dec 2024 20:59:06 +0100	[thread overview]
Message-ID: <87jzca2bg5.fsf@daniel-mendler.de> (raw)
In-Reply-To: <jwved2i8a4b.fsf-monnier+emacs@gnu.org> (Stefan Monnier's message of "Sun, 08 Dec 2024 10:33:53 -0500")

[-- Attachment #1: Type: text/plain, Size: 1483 bytes --]

Stefan Monnier <monnier@iro.umontreal.ca> writes:

>> So is the plan to add a completion metadata `eager-display' such that
>> completion tables can request immediate display? This completion
>> metadata can then be overridden by the user via
>> `completion-category-overrides'. The patch would include changes to tmm,
>> ffap-menu and imenu (obsoleting `imenu-eager-completion-buffer').
>
> That sounds good, except that in order for
> `completion-category-overrides` to work reliably, the `eager-display`
> should not be in the metadata but in `completion-category-defaults`.

Okay. Can you please clarify why you assume that overriding isn't
reliably possible if the metadata is specified directly? In
`completion-metadata-get' the `completion-category-defaults' and
`completion-category-overrides' take precedence over the completion
table metadata.

I attached a patch which adds a customization option
`completion-eager-display' and an `eager-display' completion table
metadata. The customization option can be set to nil (never), t (always)
or to auto, which means that the *Completions* buffer will only be shown
if the completion table requests eager display via the `eager-display'
metadata.

I updated ffap.el, tmm.el and imenu.el to take advantage of the new
`eager-display' metadata. I added completion categories where missing
such that overriding the metadata becomes possible. If desired, the
metadata can be moved to `completion-category-defaults' instead.

Daniel


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-New-customization-variable-completion-eager-display.patch --]
[-- Type: text/x-diff, Size: 14047 bytes --]

From 2a4f2c04a880c6a66207a0717f5ba79bbfe109ef Mon Sep 17 00:00:00 2001
From: Daniel Mendler <mail@daniel-mendler.de>
Date: Sun, 8 Dec 2024 20:05:07 +0100
Subject: [PATCH] New customization variable `completion-eager-display'

The customization option can be set to t or nil, to respectively
always or never show the *Completions* buffer eagerly at the
beginning of a completion session.  Furthermore the option can
be set to the value auto.  In this case the *Completions* buffer
will only be shown if requested by the completion table.
Completion tables can use the `eager-display' completion
metadata to do so.

* lisp/minibuffer.el (completion-eager-display): New
customization variable.
(completion-metadata): Update docstring, document the
new `eager-display' completion metadata.
(completion-extra-properties): Update docstring, document the
new `:eager-display' completion metadata.
(completing-read-default): Handle the `completion-eager-display'
customization variable and the `eager-display' completion
metadata.
(completion-table-with-metadata): New function to create
a completion table with metadata.
(minibuffer-complete-defaults, minibuffer-complete-history):
Use it.
* lisp/ffap.el (ffap-menu-ask): Add `ffap-menu' completion
category and `eager-display' completion metadata.  Use
`completion-table-with-metadata'.
* lisp/imenu.el (imenu-eager-completion-buffer): Correct
docstring, which had been inverted.
(imenu--completion-buffer): Add `eager-display' completion
metadata.  Use `completion-table-with-metadata'.
* lisp/tmm.el (tmm-prompt): Add `tmm' completion category and
`eager-display' completion metadata.  Use
`completion-table-with-metadata'.
(tmm-goto-completions): Ensure that a *Completions* buffer is
available.
(tmm--completion-table): Remove unused internal function.
---
 lisp/ffap.el       | 17 ++++++++-------
 lisp/imenu.el      | 40 ++++++++++++++++------------------
 lisp/minibuffer.el | 54 ++++++++++++++++++++++++++++++++++++----------
 lisp/tmm.el        | 38 ++++++++++++++++----------------
 4 files changed, 90 insertions(+), 59 deletions(-)

diff --git a/lisp/ffap.el b/lisp/ffap.el
index 6a4915fb5a3..c869e234140 100644
--- a/lisp/ffap.el
+++ b/lisp/ffap.el
@@ -1738,14 +1738,15 @@ ffap-menu-ask
 				    alist))))))
      ;; minibuffer with completion buffer:
      (t
-      (let ((minibuffer-setup-hook 'minibuffer-completion-help))
-	;; Bug: prompting may assume unique strings, no "".
-	(setq choice
-	      (completing-read
-	       (format-prompt title (car (car alist)))
-	       alist nil t
-	       ;; (cons (car (car alist)) 0)
-	       nil)))
+      ;; Bug: prompting may assume unique strings, no "".
+      (setq choice
+	    (completing-read
+	     (format-prompt title (car (car alist)))
+             (completion-table-with-metadata
+	      alist '((category . ffap-menu) (eager-display . t)))
+             nil t
+	     ;; (cons (car (car alist)) 0)
+	     nil))
       (sit-for 0)			; redraw original screen
       ;; Convert string to its entry, or else the default:
       (setq choice (or (assoc choice alist) (car alist)))))
diff --git a/lisp/imenu.el b/lisp/imenu.el
index 2d64970bfcf..ba1ba5fcd00 100644
--- a/lisp/imenu.el
+++ b/lisp/imenu.el
@@ -100,7 +100,7 @@ imenu-use-popup-menu
                  (other :tag "Always" t)))
 
 (defcustom imenu-eager-completion-buffer t
-  "If non-nil, eagerly pop up the completion buffer."
+  "If nil, eagerly pop up the completion buffer."
   :type 'boolean
   :version "22.1")
 
@@ -767,27 +767,25 @@ imenu--completion-buffer
                          (imenu--in-alist name prepared-index-alist)
                          ;; Default to `name' if it's in the alist.
                          name))))
-    ;; Display the completion buffer.
     (minibuffer-with-setup-hook
-        (lambda ()
-          (setq-local minibuffer-allow-text-properties t)
-          (setq-local completion-extra-properties
-                      `( :category imenu
-                         ,@(when (eq imenu-flatten 'annotation)
-                             `(:annotation-function
-                               ,(lambda (s) (get-text-property
-                                             0 'imenu-section s))))
-                         ,@(when (eq imenu-flatten 'group)
-                             `(:group-function
-                               ,(lambda (s transform)
-                                  (if transform s
-                                    (get-text-property
-                                     0 'imenu-section s)))))))
-          (unless imenu-eager-completion-buffer
-            (minibuffer-completion-help)))
-      (setq name (completing-read prompt
-				  prepared-index-alist
-				  nil t nil 'imenu--history-list name)))
+        (lambda () (setq-local minibuffer-allow-text-properties t))
+      (setq name (completing-read
+                  prompt
+                  (completion-table-with-metadata
+		   prepared-index-alist
+                   `((category . imenu)
+                     (eager-display . ,(not imenu-eager-completion-buffer))
+                     ,@(when (eq imenu-flatten 'annotation)
+                         `((annotation-function
+                            . ,(lambda (s) (get-text-property
+                                            0 'imenu-section s)))))
+                     ,@(when (eq imenu-flatten 'group)
+                         `((group-function
+                            . ,(lambda (s transform)
+                                 (if transform s
+                                   (get-text-property
+                                    0 'imenu-section s))))))))
+		  nil t nil 'imenu--history-list name)))
 
     (when (stringp name)
       (or (get-text-property 0 'imenu-choice name)
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 405ee21cdb2..1dfe450a35c 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -138,6 +138,9 @@ completion-metadata
    of completions.  Can operate destructively.
 - `cycle-sort-function': function to sort entries when cycling.
    Works like `display-sort-function'.
+- `eager-display': non-nil to request eager display of the
+  completion candidates.  Can also be a function which is invoked
+  after minibuffer setup.
 The metadata of a completion table should be constant between two boundaries."
   (let ((metadata (if (functionp table)
                       (funcall table string pred 'metadata))))
@@ -277,6 +280,15 @@ completion-table-case-fold
     (let ((completion-ignore-case (not dont-fold)))
       (complete-with-action action table string pred))))
 
+(defun completion-table-with-metadata (table metadata)
+  "Return new completion TABLE with METADATA.
+METADATA should be an alist of completion metadata.  See
+`completion-metadata' for a list of supported metadata."
+  (lambda (string pred action)
+    (if (eq action 'metadata)
+        `(metadata . ,metadata)
+      (complete-with-action action table string pred))))
+
 (defun completion-table-subvert (table s1 s2)
   "Return a completion table from TABLE with S1 replaced by S2.
 The result is a completion table which completes strings of the
@@ -1031,6 +1043,18 @@ minibuffer--completion-prompt-end
 (defvar completion-show-inline-help t
   "If non-nil, print helpful inline messages during completion.")
 
+(defcustom completion-eager-display 'auto
+  "Display the *Completions* buffer eagerly.
+
+If the variable is set to t or nil, respectively show the *Completions*
+buffer always or never eagerly.  The value `auto' shows the
+*Completions* buffer eagerly only if requested by the completion
+command.  Completion tables can request eager display via the
+`eager-display' metadata."
+  :type '(choice (const :tag "Never show *Completions* eagerly" nil)
+                 (const :tag "Always show *Completions* eagerly" t)
+                 (const :tag "If requested by the completion command" auto)))
+
 (defcustom completion-auto-help t
   "Non-nil means automatically provide help for invalid completion input.
 If the value is t, the *Completions* buffer is displayed whenever completion
@@ -2493,6 +2517,8 @@ completion-extra-properties
 
 `:cycle-sort-function': Function to sort entries when cycling.
 
+`:eager-display': Show the *Completions* buffer eagerly.
+
 See more information about these functions above
 in `completion-metadata'.
 
@@ -4809,7 +4835,17 @@ completing-read-default
                 (setq-local minibuffer--require-match require-match)
                 (setq-local minibuffer--original-buffer buffer)
                 ;; Copy the value from original buffer to the minibuffer.
-                (setq-local completion-ignore-case c-i-c))
+                (setq-local completion-ignore-case c-i-c)
+                ;; Show the completion help eagerly if
+                ;; `completion-eager-display' is t or if eager display
+                ;; has been requested by the completion table.
+                (when completion-eager-display
+                  (let* ((md (completion-metadata
+                              initial-input collection predicate))
+                         (fun (completion-metadata-get md 'eager-display)))
+                    (when (or fun (eq completion-eager-display t))
+                      (funcall (if (functionp fun)
+                                   fun #'minibuffer-completion-help))))))
             (read-from-minibuffer prompt initial-input keymap
                                   nil hist def inherit-input-method))))
     (when (and (equal result "") def)
@@ -4999,11 +5035,9 @@ minibuffer-complete-history
            (lambda () (get-buffer-window "*Completions*" 0))))
       (completion-in-region
        (minibuffer--completion-prompt-end) (point-max)
-       (lambda (string pred action)
-         (if (eq action 'metadata)
-             '(metadata (display-sort-function . identity)
-                        (cycle-sort-function . identity))
-           (complete-with-action action completions string pred)))))))
+       (completion-table-with-metadata
+        completions '((display-sort-function . identity)
+                      (cycle-sort-function . identity)))))))
 
 (defun minibuffer-complete-defaults ()
   "Complete minibuffer defaults as far as possible.
@@ -5019,11 +5053,9 @@ minibuffer-complete-defaults
          (lambda () (get-buffer-window "*Completions*" 0))))
     (completion-in-region
      (minibuffer--completion-prompt-end) (point-max)
-     (lambda (string pred action)
-       (if (eq action 'metadata)
-           '(metadata (display-sort-function . identity)
-                      (cycle-sort-function . identity))
-         (complete-with-action action completions string pred))))))
+     (completion-table-with-metadata
+      completions '((display-sort-function . identity)
+                    (cycle-sort-function . identity))))))
 
 (define-key minibuffer-local-map [?\C-x up] 'minibuffer-complete-history)
 (define-key minibuffer-local-map [?\C-x down] 'minibuffer-complete-defaults)
diff --git a/lisp/tmm.el b/lisp/tmm.el
index 632e55e47a8..01912916a6d 100644
--- a/lisp/tmm.el
+++ b/lisp/tmm.el
@@ -119,12 +119,6 @@ tmm-inactive
   '((t :inherit shadow))
   "Face used for inactive menu items.")
 
-(defun tmm--completion-table (items)
-  (lambda (string pred action)
-    (if (eq action 'metadata)
-	'(metadata (display-sort-function . identity))
-      (complete-with-action action items string pred))))
-
 (defvar tmm--history nil)
 
 ;;;###autoload
@@ -222,19 +216,23 @@ tmm-prompt
              (setq out
                    (if default-item
                        (car (nth index-of-default tmm-km-list))
-                     (minibuffer-with-setup-hook #'tmm-add-prompt
-                       ;; tmm-km-list is reversed, because history
-                       ;; needs it in LIFO order.  But default list
-                       ;; needs it in non-reverse order, so that the
-                       ;; menu items are displayed by M-n as default
-                       ;; values in the order they are shown on
-                       ;; the menu bar.  So pass the DEFAULT arg the
-                       ;; reversed copy of the list.
-                       (completing-read-default
-                        (concat gl-str
-                                " (up/down to change, PgUp to menu): ")
-                        (tmm--completion-table tmm-km-list) nil t nil
-                        'tmm--history (reverse tmm--history)))))))
+                     ;; tmm-km-list is reversed, because history
+                     ;; needs it in LIFO order.  But default list
+                     ;; needs it in non-reverse order, so that the
+                     ;; menu items are displayed by M-n as default
+                     ;; values in the order they are shown on
+                     ;; the menu bar.  So pass the DEFAULT arg the
+                     ;; reversed copy of the list.
+                     (completing-read-default
+                      (concat gl-str
+                              " (up/down to change, PgUp to menu): ")
+                      (completion-table-with-metadata
+                       tmm-km-list '((category . tmm)
+                                     (eager-display . tmm-add-prompt)
+                                     (display-sort-function . identity)
+                                     (cycle-sort-function . identity)))
+                      nil t nil
+                      'tmm--history (reverse tmm--history))))))
       (if (and (stringp out) (string= "^" out))
           ;; A fake choice to please the destructuring later.
           (setq choice (cons out out))
@@ -458,6 +456,8 @@ tmm-shortcut
 (defun tmm-goto-completions ()
   "Jump to the completions buffer."
   (interactive)
+  (unless (get-buffer "*Completions*")
+    (minibuffer-completion-help))
   (setq tmm-c-prompt (buffer-substring (minibuffer-prompt-end) (point-max)))
   ;; Clear minibuffer old contents before using *Completions* buffer for
   ;; selection.
-- 
2.45.2


  reply	other threads:[~2024-12-08 19:59 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-30  6:42 bug#74616: 30.0.92; tmm always displays the *Completions* buffer Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-11-30  8:04 ` Eli Zaretskii
2024-11-30  8:12   ` Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-11-30 18:55   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-01  4:00     ` Sean Whitton
2024-12-07 12:55     ` Eli Zaretskii
2024-12-07 14:38       ` Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-08  7:17         ` Eli Zaretskii
2024-12-08  7:49           ` Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-08 15:33         ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-08 19:59           ` Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors [this message]
2024-12-09 14:19             ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-09 14:44               ` Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-09 15:25                 ` Eli Zaretskii
2024-12-09 15:42                   ` Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-09 19:03             ` Juri Linkov
2024-12-09 19:28               ` Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-09 20:06                 ` Eli Zaretskii
2024-12-09 20:12                   ` Eli Zaretskii
2024-12-09 19:52               ` Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-09 20:08                 ` Eli Zaretskii
2024-12-09 20:32                   ` Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-10 12:32                     ` Eli Zaretskii
2024-12-11 15:37                       ` Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-14 10:31                         ` Eli Zaretskii
2024-12-14 11:44                           ` Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-14 12:40                             ` Eli Zaretskii
2024-12-15  7:44                             ` Juri Linkov
2024-12-15 10:02                               ` Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-15 15:29                                 ` Daniel Mendler via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-15 23:04                                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-12-10  7:43                 ` Juri Linkov

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=87jzca2bg5.fsf@daniel-mendler.de \
    --to=bug-gnu-emacs@gnu.org \
    --cc=74616@debbugs.gnu.org \
    --cc=eliz@gnu.org \
    --cc=juri@linkov.net \
    --cc=mail@daniel-mendler.de \
    --cc=monnier@iro.umontreal.ca \
    /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.