emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Re: Other details about completion.


From: Juri Linkov
Subject: Re: [PATCH] Re: Other details about completion.
Date: Wed, 06 Apr 2022 19:48:40 +0300
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (x86_64-pc-linux-gnu)

>>> 1) I think it is more intuitive to invert and use the M-S-<arrow>
>>> minibuffer-choose-** and M-<arrow> for
>>> minibuffer-{previous|next}-completion for not insert commands...
>>
>> Easier to type M-<arrow> were intended as the primary way to use this 
>> feature.
> I know, but such primary behavior is too intrusive IMO.
>
>> Whereas more hard to type M-S-<arrow>/M-RET as a rarely used alternative.
> Mi proposal (the suffix one) is basically to avoid the need of M-RET.

So your proposal is something in between.  Then maybe instead of two sets
of commands (that either insert the current completion or not) we could have
one set of commands bound to M-<up>/M-<down>, and a customizable option with
three values: insert, don't insert, use transient suffix.

> I took the idea basically from some configs around for fish and zsh..
> ...
> But OTOH I will strongly recommend the C-g and arrow navigation
> behavior... That could be maybe implemented with a set-transient-map...

What is also interesting to note is that even every web browser
uses own completion logic:

1. in Firefox: the suffix of the first completion is inserted to the
   address bar as the selected region, but <up>/<down> inserts
   the completion without selecting its suffix, like M-<up>/M-<down>
   currently does in Emacs.  One ESC closes the completions window,
   another ESC clears the address bar.

2. in Chromium: <up>/<down> inserts the completion without any selection,
   like M-<up>/M-<down> currently does in Emacs.  One ESC clears the
   inserted string, another ESC closes the completions window and clears
   the address bar.

>> But what about M-<left>/M-<right> for not one-column format?
>
> This just confirms me that the initial approach implemented with a minor
> mode (or using a set-transient-map) may be a solution.

We started with non-intrusive keybindings.  But indeed, more intrusive keys
should be enabled only depending on a new customizable option.

Here is the next patch that does this and allows using all arrow keys
only when the completions window is visible:

diff --git a/lisp/simple.el b/lisp/simple.el
index ef52006501..bfc268b828 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -9151,6 +9151,15 @@ delete-completion-window
       (if (get-buffer-window buf)
          (select-window (get-buffer-window buf))))))
 
+(defcustom completion-arrows nil
+  "Non-nil means to use arrows to browse completions from the minibuffer."
+  :type '(choice (const :tag "Don't use arrows" nil)
+                 (const :tag "Use arrows" t)
+                 (const :tag "Use arrows when completions window is visible"
+                        visible))
+  :version "29.1"
+  :group 'completion)
+
 (defcustom completion-wrap-movement t
   "Non-nil means to wrap around when selecting completion options.
 This affects the commands `next-completion' and
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index c79c5a7a5d..ff124e18e9 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2736,6 +2821,15 @@ completion-help-at-point
   (define-key map "\n" 'exit-minibuffer)
   (define-key map "\r" 'exit-minibuffer))
 
+(defun completion-arrows (binding)
+  `(menu-item
+    "" ,binding
+    :filter ,(lambda (cmd)
+               (when (or (eq completion-arrows t)
+                         (and (eq completion-arrows 'visible)
+                              (get-buffer-window "*Completions*" 0)))
+                 cmd))))
+
 (defvar-keymap minibuffer-local-completion-map
   :doc "Local keymap for minibuffer input with completion."
   :parent minibuffer-local-map
@@ -2749,6 +2843,12 @@ minibuffer-local-completion-map
   "<prior>"   #'switch-to-completions
   "M-v"       #'switch-to-completions
   "M-g M-c"   #'switch-to-completions
+
+  "<left>"    (completion-arrows 'minibuffer-previous-completion)
+  "<right>"   (completion-arrows 'minibuffer-next-completion)
+  "<up>"      (completion-arrows 'minibuffer-previous-line-completion)
+  "<down>"    (completion-arrows 'minibuffer-next-line-completion)
+
   "M-<up>"    #'minibuffer-choose-previous-completion
   "M-<down>"  #'minibuffer-choose-next-completion
   "M-S-<up>"   #'minibuffer-previous-completion
@@ -4372,6 +4472,22 @@ minibuffer-next-completion
       (setq-local cursor-face-highlight-nonselected-window t))
     (next-completion n)))
 
+(defun minibuffer-previous-line-completion (&optional n)
+  "Run `previous-line' from the minibuffer in its completions window."
+  (interactive "p")
+  (with-minibuffer-completions-window
+    (when completions-highlight-face
+      (setq-local cursor-face-highlight-nonselected-window t))
+    (forward-line (- n))))
+
+(defun minibuffer-next-line-completion (&optional n)
+  "Run `next-line' from the minibuffer in its completions window."
+  (interactive "p")
+  (with-minibuffer-completions-window
+    (when completions-highlight-face
+      (setq-local cursor-face-highlight-nonselected-window t))
+    (forward-line n)))
+
 (defun minibuffer-choose-previous-completion (&optional n)
   "Run `previous-completion' from the minibuffer in its completions window.
 Also insert the selected completion to the minibuffer."

reply via email to

[Prev in Thread] Current Thread [Next in Thread]