From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Philip Kaludercic Newsgroups: gmane.emacs.devel Subject: Re: Suggestions for improvements to the *Completions* buffer Date: Sat, 18 Dec 2021 12:22:10 +0000 Message-ID: <87pmpurtl9.fsf@posteo.net> References: <87czlv1nes.fsf@posteo.net> 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="9064"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel@gnu.org To: Juri Linkov Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sat Dec 18 13:23:12 2021 Return-path: Envelope-to: ged-emacs-devel@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 1myYk4-0002At-2W for ged-emacs-devel@m.gmane-mx.org; Sat, 18 Dec 2021 13:23:12 +0100 Original-Received: from localhost ([::1]:52874 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1myYk2-0006Bh-TB for ged-emacs-devel@m.gmane-mx.org; Sat, 18 Dec 2021 07:23:10 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:44706) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1myYjC-0005On-QU for emacs-devel@gnu.org; Sat, 18 Dec 2021 07:22:19 -0500 Original-Received: from mout02.posteo.de ([185.67.36.66]:58443) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1myYj9-0007ek-Dh for emacs-devel@gnu.org; Sat, 18 Dec 2021 07:22:18 -0500 Original-Received: from submission (posteo.de [89.146.220.130]) by mout02.posteo.de (Postfix) with ESMTPS id 1E7C3240101 for ; Sat, 18 Dec 2021 13:22:12 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.net; s=2017; t=1639830132; bh=oMOrbjJ1IBBidHQgOc9IlDle40yenEVtTJmRrsTCZ34=; h=From:To:Cc:Subject:Autocrypt:Date:From; b=njBZxWkkjGQbHMJqgRI8gTSESsIpwk2124ZFc/T/p9VqTeyU082YyigF2eolQkyR1 PI9JAFXMEOe5qXsNyn6mRxuK1hyUz2blpdA+QevEHUAvon5uA6VmbX7Ig8k0D3ELUb +/YFE3SV/reVku7P/CFKr4RZI31Lfs7KIv/D6WcJpkNdlEvwtW3QDhZEE+utXQr8fZ yM1rPka/A5JMkaCnmr4FzL5sntfIBwMGIg6p2VyRbefTF6NxQ5G2NvV9TWrHu24SMO HpoP79B5TeMJovscl2m/zXLB8rNPJDdyO3WSUJuw/vLLKoR5ZHjKqtEa4rTvkocy86 ImGc0xDzU2o9A== Original-Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4JGQ2q2y5Vz6tm5; Sat, 18 Dec 2021 13:22:11 +0100 (CET) FrReferences: <87a6h9g0c0.fsf@posteo.net> <87zgp45gri.fsf@posteo.net> <865yrr300t.fsf@mail.linkov.net> <87czlv1nes.fsf@posteo.net> om: Philip Kaludercic Autocrypt: addr=philipk@posteo.net; prefer-encrypt=nopreference; keydata= mDMEYHHqUhYJKwYBBAHaRw8BAQdAp3GdmYJ6tm5McweY6dEvIYIiry+Oz9rU4MH6NHWK0Ee0QlBo aWxpcCBLYWx1ZGVyY2ljIChnZW5lcmF0ZWQgYnkgYXV0b2NyeXB0LmVsKSA8cGhpbGlwa0Bwb3N0 ZW8ubmV0PoiQBBMWCAA4FiEEDM2H44ZoPt9Ms0eHtVrAHPRh1FwFAmBx6lICGwMFCwkIBwIGFQoJ CAsCBBYCAwECHgECF4AACgkQtVrAHPRh1FyTkgEAjlbGPxFchvMbxzAES3r8QLuZgCxeAXunM9gh io0ePtUBALVhh9G6wIoZhl0gUCbQpoN/UJHI08Gm1qDob5zDxnIHuDgEYHHqUhIKKwYBBAGXVQEF AQEHQNcRB+MUimTMqoxxMMUERpOR+Q4b1KgncDZkhrO2ql1tAwEIB4h4BBgWCAAgFiEEDM2H44Zo Pt9Ms0eHtVrAHPRh1FwFAmBx6lICGwwACgkQtVrAHPRh1Fw1JwD/Qo7kvtib8jy7puyWrSv0MeTS g8qIxgoRWJE/KKdkCLEA/jb9b9/g8nnX+UcwHf/4VfKsjExlnND3FrBviXUW6NcB In-Reply-To: <87czlv1nes.fsf@posteo.net> (Philip Kaludercic's message of "Fri, 17 Dec 2021 11:27:55 +0000") Received-SPF: pass client-ip=185.67.36.66; envelope-from=philipk@posteo.net; helo=mout02.posteo.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:282287 Archived-At: --=-=-= Content-Type: text/plain Philip Kaludercic writes: >>> The question is whether or not there is a need for a separate >>> switch-to-minibuffer binding (besides M-g M-c)? Is keeping the >>> completions buffer active while returning to the minibuffer a real need? >> >> Good question. If four key bindings (q, z, C-g, ESC ESC ESC) >> all will close the completions (first two using quit-window, >> and last two using delete-completion-window), then maybe we should have >> an easy-to-type keybinding that will switch to the minibuffer without >> closing the completions window? >> >> There is an easy-to-type keys and M-v to switch to the >> completions window, but no an easy-to-type key to switch back. >> >> It seems wrong for `q' to switch to the minibuffer without closing >> the window because `quit-window' implies that window should quit. >> But what key to use instead, I have no idea. > > Or to take inspiration from Protesilaos's MCT package, that switches > back to the minibuffer once next-completion and previous-completion > reaches the end/beginning of the buffer, without quitting the window. > With next-completion bound to TAB while TAB also jumps back to the > completion buffer, it would behave to just by cycling. Here are the patches that would implement this behaviour. I have to use it for a bit longer before I can say if it is preferable, but I guess if something along these lines were to be applied, this could be an option. The mechanism used to make backtab in the minibuffer switch to the last completion option is not that nice as it uses this-command and this-command-keys. --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0001-Allow-for-the-completion-buffer-to-be-automatically-.patch >From 0cc155ee3395fab376b06838a79c9a8b6fee6378 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Thu, 9 Dec 2021 17:34:54 +0100 Subject: [PATCH 1/3] Allow for the completion buffer to be automatically selected * lisp/simple.el (completion-auto-select): Add new option. (completion-setup-function): Respect completion-auto-select. --- lisp/simple.el | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lisp/simple.el b/lisp/simple.el index 84928caa31..213720784c 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -9226,6 +9226,12 @@ completion-show-help :version "22.1" :group 'completion) +(defcustom completion-auto-select t + "Non-nil means to automatically select the completions buffer." + :type 'boolean + :version "29.1" + :group 'completion) + ;; This function goes in completion-setup-hook, so that it is called ;; after the text of the completion list buffer is written. (defun completion-setup-function () @@ -9262,7 +9268,9 @@ completion-setup-function (insert "Click on a completion to select it.\n")) (insert (substitute-command-keys "In this buffer, type \\[choose-completion] to \ -select the completion near point.\n\n")))))) +select the completion near point.\n\n"))))) + (when completion-auto-select + (switch-to-completions))) (add-hook 'completion-setup-hook #'completion-setup-function) -- 2.30.2 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0002-Allow-for-next-completion-to-wrap-around-the-complet.patch >From 1b53b0c60c830c5e9173f143e4ed7e4719288ec9 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Thu, 9 Dec 2021 17:26:14 +0100 Subject: [PATCH 2/3] Allow for next-completion to wrap around the completion buffer * lisp/simple.el (completion-wrap-movement): Add new option. (previous-completion): Update docstring. (next-completion): Respect completion-wrap-movement. (switch-to-completions): Handle backwards completion by jumping to the end of the buffer. * lisp/minibuffer.el: (minibuffer-local-completion-map): Bind minibuffer-complete to backtab --- lisp/minibuffer.el | 1 + lisp/simple.el | 81 ++++++++++++++++++++++++++++++---------------- 2 files changed, 54 insertions(+), 28 deletions(-) diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 28bd1df59a..5f831665eb 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2651,6 +2651,7 @@ minibuffer-local-completion-map (let ((map (make-sparse-keymap))) (set-keymap-parent map minibuffer-local-map) (define-key map "\t" 'minibuffer-complete) + (define-key map [backtab] 'minibuffer-complete) ;; M-TAB is already abused for many other purposes, so we should find ;; another binding for it. ;; (define-key map "\e\t" 'minibuffer-force-complete) diff --git a/lisp/simple.el b/lisp/simple.el index 213720784c..6a7d7ba918 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -9027,38 +9027,57 @@ delete-completion-window (if (get-buffer-window buf) (select-window (get-buffer-window buf)))))) +(defcustom completion-wrap-movement t + "Non-nil means to wrap around when selecting completion options. +This affects the commands `next-completion' and +`previous-completion'." + :type 'boolean + :version "29.1" + :group 'completion) + (defun previous-completion (n) - "Move to the previous item in the completion list." + "Move to the previous item in the completion list. +With prefix argument N, move back N items (negative N means move +forward)." (interactive "p") (next-completion (- n))) (defun next-completion (n) "Move to the next item in the completion list. -With prefix argument N, move N items (negative N means move backward)." +With prefix argument N, move N items (negative N means move +backward)." (interactive "p") (let ((beg (point-min)) (end (point-max))) - (while (and (> n 0) (not (eobp))) - ;; If in a completion, move to the end of it. - (when (get-text-property (point) 'mouse-face) - (goto-char (next-single-property-change (point) 'mouse-face nil end))) - ;; Move to start of next one. - (unless (get-text-property (point) 'mouse-face) - (goto-char (next-single-property-change (point) 'mouse-face nil end))) - (setq n (1- n))) - (while (and (< n 0) (not (bobp))) - (let ((prop (get-text-property (1- (point)) 'mouse-face))) - ;; If in a completion, move to the start of it. - (when (and prop (eq prop (get-text-property (point) 'mouse-face))) - (goto-char (previous-single-property-change - (point) 'mouse-face nil beg))) - ;; Move to end of the previous completion. - (unless (or (bobp) (get-text-property (1- (point)) 'mouse-face)) - (goto-char (previous-single-property-change - (point) 'mouse-face nil beg))) - ;; Move to the start of that one. - (goto-char (previous-single-property-change - (point) 'mouse-face nil beg)) - (setq n (1+ n)))))) + (catch 'bound + (while (> n 0) + ;; If in a completion, move to the end of it. + (when (get-text-property (point) 'mouse-face) + (goto-char (next-single-property-change (point) 'mouse-face nil end))) + (when (and completion-wrap-movement (eobp)) + (throw 'bound nil)) + ;; Move to start of next one. + (unless (get-text-property (point) 'mouse-face) + (goto-char (next-single-property-change (point) 'mouse-face nil end))) + (setq n (1- n))) + (while (< n 0) + (let ((prop (get-text-property (1- (point)) 'mouse-face))) + ;; If in a completion, move to the start of it. + (when (and prop (eq prop (get-text-property (point) 'mouse-face))) + (goto-char (previous-single-property-change + (point) 'mouse-face nil beg))) + ;; Move to end of the previous completion. + (unless (or (bobp) (get-text-property (1- (point)) 'mouse-face)) + (goto-char (previous-single-property-change + (point) 'mouse-face nil beg))) + (when (and completion-wrap-movement (bobp)) + (goto-char (next-single-property-change (point) 'mouse-face nil end)) + (throw 'bound nil)) + ;; Move to the start of that one. + (goto-char (previous-single-property-change + (point) 'mouse-face nil beg)) + (setq n (1+ n))))) + (when (/= 0 n) + (switch-to-minibuffer)))) (defun choose-completion (&optional event) "Choose the completion at point. @@ -9283,10 +9302,16 @@ switch-to-completions (get-buffer-window "*Completions*" 0))))) (when window (select-window window) - ;; In the new buffer, go to the first completion. - ;; FIXME: Perhaps this should be done in `minibuffer-completion-help'. - (when (bobp) - (next-completion 1))))) + (cond + ((and (memq this-command '(completion-at-point minibuffer-complete)) + (equal (this-command-keys) [backtab]) + (bobp)) + (goto-char (point-max)) + (previous-completion 1)) + ;; In the new buffer, go to the first completion. + ;; FIXME: Perhaps this should be done in `minibuffer-completion-help'. + ((bobp) + (next-completion 1)))))) (defun read-expression-switch-to-completions () "Select the completion list window while reading an expression." -- 2.30.2 --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0003-Switch-back-to-minibuffer-when-quitting-completion-b.patch >From 1612aa4f9a5c1d4afa9e0d97b959c9623c400ce2 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Thu, 9 Dec 2021 17:36:14 +0100 Subject: [PATCH 3/3] Switch back to minibuffer when quitting completion buffer * lisp/simple.el (completion-quit): Add new command (completion-kill-buffer): Add new command (completion-list-mode-map): Bind completion-quit and rebind kill-current-buffer to completion-kill-buffer --- lisp/simple.el | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lisp/simple.el b/lisp/simple.el index 6a7d7ba918..c9ddca7b0a 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -8971,6 +8971,19 @@ set-variable ;; Define the major mode for lists of completions. +(defun completion-quit () + "Close the completion buffer and return to the minibuffer." + (interactive) + (quit-window) + (switch-to-minibuffer)) + +(defun completion-kill-buffer () + "Close the completion buffer and return to the minibuffer." + (interactive) + (let ((win (get-buffer-window "*Completions*"))) + (when win (quit-window t win))) + (switch-to-minibuffer)) + (defvar completion-list-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map special-mode-map) @@ -8984,10 +8997,12 @@ completion-list-mode-map (define-key map [right] 'next-completion) (define-key map [?\t] 'next-completion) (define-key map [backtab] 'previous-completion) - (define-key map "z" 'kill-current-buffer) (define-key map "n" 'next-completion) (define-key map "p" 'previous-completion) (define-key map "\M-g\M-c" 'switch-to-minibuffer) + (define-key map "z" #'completion-kill-buffer) + (define-key map [remap keyboard-quit] #'delete-completion-window) + (define-key map [remap quit-window] #'completion-quit) map) "Local map for completion list buffers.") -- 2.30.2 --=-=-= Content-Type: text/plain -- Philip Kaludercic --=-=-=--