unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Juri Linkov <juri@linkov.net>
To: Daniel Mendler <mail@daniel-mendler.de>
Cc: 48356@debbugs.gnu.org, Stefan Monnier <monnier@iro.umontreal.ca>,
	JD Smith <jdtsmith@gmail.com>
Subject: bug#48356: 28.0.50; choose-completion discards the suffix after the completion boundary
Date: Sun, 13 Mar 2022 19:56:50 +0200	[thread overview]
Message-ID: <865yoh91nh.fsf@mail.linkov.net> (raw)
In-Reply-To: <18593691-8b7a-facf-68e1-e9d0c106897b@daniel-mendler.de> (Daniel Mendler's message of "Tue, 11 May 2021 19:23:13 +0200")

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

forcemerge 48356 49931
thanks

> When selecting a candidate the suffix after the completion boundary is
> discarded by `choose-completion`/`choose-completion-string`.
> `choose-completion` is invoked when a candidate in the *Completions*
> buffer is selected with the mouse or RET.
>
> For example when completing a file path "~/emacs/master/li|/calc", where
> "|" is the cursor, and then the candidate "lisp" is selected in the
> *Completions* buffer, the result is "~/emacs/master/lisp/". The prefix
> "~/emacs/master/" is prepended to the selected candidate, but the suffix
> "/calc" is discarded.
>
> `choose-completion-string` contains logic which checks if the resulting
> string equals the car of the completion boundary. In that case the
> minibuffer is not exited.

Strange, in your test case above, the minibuffer is not exited already.

> I propose the following change to the existing logic: When
> selecting a candidate with `choose-completion` and a suffix is present,
> the minibuffer should not be exited (completion continues) and the
> suffix is preserved.

Here is a better patch than was posted to bug#49931
to preserve the suffix.

It correctly handles at least three different cases:

1. When manually adding a suffix in the minibuffer after completions
   were displayed, choose-completion discards that suffix.

2. In file name completion in the above case the suffix is preserved.

3. 'M-! command filename TAB' and choosing a completion preserves both
   prefix and suffix.

This works only after customizing 'completion-use-base-affixes' to t:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: completion-base-affixes.patch --]
[-- Type: text/x-diff, Size: 5170 bytes --]

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 36b8d80841..5685f078ad 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2227,6 +2312,8 @@ minibuffer-completion-help
       (let* ((last (last completions))
              (base-size (or (cdr last) 0))
              (prefix (unless (zerop base-size) (substring string 0 base-size)))
+             (base-prefix (buffer-substring (minibuffer--completion-prompt-end) (+ start base-size)))
+             (base-suffix (buffer-substring (point) (point-max)))
              (all-md (completion--metadata (buffer-substring-no-properties
                                             start (point))
                                            base-size md
@@ -2320,11 +2407,18 @@ minibuffer-completion-help
                                    ;; completion-all-completions does not give us the
                                    ;; necessary information.
                                    end))
+                        (setq-local completion-base-affixes (list base-prefix base-suffix))
                         (setq-local completion-list-insert-choice-function
                              (let ((ctable minibuffer-completion-table)
                                    (cpred minibuffer-completion-predicate)
                                    (cprops completion-extra-properties))
                                (lambda (start end choice)
+                                 (if (and (stringp start) (stringp end))
+                                     (progn
+                                       (delete-minibuffer-contents)
+                                       (insert start choice)
+                                       ;; Keep point after completion before suffix
+                                       (save-excursion (insert end)))
                                  (unless (or (zerop (length prefix))
                                              (equal prefix
                                                     (buffer-substring-no-properties
@@ -2333,7 +2427,7 @@ minibuffer-completion-help
                                                      start)))
                                    (message "*Completions* out of date"))
                                  ;; FIXME: Use `md' to do quoting&terminator here.
-                                 (completion--replace start end choice)
+                                 (completion--replace start end choice))
                                  (let* ((minibuffer-completion-table ctable)
                                         (minibuffer-completion-predicate cpred)
                                         (completion-extra-properties cprops)
diff --git a/lisp/simple.el b/lisp/simple.el
index accc119e2b..52cf54c563 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -9071,6 +9075,19 @@ completion-base-position
 where the completion should be inserted and END (if non-nil) is the end
 of the text to replace.  If END is nil, point is used instead.")
 
+(defvar completion-base-affixes nil
+  "Base context of the text corresponding to the shown completions.
+This variable is used in the *Completions* buffers.
+Its value is a list of the form (PREFIX SUFFIX) where PREFIX is the text
+before the place where completion should be inserted and SUFFIX is the text
+after the completion.")
+
+(defcustom completion-use-base-affixes nil
+  "Non-nil means to restore original prefix and suffix in the minibuffer."
+  :type 'boolean
+  :version "29.1"
+  :group 'completion)
+
 (defvar completion-list-insert-choice-function #'completion--replace
   "Function to use to insert the text chosen in *Completions*.
 Called with three arguments (BEG END TEXT), it should replace the text
@@ -9151,6 +9168,7 @@ next-completion
   (with-current-buffer (window-buffer (posn-window (event-start event)))
     (let ((buffer completion-reference-buffer)
           (base-position completion-base-position)
+          (base-affixes completion-base-affixes)
           (insert-function completion-list-insert-choice-function)
           (choice
            (save-excursion
@@ -9184,7 +9203,8 @@ choose-completion
       (with-current-buffer buffer
         (choose-completion-string
          choice buffer
-         (or base-position
+         (or (and completion-use-base-affixes base-affixes)
+             base-position
              ;; If all else fails, just guess.
              (list (choose-completion-guess-base-position choice)))
          insert-function)))))
@@ -9344,9 +9372,11 @@ completion-setup-function
                 (buffer-substring (minibuffer-prompt-end) (point)))))))
     (with-current-buffer standard-output
       (let ((base-position completion-base-position)
+            (base-affixes completion-base-affixes)
             (insert-fun completion-list-insert-choice-function))
         (completion-list-mode)
         (setq-local completion-base-position base-position)
+        (setq-local completion-base-affixes base-affixes)
         (setq-local completion-list-insert-choice-function insert-fun))
       (setq-local completion-reference-buffer mainbuf)
       (if base-dir (setq default-directory base-dir))

  reply	other threads:[~2022-03-13 17:56 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-11 17:23 bug#48356: 28.0.50; choose-completion discards the suffix after the completion boundary Daniel Mendler
2022-03-13 17:56 ` Juri Linkov [this message]
2022-03-13 20:35   ` bug#48356: [External] : " Drew Adams
2022-03-14  3:10 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-03-14 18:53   ` Juri Linkov
2022-03-14 20:55     ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-03-15  2:14       ` Daniel Mendler
2022-03-15  7:53         ` Juri Linkov
2022-03-20 20:34           ` Juri Linkov
2024-04-08 21:59             ` Dmitry Gutov
2024-04-08 22:27               ` Dmitry Gutov
2024-04-08 23:50               ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-10  1:33                 ` Dmitry Gutov
2024-04-10  2:38                   ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-11  1:00                     ` Dmitry Gutov
2024-04-11  6:55                       ` Eli Zaretskii
2024-04-11 10:36                         ` Dmitry Gutov
2024-04-11 21:59                         ` Dmitry Gutov
2024-04-14 16:44                           ` Juri Linkov
2024-04-14 23:55                             ` Dmitry Gutov
2024-04-18 14:25                               ` Spencer Baugh
2024-04-20  0:12                                 ` Dmitry Gutov
2024-05-04  2:23                                   ` Dmitry Gutov
2024-05-09  2:33                                     ` Dmitry Gutov

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

  List information: https://www.gnu.org/software/emacs/

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

  git send-email \
    --in-reply-to=865yoh91nh.fsf@mail.linkov.net \
    --to=juri@linkov.net \
    --cc=48356@debbugs.gnu.org \
    --cc=jdtsmith@gmail.com \
    --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 public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).