From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Spencer Baugh via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#74019: [PATCH] Optionally preserve selected candidate across *Completions* update Date: Fri, 25 Oct 2024 17:32:38 -0400 Message-ID: Reply-To: Spencer Baugh 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="5068"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Juri Linkov To: 74019@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Fri Oct 25 23:33:45 2024 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 1t4RwG-0001CF-OT for geb-bug-gnu-emacs@m.gmane-mx.org; Fri, 25 Oct 2024 23:33:44 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1t4Rw4-0007cb-57; Fri, 25 Oct 2024 17:33:32 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t4Rw2-0007cR-5M for bug-gnu-emacs@gnu.org; Fri, 25 Oct 2024 17:33:30 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1t4Rw1-00043o-T6 for bug-gnu-emacs@gnu.org; Fri, 25 Oct 2024 17:33:29 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debbugs.gnu.org; s=debbugs-gnu-org; h=MIME-Version:Date:From:To:Subject; bh=1mli0snQQenBepKB2YnHq4maJjMec9FajddGv+5NbPo=; b=p8S8e3RypK9tRFYhBqsNIsQbSTs/m0EYI2Fbu+TJt1BMquWUEtwz8gJ4SK+vdm9KUdlmL0jSKKqgxQEzqEEO/Vgbd8gvwIPXY5zec7+XJG4pRXc3Wi9lNXqbDmbEOCRf5PXsInMTokw4mMlIsuHHwi31eK+y+ZOTYzU42ASUBUnNCbSG6po7i4ahVeBwNr/M1Arlg03PVhYCgyX4uB1vsKeOduUz6w/A6lpb0669R9dI1WhoZedXOFhvehYgfeAMWNQLofbB9rLhB/sQz8A6H3bd+Iut9hzrL8dy+T49mT4yQmu3qTaTEBbTqmADZVuZDo/u9QDCg2s8VhMYcrRhXQ==; Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1t4RwY-00024b-5x for bug-gnu-emacs@gnu.org; Fri, 25 Oct 2024 17:34:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Spencer Baugh Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Fri, 25 Oct 2024 21:34:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 74019 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.17298919997900 (code B ref -1); Fri, 25 Oct 2024 21:34:01 +0000 Original-Received: (at submit) by debbugs.gnu.org; 25 Oct 2024 21:33:19 +0000 Original-Received: from localhost ([127.0.0.1]:39662 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1t4Rvq-00023J-Eb for submit@debbugs.gnu.org; Fri, 25 Oct 2024 17:33:19 -0400 Original-Received: from lists.gnu.org ([209.51.188.17]:49872) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1t4Rvo-000239-72 for submit@debbugs.gnu.org; Fri, 25 Oct 2024 17:33:17 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t4RvG-0007Zq-KJ for bug-gnu-emacs@gnu.org; Fri, 25 Oct 2024 17:32:43 -0400 Original-Received: from mxout5.mail.janestreet.com ([64.215.233.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1t4RvE-00042e-Kh for bug-gnu-emacs@gnu.org; Fri, 25 Oct 2024 17:32:42 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=janestreet.com; s=waixah; t=1729891958; bh=1mli0snQQenBepKB2YnHq4maJjMec9FajddGv+5NbPo=; h=From:To:Cc:Subject:Date; b=RGDb98ItjzhKOG31w6g6FzQGQJ3MMjeQBq9+Er0vjCtBCJnwRZXmypQjWrbqNFQXM Wu4Lynt8LT6LMak0o0DGktAKcNM85YiUkFtuVavsTRipW/M8J61lVqHtwcuNLQaYvB XJobvKjUC2flGFz7UMh36A6dg4cpa4vcJIuhMCPIEq2SO2R/2FW9pZqDWWuym8G6G+ vEsE22DAWZRAXc/YwZDZgr15bR2p80Y4VInOS/HCZiLeTl7Qxp7f7Z7f5tN3AGcPdj JpCtHXcl+sdKlnrC8KEDgbO6ww/tRkvgQwyExHTPOPxZmwt2LVErkmStVsc4Jn1T5l o9jCd32UAJwCg== Received-SPF: pass client-ip=64.215.233.18; envelope-from=sbaugh@janestreet.com; helo=mxout5.mail.janestreet.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:294240 Archived-At: --=-=-= Content-Type: text/plain Tags: patch Add completion-preserve-selection, a defcustom which allows keeping the same selected candidate after *Completions* is updated by minibuffer-completion-help. This works correctly with choose-completion-deselect-if-after: If point is after a completion (such that choose-completion-deselect-if-after=t means it won't be treated as selected), point will still be after that completion after updating the list. This feature is primarily motivated by the fact that some other completion UIs (e.g. ido, vertico, etc) effectively have this behavior: whenever they update the list of completions, they preserve whatever candidate is selected. Since the default UI doesn't (yet) have support for auto-updating the list of completions, preserving the selected candidate is less significant. But it might be an interesting feature on its own, and it's very non-invasive, so maybe we can turn it on by default. In GNU Emacs 29.2.50 (build 5, x86_64-pc-linux-gnu, X toolkit, cairo version 1.15.12, Xaw scroll bars) of 2024-10-15 built on igm-qws-u22796a Repository revision: 16a2e41014c6ea0f3cf268be8d37fe09aeac231e Repository branch: emacs-29 Windowing system distributor 'The X.Org Foundation', version 11.0.12011000 System Description: Rocky Linux 8.10 (Green Obsidian) Configured using: 'configure --with-x-toolkit=lucid --without-gpm --without-gconf --without-selinux --without-imagemagick --with-modules --with-gif=no --with-tree-sitter --with-native-compilation=aot PKG_CONFIG_PATH=/usr/local/home/garnish/libtree-sitter/0.22.6-1/lib/pkgconfig/' --=-=-= Content-Type: text/patch Content-Disposition: attachment; filename=0001-Optionally-preserve-selected-candidate-across-Comple.patch >From 7708bdbc0641c6468aba70662791d9dda043ff88 Mon Sep 17 00:00:00 2001 From: Spencer Baugh Date: Fri, 25 Oct 2024 16:56:30 -0400 Subject: [PATCH] Optionally preserve selected candidate across *Completions* update * lisp/minibuffer.el (completion-preserve-selection): (minibuffer-completion-help): (minibuffer-next-completion): * lisp/simple.el (choose-completion): (completion-setup-function): --- lisp/minibuffer.el | 29 +++++++++++++++++++++++++---- lisp/simple.el | 39 ++++++++++++++++++++++++--------------- 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 44d07557f48..a18f4330514 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2538,6 +2538,16 @@ completions--fit-window-to-buffer (resize-temp-buffer-window win)) (fit-window-to-buffer win completions-max-height))) +(defcustom completion-preserve-selection nil + "If non-nil, `minibuffer-completion-help' preserves the selected completion candidate. + +If non-nil, and point is on a completion candidate in the displayed +*Completions* window, `minibuffer-completion-help' will put point on the +same candidate after updating *Completions*." + :type '(choice (const :tag "Updating *Completions* deselects any completion candidate" t) + (const :tag "Candidates in *Completions* stay selected when the list is updated" nil)) + :version "31.1") + (defcustom completion-auto-deselect t "If non-nil, deselect current completion candidate when you type in minibuffer. @@ -2624,6 +2634,12 @@ minibuffer-completion-help (sort-fun (completion-metadata-get all-md 'display-sort-function)) (group-fun (completion-metadata-get all-md 'group-function)) (mainbuf (current-buffer)) + (current-candidate-and-offset + (when-let* ((window (get-buffer-window "*Completions*" 0))) + (with-selected-window window + (when-let* ((beg (completions--start-of-candidate-at (point)))) + + (cons (get-text-property beg 'completion--string) (- (point) beg)))))) ;; If the *Completions* buffer is shown in a new ;; window, mark it as softly-dedicated, so bury-buffer in ;; minibuffer-hide-completions will know whether to @@ -2647,7 +2663,7 @@ minibuffer-completion-help ,(when temp-buffer-resize-mode '(preserve-size . (nil . t))) (body-function - . ,#'(lambda (_window) + . ,#'(lambda (window) (with-current-buffer mainbuf (when completion-auto-deselect (add-hook 'after-change-functions #'completions--after-change nil t)) @@ -2737,7 +2753,14 @@ minibuffer-completion-help (if (eq (car bounds) (length result)) 'exact 'finished)))))) - (display-completion-list completions nil group-fun))))) + (display-completion-list completions nil group-fun) + (when (and completion-preserve-selection current-candidate-and-offset) + (with-current-buffer standard-output + (when-let* ((match (text-property-search-forward + 'completion--string (car current-candidate-and-offset) t))) + (goto-char (prop-match-beginning match)) + (forward-char (cdr current-candidate-and-offset)) + (set-window-point window (point))))))))) nil))) nil)) @@ -4905,8 +4928,6 @@ minibuffer-next-completion (interactive "p") (let ((auto-choose minibuffer-completion-auto-choose)) (with-minibuffer-completions-window - (when completions-highlight-face - (setq-local cursor-face-highlight-nonselected-window t)) (if vertical (next-line-completion (or n 1)) (next-completion (or n 1))) diff --git a/lisp/simple.el b/lisp/simple.el index 2ffd6e86e56..3a142ef14b3 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -10246,6 +10246,23 @@ choose-completion-deselect-if-after This makes `completions--deselect' effective.") +(defun completions--start-of-candidate-at (position) + "Return the start position of the completion candidate at POSITION." + (save-excursion + (goto-char position) + (let (beg) + (cond + ((and (not (eobp)) + (get-text-property (point) 'completion--string)) + (setq beg (1+ (point)))) + ((and (not (bobp)) + (get-text-property (1- (point)) 'completion--string)) + (setq beg (point)))) + (when beg + (or (previous-single-property-change + beg 'completion--string) + beg))))) + (defun choose-completion (&optional event no-exit no-quit) "Choose the completion at point. If EVENT, use EVENT's position to determine the starting position. @@ -10269,21 +10286,11 @@ choose-completion (or (get-text-property (posn-point (event-start event)) 'completion--string) (error "No completion here")) - (save-excursion - (goto-char (posn-point (event-start event))) - (let (beg) - (cond - ((and (not (eobp)) - (get-text-property (point) 'completion--string)) - (setq beg (1+ (point)))) - ((and (not (bobp)) - (get-text-property (1- (point)) 'completion--string)) - (setq beg (point))) - (t (error "No completion here"))) - (setq beg (or (previous-single-property-change - beg 'completion--string) - beg)) - (get-text-property beg 'completion--string)))))) + (if-let* ((candidate-start + (completions--start-of-candidate-at + (posn-point (event-start event))))) + (get-text-property candidate-start 'completion--string) + (error "No completion here"))))) (unless (buffer-live-p buffer) (error "Destination buffer is dead")) @@ -10451,6 +10458,8 @@ completion-setup-function (let ((base-position completion-base-position) (insert-fun completion-list-insert-choice-function)) (completion-list-mode) + (when completions-highlight-face + (setq-local cursor-face-highlight-nonselected-window t)) (setq-local completion-base-position base-position) (setq-local completion-list-insert-choice-function insert-fun)) (setq-local completion-reference-buffer mainbuf) -- 2.39.3 --=-=-=--