diff --git a/lisp/simple.el b/lisp/simple.el index accc119e2b..52cf54c563 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -3891,6 +3891,9 @@ minibuffer-local-shell-command-map (let ((map (make-sparse-keymap))) (set-keymap-parent map minibuffer-local-map) (define-key map "\t" 'completion-at-point) + (define-key map (kbd "M-") 'minibuffer-previous-completion) + (define-key map (kbd "M-") 'minibuffer-next-completion) + (define-key map (kbd "M-RET") 'minibuffer-choose-completion) map) "Keymap used for completing shell commands in minibuffer.") diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index 36b8d80841..5685f078ad 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el @@ -2681,7 +2775,12 @@ minibuffer-local-completion-map "?" #'minibuffer-completion-help "" #'switch-to-completions "M-v" #'switch-to-completions - "M-g M-c" #'switch-to-completions) + "M-g M-c" #'switch-to-completions + "M-S-" #'minibuffer-previous-completion + "M-S-" #'minibuffer-next-completion + "M-" #'minibuffer-choose-previous-completion + "M-" #'minibuffer-choose-next-completion + "M-RET" #'minibuffer-choose-completion) (defvar-keymap minibuffer-local-must-match-map :doc "Local keymap for minibuffer input with completion, for exact match." @@ -4271,6 +4370,52 @@ minibuffer-scroll-other-window-down (with-minibuffer-selected-window (scroll-other-window-down arg))) +(defmacro with-minibuffer-completions-window (&rest body) + "Execute the forms in BODY from the minibuffer in its completions window. +When used in a minibuffer window, select the window with completions, +and execute the forms." + (declare (indent 0) (debug t)) + `(let ((window (or (get-buffer-window "*Completions*" 0) + ;; Make sure we have a completions window. + (progn (minibuffer-completion-help) + (get-buffer-window "*Completions*" 0))))) + (when window + (with-selected-window window + ,@body)))) + +(defun minibuffer-previous-completion (&optional n) + "Run `previous-completion' from the minibuffer in its completions window." + (interactive "p") + (with-minibuffer-completions-window + (previous-completion n))) + +(defun minibuffer-next-completion (&optional n) + "Run `next-completion' from the minibuffer in its completions window." + (interactive "p") + (with-minibuffer-completions-window + (next-completion 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." + (interactive "p") + (minibuffer-previous-completion n) + (minibuffer-choose-completion t t)) + +(defun minibuffer-choose-next-completion (&optional n) + "Run `next-completion' from the minibuffer in its completions window. +Also insert the selected completion to the minibuffer." + (interactive "p") + (minibuffer-next-completion n) + (minibuffer-choose-completion t t)) + +(defun minibuffer-choose-completion (&optional no-exit no-quit) + "Run `choose-completion' from the minibuffer in its completions window." + (interactive "p") + (with-minibuffer-completions-window + (let ((completion-use-base-affixes t)) + (choose-completion nil no-exit no-quit)))) + (defcustom minibuffer-default-prompt-format " (default %s)" "Format string used to output \"default\" values. When prompting for input, there will often be a default value,