summaryrefslogtreecommitdiff
path: root/lisp/minibuffer.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/minibuffer.el')
-rw-r--r--lisp/minibuffer.el418
1 files changed, 287 insertions, 131 deletions
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 0ef846ccd78..6694340e021 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -1,4 +1,4 @@
-;;; minibuffer.el --- Minibuffer completion functions -*- lexical-binding: t -*-
+;;; minibuffer.el --- Minibuffer and completion functions -*- lexical-binding: t -*-
;; Copyright (C) 2008-2022 Free Software Foundation, Inc.
@@ -864,7 +864,11 @@ Intended to be called via `clear-message-function'."
(setq minibuffer-message-timer nil))
(when (overlayp minibuffer-message-overlay)
(delete-overlay minibuffer-message-overlay)
- (setq minibuffer-message-overlay nil))))
+ (setq minibuffer-message-overlay nil)))
+
+ ;; Return nil telling the caller that the message
+ ;; should be also handled by the caller.
+ nil)
(setq clear-message-function 'clear-minibuffer-message)
@@ -894,13 +898,25 @@ If the current buffer is not a minibuffer, erase its entire contents."
(defcustom completion-auto-help t
"Non-nil means automatically provide help for invalid completion input.
-If the value is t the *Completions* buffer is displayed whenever completion
+If the value is t, the *Completions* buffer is displayed whenever completion
is requested but cannot be done.
If the value is `lazy', the *Completions* buffer is only displayed after
-the second failed attempt to complete."
- :type '(choice (const nil) (const t) (const lazy)))
-
-(defconst completion-styles-alist
+the second failed attempt to complete.
+If the value is `always', the *Completions* buffer is always shown
+after a completion attempt, and the list of completions is updated if
+already visible.
+If the value is `visible', the *Completions* buffer is displayed
+whenever completion is requested but cannot be done for the first time,
+but remains visible thereafter, and the list of completions in it is
+updated for subsequent attempts to complete.."
+ :type '(choice (const :tag "Don't show" nil)
+ (const :tag "Show only when cannot complete" t)
+ (const :tag "Show after second failed completion attempt" lazy)
+ (const :tag
+ "Leave visible after first failed completion" visible)
+ (const :tag "Always visible" always)))
+
+(defvar completion-styles-alist
'((emacs21
completion-emacs21-try-completion completion-emacs21-all-completions
"Simple prefix-based completion.
@@ -1008,7 +1024,9 @@ an association list that can specify properties such as:
- `styles': the list of `completion-styles' to use for that category.
- `cycle': the `completion-cycle-threshold' to use for that category.
Categories are symbols such as `buffer' and `file', used when
-completing buffer and file names, respectively.")
+completing buffer and file names, respectively.
+
+Also see `completion-category-overrides'.")
(defcustom completion-category-overrides nil
"List of category-specific user overrides for completion styles.
@@ -1018,7 +1036,9 @@ an association list that can specify properties such as:
- `cycle': the `completion-cycle-threshold' to use for that category.
Categories are symbols such as `buffer' and `file', used when
completing buffer and file names, respectively.
-This overrides the defaults specified in `completion-category-defaults'."
+
+If a property in a category is specified by this variable, it
+overrides the default specified in `completion-category-defaults'."
:version "25.1"
:type `(alist :key-type (choice :tag "Category"
(const buffer)
@@ -1080,9 +1100,10 @@ This overrides the defaults specified in `completion-category-defaults'."
(result-and-style
(completion--some
(lambda (style)
- (let ((probe (funcall (nth n (assq style
- completion-styles-alist))
- string table pred point)))
+ (let ((probe (funcall
+ (or (nth n (assq style completion-styles-alist))
+ (error "Invalid completion style %s" style))
+ string table pred point)))
(and probe (cons probe style))))
(completion--styles md)))
(adjust-fn (get (cdr result-and-style) 'completion--adjust-metadata)))
@@ -1123,6 +1144,7 @@ Moves point to the end of the new text."
;; The properties on `newtext' include things like the
;; `completions-first-difference' face, which we don't want to
;; include upon insertion.
+ (setq newtext (copy-sequence newtext)) ;Don't modify the arg by side-effect.
(if minibuffer-allow-text-properties
;; If we're preserving properties, then just remove the faces
;; and other properties added by the completion machinery.
@@ -1172,6 +1194,18 @@ completion candidates than this number."
:version "24.1"
:type completion--cycling-threshold-type)
+(defcustom completions-sort 'alphabetical
+ "Sort candidates in the *Completions* buffer.
+
+The value can be nil to disable sorting, `alphabetical' for
+alphabetical sorting or a custom sorting function. The sorting
+function takes and returns a list of completion candidate
+strings."
+ :type '(choice (const :tag "No sorting" nil)
+ (const :tag "Alphabetical sorting" alphabetical)
+ (function :tag "Custom function"))
+ :version "29.1")
+
(defcustom completions-group nil
"Enable grouping of completion candidates in the *Completions* buffer.
See also `completions-group-format' and `completions-group-sort'."
@@ -1330,16 +1364,18 @@ when the buffer's text is already an exact match."
(completion--cache-all-sorted-completions beg end comps)
(minibuffer-force-complete beg end))
(completed
- ;; We could also decide to refresh the completions,
- ;; if they're displayed (and assuming there are
- ;; completions left).
- (minibuffer-hide-completions)
- (if exact
- ;; If completion did not put point at end of field,
- ;; it's a sign that completion is not finished.
- (completion--done completion
- (if (< comp-pos (length completion))
- 'exact 'unknown))))
+ (cond
+ ((pcase completion-auto-help
+ ('visible (get-buffer-window "*Completions*" 0))
+ ('always t))
+ (minibuffer-completion-help beg end))
+ (t (minibuffer-hide-completions)
+ (when exact
+ ;; If completion did not put point at end of field,
+ ;; it's a sign that completion is not finished.
+ (completion--done completion
+ (if (< comp-pos (length completion))
+ 'exact 'unknown))))))
;; Show the completion table, if requested.
((not exact)
(if (pcase completion-auto-help
@@ -1385,12 +1421,24 @@ scroll the window of possible completions."
(eq t (frame-visible-p (window-frame minibuffer-scroll-window))))
(let ((window minibuffer-scroll-window))
(with-current-buffer (window-buffer window)
- (if (pos-visible-in-window-p (point-max) window)
- ;; If end is in view, scroll up to the beginning.
- (set-window-start window (point-min) nil)
- ;; Else scroll down one screen.
- (with-selected-window window
- (scroll-up)))
+ (cond
+ ;; Here this is possible only when second-tab, so jump now.
+ (completion-auto-select
+ (switch-to-completions))
+ ;; Reverse tab
+ ((equal (this-command-keys) [backtab])
+ (if (pos-visible-in-window-p (point-min) window)
+ ;; If beginning is in view, scroll up to the end.
+ (set-window-point window (point-max))
+ ;; Else scroll down one screen.
+ (with-selected-window window (scroll-down))))
+ ;; Normal tab
+ (t
+ (if (pos-visible-in-window-p (point-max) window)
+ ;; If end is in view, scroll up to the end.
+ (set-window-start window (point-min) nil)
+ ;; Else scroll down one screen.
+ (with-selected-window window (scroll-up)))))
nil)))
;; If we're cycling, keep on cycling.
((and completion-cycling completion-all-sorted-completions)
@@ -1825,6 +1873,17 @@ Return nil if there is no valid completion, else t."
This face is only used if the strings used for completions
doesn't already specify a face.")
+(defface completions-highlight
+ '((t :inherit highlight))
+ "Default face for highlighting the current completion candidate."
+ :version "29.1")
+
+(defcustom completions-highlight-face 'completions-highlight
+ "A face name to highlight the current completion candidate.
+If the value is nil, no highlighting is performed."
+ :type '(choice (const nil) face)
+ :version "29.1")
+
(defcustom completions-format 'horizontal
"Define the appearance and sorting of completions.
If the value is `vertical', display completions sorted vertically
@@ -1844,6 +1903,15 @@ completions."
:type 'boolean
:version "28.1")
+(defcustom completions-header-format
+ (propertize "%s possible completions:\n" 'face 'shadow)
+ "Format of completions header.
+It may contain one %s to show the total count of completions.
+When nil, no header is shown."
+ :type '(choice (const :tag "No header" nil)
+ (string :tag "Header format string"))
+ :version "29.1")
+
(defun completion--insert-strings (strings &optional group-fun)
"Insert a list of STRINGS into the current buffer.
The candidate strings are inserted into the buffer depending on the
@@ -1983,7 +2051,8 @@ Runs of equal candidate strings are eliminated. GROUP-FUN is a
(when title
(insert (format completions-group-format title) "\n")))))
(completion--insert str group-fun)
- (insert "\n")))))
+ (insert "\n")))
+ (delete-char -1)))
(defun completion--insert (str group-fun)
(if (not (consp str))
@@ -1995,7 +2064,7 @@ Runs of equal candidate strings are eliminated. GROUP-FUN is a
(funcall group-fun str 'transform)
str))
(point))
- `(mouse-face highlight completion--string ,str))
+ `(mouse-face highlight cursor-face ,completions-highlight-face completion--string ,str))
;; If `str' is a list that has 2 elements,
;; then the second element is a suffix annotation.
;; If `str' has 3 elements, then the second element
@@ -2106,10 +2175,9 @@ candidates."
(with-current-buffer standard-output
(goto-char (point-max))
- (if (null completions)
- (insert "There are no possible completions of what you have typed.")
- (insert "Possible completions are:\n")
- (completion--insert-strings completions group-fun))))
+ (when completions-header-format
+ (insert (format completions-header-format (length completions))))
+ (completion--insert-strings completions group-fun)))
(run-hooks 'completion-setup-hook)
nil)
@@ -2181,6 +2249,19 @@ variables.")
(equal pre-msg (and exit-fun (current-message))))
(completion--message message))))
+(defcustom completions-max-height nil
+ "Maximum height for *Completions* buffer window."
+ :type '(choice (const nil) natnum)
+ :version "29.1")
+
+(defun completions--fit-window-to-buffer (&optional win &rest _)
+ "Resize *Completions* buffer window."
+ (if temp-buffer-resize-mode
+ (let ((temp-buffer-max-height (or completions-max-height
+ temp-buffer-max-height)))
+ (resize-temp-buffer-window win))
+ (fit-window-to-buffer win completions-max-height)))
+
(defun minibuffer-completion-help (&optional start end)
"Display a list of possible completions of the current minibuffer contents."
(interactive)
@@ -2210,6 +2291,9 @@ variables.")
(let* ((last (last completions))
(base-size (or (cdr last) 0))
(prefix (unless (zerop base-size) (substring string 0 base-size)))
+ (base-prefix (buffer-substring (minibuffer--completion-prompt-end)
+ (+ start base-size)))
+ (base-suffix (buffer-substring (point) (point-max)))
(all-md (completion--metadata (buffer-substring-no-properties
start (point))
base-size md
@@ -2244,9 +2328,7 @@ variables.")
,(if (eq (selected-window) (minibuffer-window))
'display-buffer-at-bottom
'display-buffer-below-selected))
- ,(if temp-buffer-resize-mode
- '(window-height . resize-temp-buffer-window)
- '(window-height . fit-window-to-buffer))
+ (window-height . completions--fit-window-to-buffer)
,(when temp-buffer-resize-mode
'(preserve-size . (nil . t)))
(body-function
@@ -2263,7 +2345,10 @@ variables.")
;; same, but not always.
(setq completions (if sort-fun
(funcall sort-fun completions)
- (sort completions 'string-lessp)))
+ (pcase completions-sort
+ ('nil completions)
+ ('alphabetical (sort completions #'string-lessp))
+ (_ (funcall completions-sort completions)))))
;; After sorting, group the candidates using the
;; `group-function'.
@@ -2300,20 +2385,28 @@ variables.")
;; completion-all-completions does not give us the
;; necessary information.
end))
+ (setq-local completion-base-affixes
+ (list base-prefix base-suffix))
(setq-local completion-list-insert-choice-function
(let ((ctable minibuffer-completion-table)
(cpred minibuffer-completion-predicate)
(cprops completion-extra-properties))
(lambda (start end choice)
- (unless (or (zerop (length prefix))
- (equal prefix
- (buffer-substring-no-properties
- (max (point-min)
- (- start (length prefix)))
- start)))
- (message "*Completions* out of date"))
- ;; FIXME: Use `md' to do quoting&terminator here.
- (completion--replace start end choice)
+ (if (and (stringp start) (stringp end))
+ (progn
+ (delete-minibuffer-contents)
+ (insert start choice)
+ ;; Keep point after completion before suffix
+ (save-excursion (insert end)))
+ (unless (or (zerop (length prefix))
+ (equal prefix
+ (buffer-substring-no-properties
+ (max (point-min)
+ (- start (length prefix)))
+ start)))
+ (message "*Completions* out of date"))
+ ;; FIXME: Use `md' to do quoting&terminator here.
+ (completion--replace start end choice))
(let* ((minibuffer-completion-table ctable)
(minibuffer-completion-predicate cpred)
(completion-extra-properties cprops)
@@ -2334,6 +2427,7 @@ variables.")
"Get rid of an out-of-date *Completions* buffer."
;; FIXME: We could/should use minibuffer-scroll-window here, but it
;; can also point to the minibuffer-parent-window, so it's a bit tricky.
+ (interactive)
(let ((win (get-buffer-window "*Completions*" 0)))
(if win (with-selected-window win (bury-buffer)))))
@@ -2448,14 +2542,15 @@ Also respects the obsolete wrapper hook `completion-in-region-functions'.
(completion-in-region-mode 1))
(completion--in-region-1 start end))))
-(defvar completion-in-region-mode-map
- (let ((map (make-sparse-keymap)))
- ;; FIXME: Only works if completion-in-region-mode was activated via
- ;; completion-at-point called directly.
- (define-key map "\M-?" 'completion-help-at-point)
- (define-key map "\t" 'completion-at-point)
- map)
- "Keymap activated during `completion-in-region'.")
+(defvar-keymap completion-in-region-mode-map
+ :doc "Keymap activated during `completion-in-region'."
+ ;; FIXME: Only works if completion-in-region-mode was activated via
+ ;; completion-at-point called directly.
+ "M-?" #'completion-help-at-point
+ "TAB" #'completion-at-point
+ "M-<up>" #'minibuffer-previous-completion
+ "M-<down>" #'minibuffer-next-completion
+ "M-RET" #'minibuffer-choose-completion)
;; It is difficult to know when to exit completion-in-region-mode (i.e. hide
;; the *Completions*). Here's how previous packages did it:
@@ -2502,6 +2597,7 @@ Also respects the obsolete wrapper hook `completion-in-region-functions'.
(cl-assert completion-in-region-mode-predicate)
(setq completion-in-region-mode--predicate
completion-in-region-mode-predicate)
+ (setq-local minibuffer-completion-auto-choose nil)
(add-hook 'post-command-hook #'completion-in-region--postch)
(push `(completion-in-region-mode . ,completion-in-region-mode-map)
minor-mode-overriding-map-alist)))
@@ -2651,48 +2747,44 @@ The completion method is determined by `completion-at-point-functions'."
(define-key map "\n" 'exit-minibuffer)
(define-key map "\r" 'exit-minibuffer))
-(defvar minibuffer-local-completion-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map minibuffer-local-map)
- (define-key map "\t" '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)
- (define-key map " " 'minibuffer-complete-word)
- (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.")
-
-(defvar minibuffer-local-must-match-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map minibuffer-local-completion-map)
- (define-key map "\r" 'minibuffer-complete-and-exit)
- (define-key map "\n" 'minibuffer-complete-and-exit)
- map)
- "Local keymap for minibuffer input with completion, for exact match.")
-
-(defvar minibuffer-local-filename-completion-map
- (let ((map (make-sparse-keymap)))
- (define-key map " " nil)
- map)
- "Local keymap for minibuffer input with completion for filenames.
+(defvar-keymap minibuffer-local-completion-map
+ :doc "Local keymap for minibuffer input with completion."
+ :parent minibuffer-local-map
+ "TAB" #'minibuffer-complete
+ "<backtab>" #'minibuffer-complete
+ ;; M-TAB is already abused for many other purposes, so we should find
+ ;; another binding for it.
+ ;; "M-TAB" #'minibuffer-force-complete
+ "SPC" #'minibuffer-complete-word
+ "?" #'minibuffer-completion-help
+ "<prior>" #'switch-to-completions
+ "M-v" #'switch-to-completions
+ "M-g M-c" #'switch-to-completions
+ "M-<up>" #'minibuffer-previous-completion
+ "M-<down>" #'minibuffer-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."
+ :parent minibuffer-local-completion-map
+ "RET" #'minibuffer-complete-and-exit
+ "C-j" #'minibuffer-complete-and-exit)
+
+(defvar-keymap minibuffer-local-filename-completion-map
+ :doc "Local keymap for minibuffer input with completion for filenames.
Gets combined either with `minibuffer-local-completion-map' or
-with `minibuffer-local-must-match-map'.")
+with `minibuffer-local-must-match-map'."
+ "SPC" nil)
(defvar minibuffer-local-filename-must-match-map (make-sparse-keymap))
(make-obsolete-variable 'minibuffer-local-filename-must-match-map nil "24.1")
-(defvar minibuffer-local-ns-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map minibuffer-local-map)
- (define-key map " " #'exit-minibuffer)
- (define-key map "\t" #'exit-minibuffer)
- (define-key map "?" #'self-insert-and-exit)
- map)
- "Local keymap for the minibuffer when spaces are not allowed.")
+(defvar-keymap minibuffer-local-ns-map
+ :doc "Local keymap for the minibuffer when spaces are not allowed."
+ :parent minibuffer-local-map
+ "SPC" #'exit-minibuffer
+ "TAB" #'exit-minibuffer
+ "?" #'self-insert-and-exit)
(defun read-no-blanks-input (prompt &optional initial inherit-input-method)
"Read a string from the terminal, not allowing blanks.
@@ -2713,24 +2805,23 @@ If `inhibit-interaction' is non-nil, this function will signal an
;;; Major modes for the minibuffer
-(defvar minibuffer-inactive-mode-map
- (let ((map (make-keymap)))
- (suppress-keymap map)
- (define-key map "e" 'find-file-other-frame)
- (define-key map "f" 'find-file-other-frame)
- (define-key map "b" 'switch-to-buffer-other-frame)
- (define-key map "i" 'info)
- (define-key map "m" 'mail)
- (define-key map "n" 'make-frame)
- (define-key map [mouse-1] 'view-echo-area-messages)
- ;; So the global down-mouse-1 binding doesn't clutter the execution of the
- ;; above mouse-1 binding.
- (define-key map [down-mouse-1] #'ignore)
- map)
- "Keymap for use in the minibuffer when it is not active.
+(defvar-keymap minibuffer-inactive-mode-map
+ :doc "Keymap for use in the minibuffer when it is not active.
The non-mouse bindings in this keymap can only be used in minibuffer-only
frames, since the minibuffer can normally not be selected when it is
-not active.")
+not active."
+ :full t
+ :suppress t
+ "e" #'find-file-other-frame
+ "f" #'find-file-other-frame
+ "b" #'switch-to-buffer-other-frame
+ "i" #'info
+ "m" #'mail
+ "n" #'make-frame
+ "<mouse-1>" #'view-echo-area-messages
+ ;; So the global down-mouse-1 binding doesn't clutter the execution of the
+ ;; above mouse-1 binding.
+ "<down-mouse-1>" #'ignore)
(define-derived-mode minibuffer-inactive-mode nil "InactiveMinibuffer"
:abbrev-table nil ;abbrev.el is not loaded yet during dump.
@@ -2739,7 +2830,7 @@ not active.")
This is only used when the minibuffer area has no active minibuffer.
Note that the minibuffer may change to this mode more often than
-you might expect. For instance, typing `M-x' may change the
+you might expect. For instance, typing \\`M-x' may change the
buffer to this mode, then to a different mode, and then back
again to this mode upon exit. Code running from
`minibuffer-inactive-mode-hook' has to be prepared to run
@@ -2922,26 +3013,30 @@ same as `substitute-in-file-name'."
(let* ((ustr (substitute-in-file-name qstr))
(uprefix (substring ustr 0 upos))
qprefix)
- ;; Main assumption: nothing after qpos should affect the text before upos,
- ;; so we can work our way backward from the end of qstr, one character
- ;; at a time.
- ;; Second assumptions: If qpos is far from the end this can be a bit slow,
- ;; so we speed it up by doing a first loop that skips a word at a time.
- ;; This word-sized loop is careful not to cut in the middle of env-vars.
- (while (let ((boundary (string-match "\\(\\$+{?\\)?\\w+\\W*\\'" qstr)))
- (and boundary
- (progn
- (setq qprefix (substring qstr 0 boundary))
+ (if (eq upos (length ustr))
+ ;; Easy and common case. This not only speed things up in a very
+ ;; common case but it also avoids problems in some cases (bug#53053).
+ (cons (length qstr) #'minibuffer-maybe-quote-filename)
+ ;; Main assumption: nothing after qpos should affect the text before upos,
+ ;; so we can work our way backward from the end of qstr, one character
+ ;; at a time.
+ ;; Second assumptions: If qpos is far from the end this can be a bit slow,
+ ;; so we speed it up by doing a first loop that skips a word at a time.
+ ;; This word-sized loop is careful not to cut in the middle of env-vars.
+ (while (let ((boundary (string-match "\\(\\$+{?\\)?\\w+\\W*\\'" qstr)))
+ (and boundary
+ (progn
+ (setq qprefix (substring qstr 0 boundary))
+ (string-prefix-p uprefix
+ (substitute-in-file-name qprefix)))))
+ (setq qstr qprefix))
+ (let ((qpos (length qstr)))
+ (while (and (> qpos 0)
(string-prefix-p uprefix
- (substitute-in-file-name qprefix)))))
- (setq qstr qprefix))
- (let ((qpos (length qstr)))
- (while (and (> qpos 0)
- (string-prefix-p uprefix
- (substitute-in-file-name
- (substring qstr 0 (1- qpos)))))
- (setq qpos (1- qpos)))
- (cons qpos #'minibuffer-maybe-quote-filename))))
+ (substitute-in-file-name
+ (substring qstr 0 (1- qpos)))))
+ (setq qpos (1- qpos)))
+ (cons qpos #'minibuffer-maybe-quote-filename)))))
(defalias 'completion--file-name-table
(completion-table-with-quoting #'completion-file-name-table
@@ -3056,7 +3151,10 @@ Fourth arg MUSTMATCH can take the following values:
- anything else behaves like t except that typing RET does not exit if it
does non-null completion.
-Fifth arg INITIAL specifies text to start with.
+Fifth arg INITIAL specifies text to start with. It will be
+interpreted as the trailing part of DEFAULT-FILENAME, so using a
+full file name for INITIAL will usually lead to surprising
+results.
Sixth arg PREDICATE, if non-nil, should be a function of one
argument; then a file name is considered an acceptable completion
@@ -4016,7 +4114,7 @@ This turns
into
(prefix \"f\" any \"o\" any \"o\" any point)
which is at the core of flex logic. The extra
-'any' is optimized away later on."
+`any' is optimized away later on."
(mapcan (lambda (elem)
(if (stringp elem)
(mapcan (lambda (char)
@@ -4160,6 +4258,7 @@ See `completing-read' for the meaning of the arguments."
;; override bindings in base-keymap.
base-keymap)))
(buffer (current-buffer))
+ (c-i-c completion-ignore-case)
(result
(minibuffer-with-setup-hook
(lambda ()
@@ -4169,7 +4268,9 @@ See `completing-read' for the meaning of the arguments."
(setq-local minibuffer-completion-confirm
(unless (eq require-match t) require-match))
(setq-local minibuffer--require-match require-match)
- (setq-local minibuffer--original-buffer buffer))
+ (setq-local minibuffer--original-buffer buffer)
+ ;; Copy the value from original buffer to the minibuffer.
+ (setq-local completion-ignore-case c-i-c))
(read-from-minibuffer prompt initial-input keymap
nil hist def inherit-input-method))))
(when (and (equal result "") def)
@@ -4254,6 +4355,61 @@ the minibuffer was activated, and execute the forms."
(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))))
+
+(defcustom minibuffer-completion-auto-choose t
+ "Non-nil means to automatically insert completions to the minibuffer.
+When non-nil, then `minibuffer-next-completion' and
+`minibuffer-previous-completion' will insert the completion
+selected by these commands to the minibuffer."
+ :type 'boolean
+ :version "29.1")
+
+(defun minibuffer-next-completion (&optional n)
+ "Move to the next item in its completions window from the minibuffer.
+When `minibuffer-completion-auto-choose' is non-nil, then also
+insert the selected completion to the minibuffer."
+ (interactive "p")
+ (let ((auto-choose minibuffer-completion-auto-choose))
+ (with-minibuffer-completions-window
+ (when completions-highlight-face
+ (setq-local cursor-face-highlight-nonselected-window t))
+ (next-completion (or n 1))
+ (when auto-choose
+ (let ((completion-use-base-affixes t))
+ (choose-completion nil t t))))))
+
+(defun minibuffer-previous-completion (&optional n)
+ "Move to the previous item in its completions window from the minibuffer.
+When `minibuffer-completion-auto-choose' is non-nil, then also
+insert the selected completion to the minibuffer."
+ (interactive "p")
+ (minibuffer-next-completion (- (or n 1))))
+
+(defun minibuffer-choose-completion (&optional no-exit no-quit)
+ "Run `choose-completion' from the minibuffer in its completions window.
+With prefix argument NO-EXIT, insert the completion at point to the
+minibuffer, but don't exit the minibuffer. When the prefix argument
+is not provided, then whether to exit the minibuffer depends on the value
+of `completion-no-auto-exit'.
+If NO-QUIT is non-nil, insert the completion at point to the
+minibuffer, but don't quit the 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,