Function: minibuffer-completion-help

minibuffer-completion-help is an interactive and byte-compiled function defined in minibuffer.el.gz.

Signature

(minibuffer-completion-help &optional START END)

Documentation

Display a list of possible completions of the current minibuffer contents.

View in manual

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/minibuffer.el.gz
(defun minibuffer-completion-help (&optional start end)
  "Display a list of possible completions of the current minibuffer contents."
  (interactive)
  (message "Making completion list...")
  (let* ((start (or start (minibuffer--completion-prompt-end)))
         (end (or end (point-max)))
         (string (buffer-substring start end))
         (md (completion--field-metadata start))
         (completions (completion-all-completions
                       string
                       minibuffer-completion-table
                       minibuffer-completion-predicate
                       (- (point) start)
                       md)))
    (message nil)
    (if (or (null completions)
            (and (not (consp (cdr completions)))
                 (equal (car completions) string)))
        (progn
          ;; If there are no completions, or if the current input is already
          ;; the sole completion, then hide (previous&stale) completions.
          (minibuffer-hide-completions)
          (if completions
              (completion--message "Sole completion")
            (unless completion-fail-discreetly
	      (ding)
	      (completion--message "No match"))))

      (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
                                           minibuffer-completion-table
                                           minibuffer-completion-predicate))
             (ann-fun (or (completion-metadata-get all-md 'annotation-function)
                          (plist-get completion-extra-properties
                                     :annotation-function)))
             (aff-fun (or (completion-metadata-get all-md 'affixation-function)
                          (plist-get completion-extra-properties
                                     :affixation-function)))
             (sort-fun (completion-metadata-get all-md 'display-sort-function))
             (group-fun (completion-metadata-get all-md 'group-function))
             (mainbuf (current-buffer))
             ;; If the *Completions* buffer is shown in a new
             ;; window, mark it as softly-dedicated, so bury-buffer in
             ;; minibuffer-hide-completions will know whether to
             ;; delete the window or not.
             (display-buffer-mark-dedicated 'soft))
        (with-current-buffer-window
          "*Completions*"
          ;; This is a copy of `display-buffer-fallback-action'
          ;; where `display-buffer-use-some-window' is replaced
          ;; with `display-buffer-at-bottom'.
          `((display-buffer--maybe-same-window
             display-buffer-reuse-window
             display-buffer--maybe-pop-up-frame
             ;; Use `display-buffer-below-selected' for inline completions,
             ;; but not in the minibuffer (e.g. in `eval-expression')
             ;; for which `display-buffer-at-bottom' is used.
             ,(if (eq (selected-window) (minibuffer-window))
                  'display-buffer-at-bottom
                'display-buffer-below-selected))
            (window-height . completions--fit-window-to-buffer)
            ,(when temp-buffer-resize-mode
               '(preserve-size . (nil . t)))
            (body-function
             . ,#'(lambda (_window)
                    (with-current-buffer mainbuf
                      ;; Remove the base-size tail because `sort' requires a properly
                      ;; nil-terminated list.
                      (when last (setcdr last nil))

                      ;; Sort first using the `display-sort-function'.
                      ;; FIXME: This function is for the output of
                      ;; all-completions, not
                      ;; completion-all-completions.  Often it's the
                      ;; same, but not always.
                      (setq completions (if sort-fun
                                            (funcall sort-fun completions)
                                          (pcase completions-sort
                                            ('nil completions)
                                            ('alphabetical (sort completions #'string-lessp))
                                            (_ (funcall completions-sort completions)))))

                      ;; After sorting, group the candidates using the
                      ;; `group-function'.
                      (when group-fun
                        (setq completions
                              (minibuffer--group-by
                               group-fun
                               (pcase completions-group-sort
                                 ('nil #'identity)
                                 ('alphabetical
                                  (lambda (groups)
                                    (sort groups
                                          (lambda (x y)
                                            (string< (car x) (car y))))))
                                 (_ completions-group-sort))
                               completions)))

                      (cond
                       (aff-fun
                        (setq completions
                              (funcall aff-fun completions)))
                       (ann-fun
                        (setq completions
                              (mapcar (lambda (s)
                                        (let ((ann (funcall ann-fun s)))
                                          (if ann (list s ann) s)))
                                      completions))))

                      (with-current-buffer standard-output
                        (setq-local completion-base-position
                             (list (+ start base-size)
                                   ;; FIXME: We should pay attention to completion
                                   ;; boundaries here, but currently
                                   ;; 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)
                                 (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)
                                        (result (concat prefix choice))
                                        (bounds (completion-boundaries
                                                 result ctable cpred "")))
                                   ;; If the completion introduces a new field, then
                                   ;; completion is not finished.
                                   (completion--done result
                                                     (if (eq (car bounds) (length result))
                                                         'exact 'finished)))))))

                      (display-completion-list completions nil group-fun)))))
          nil)))
    nil))