From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Juri Linkov Newsgroups: gmane.emacs.bugs Subject: bug#48356: 28.0.50; choose-completion discards the suffix after the completion boundary Date: Sun, 13 Mar 2022 19:56:50 +0200 Organization: LINKOV.NET Message-ID: <865yoh91nh.fsf@mail.linkov.net> References: <18593691-8b7a-facf-68e1-e9d0c106897b@daniel-mendler.de> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="22272"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (x86_64-pc-linux-gnu) Cc: 48356@debbugs.gnu.org, Stefan Monnier , JD Smith To: Daniel Mendler Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sun Mar 13 19:15:53 2022 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nTSky-0005gF-8Q for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 13 Mar 2022 19:15:52 +0100 Original-Received: from localhost ([::1]:45252 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nTSkw-0001wU-VZ for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 13 Mar 2022 14:15:51 -0400 Original-Received: from eggs.gnu.org ([209.51.188.92]:59882) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nTSjD-0008Df-Jj for bug-gnu-emacs@gnu.org; Sun, 13 Mar 2022 14:14:03 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:49368) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nTSjD-0001H8-7E for bug-gnu-emacs@gnu.org; Sun, 13 Mar 2022 14:14:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1nTSjD-00067Y-39 for bug-gnu-emacs@gnu.org; Sun, 13 Mar 2022 14:14:03 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Juri Linkov Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 13 Mar 2022 18:14:03 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 48356 X-GNU-PR-Package: emacs Original-Received: via spool by 48356-submit@debbugs.gnu.org id=B48356.164719523123471 (code B ref 48356); Sun, 13 Mar 2022 18:14:03 +0000 Original-Received: (at 48356) by debbugs.gnu.org; 13 Mar 2022 18:13:51 +0000 Original-Received: from localhost ([127.0.0.1]:43260 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nTSj1-00066V-BG for submit@debbugs.gnu.org; Sun, 13 Mar 2022 14:13:51 -0400 Original-Received: from relay5-d.mail.gandi.net ([217.70.183.197]:51379) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nTSj0-00066B-7O; Sun, 13 Mar 2022 14:13:51 -0400 Original-Received: (Authenticated sender: juri@linkov.net) by mail.gandi.net (Postfix) with ESMTPSA id 7BA581C0004; Sun, 13 Mar 2022 18:13:41 +0000 (UTC) In-Reply-To: <18593691-8b7a-facf-68e1-e9d0c106897b@daniel-mendler.de> (Daniel Mendler's message of "Tue, 11 May 2021 19:23:13 +0200") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:228303 Archived-At: --=-=-= Content-Type: text/plain 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: --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=completion-base-affixes.patch 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)) --=-=-=--