Subject: Re: bug#47699: [PATCH] Improve completion-list-mode-map

From: Gregory Heytings <[email-masked]>
Date: Tue, 25 May 2021 07:32:49 +0000

>> Thanks.  Here is the updated patch.  I tested it with minibuffer-only 
>> frames, and it seems to work.
>>
>> Are you sure that it's okay to rebind M-c in 
>> minibuffer-local-completion-map?  It's a good mnemonic for 
>> "completion", but it hides the capitalize-word binding, that users 
>> might possibly want to use there (I don't, it's only when thinking 
>> about this patch that I realized this).
>>
>> Another option would be M-g, which would not hide anything that is 
>> possibly useful in the minibuffer, and is still a mnemonic of "goto".
>
> Thanks; applied to Emacs 28.
>
> I went with `M-g' -- it seems pretty natural here.  If anybody else 
> wants a different key binding, go ahead and change it.
>

Juri said recently that he uses some of the keys in M-g in the minibuffer, 
so I changed my mind, and I now think that it would be better to use 'M-g 
M-c' for this, which is unused, and does not hide the complete M-g map. 
Updated patch attached.  WDYT?

From 4d6a33038e820c6043d71635fee241951229241e Mon Sep 17 00:00:00 2001
From: Gregory Heytings <[email-masked]>
Date: Tue, 25 May 2021 07:19:41 +0000
Subject: [PATCH] Switch between minibuffer and *Completions*

* lisp/simple.el (completion-list-mode-map): Make special-mode-map its
parent, unbind the 'g' revert key, bind the 'n' and 'p' keys to
next-completion and previous-completion, and the M-g M-c key to
switch-to-minibuffer.
(read-expression-map): Bind M-g M-c to read-expression-switch-to-completions.
(switch-to-minibuffer, read-expression-switch-to-completions): New
functions.

* lisp/minibuffer.el (minibuffer-local-completion-map): Bind the M-g M-c
key to switch-to-completion.

* doc/emacs/windows.texi (Temporary Displays): Document the change.
---
 doc/emacs/windows.texi |  8 +++++---
 lisp/minibuffer.el     |  1 +
 lisp/simple.el         | 18 ++++++++++++++++++
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/doc/emacs/windows.texi b/doc/emacs/windows.texi
index c66deb7748..4ab641e784 100644
--- a/doc/emacs/windows.texi
+++ b/doc/emacs/windows.texi
@@ -541,9 +541,11 @@ the following form in your initialization file (@pxref{Init File}):
 @findex temp-buffer-resize-mode
   The @file{*Completions*} buffer is also special in the sense that
 Emacs usually tries to make its window just as large as necessary to
-display all of its contents.  To resize windows showing other
-temporary displays, like, for example, the @file{*Help*} buffer, turn
-on the minor mode (@pxref{Minor Modes}) @code{temp-buffer-resize-mode}
+display all of its contents, and that you can switch back and forth
+between the minibuffer and the @file{*Completions*} buffer by typing
+@key{M-g M-c}.  To resize windows showing other temporary displays,
+like, for example, the @file{*Help*} buffer, turn on the minor mode
+(@pxref{Minor Modes}) @code{temp-buffer-resize-mode}
 (@pxref{Temporary Displays,,Temporary Displays, elisp, The Emacs Lisp
 Reference Manual}).
 
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index e04f1040b3..ec21b7b93b 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2603,6 +2603,7 @@ The completion method is determined by `completion-at-point-functions'."
     (define-key map "?" 'minibuffer-completion-help)
     (define-key map [prior] 'switch-to-completions)
     (define-key map "\M-v"  'switch-to-completions)
+    (define-key map "\M-g\M-c"  'switch-to-completions)
     map)
   "Local keymap for minibuffer input with completion.")
 
diff --git a/lisp/simple.el b/lisp/simple.el
index 2a90a07631..cac3058825 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1661,6 +1661,7 @@ in *Help* buffer.  See also the command `describe-char'."
     (define-key m "\t" 'completion-at-point)
     (define-key m "\r" 'read--expression-try-read)
     (define-key m "\n" 'read--expression-try-read)
+    (define-key m "\M-g\M-c" 'read-expression-switch-to-completions)
     (set-keymap-parent m minibuffer-local-map)
     m))
 
@@ -8834,6 +8835,8 @@ makes it easier to edit it."
 
 (defvar completion-list-mode-map
   (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map special-mode-map)
+    (define-key map "g" nil) ;; There's nothing to revert from.
     (define-key map [mouse-2] 'choose-completion)
     (define-key map [follow-link] 'mouse-face)
     (define-key map [down-mouse-2] nil)
@@ -8845,6 +8848,9 @@ makes it easier to edit it."
     (define-key map [backtab] 'previous-completion)
     (define-key map "q" 'quit-window)
     (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)
     map)
   "Local map for completion list buffers.")
 
@@ -9133,6 +9139,18 @@ select the completion near point.\n\n"))))))
       ;; FIXME: Perhaps this should be done in `minibuffer-completion-help'.
       (when (bobp)
 	(next-completion 1)))))
+
+(defun read-expression-switch-to-completions ()
+  "Select the completion list window while reading an expression."
+  (interactive)
+  (completion-help-at-point)
+  (switch-to-completions))
+
+(defun switch-to-minibuffer ()
+  "Select the minibuffer window."
+  (interactive)
+  (when (active-minibuffer-window)
+    (select-window (active-minibuffer-window))))
 
 ;;; Support keyboard commands to turn on various modifiers.
 
-- 
2.30.2