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 "" #'switch-to-completions "M-v" #'switch-to-completions "M-g M-c" #'switch-to-completions + + "" (completion-arrows 'minibuffer-previous-completion) + "" (completion-arrows 'minibuffer-next-completion) + "" (completion-arrows 'minibuffer-previous-line-completion) + "" (completion-arrows 'minibuffer-next-line-completion) + "M-" #'minibuffer-choose-previous-completion "M-" #'minibuffer-choose-next-completion "M-S-" #'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."