From c93232c796a2c0f03403e11f18908dd912e2eb4e Mon Sep 17 00:00:00 2001 From: Gregory Heytings Date: Tue, 6 Apr 2021 07:28:49 +0000 Subject: [PATCH] Add an icomplete-vertical minor mode * lisp/icomplete.el (icomplete-vertical-mode): New minor mode. (icomplete-vertical-reformat-completions, icomplete-vertical-minibuffer-setup): Auxiliary functions for the new minor mode. (icomplete-completions-filter-hook): New hook to filter the completion candidates returned by 'icomplete-completions'. (icomplete-completions): Use the new hook. * etc/NEWS: Mention the new minor mode. * doc/emacs/buffers.texi: Document the new minor mode. --- doc/emacs/buffers.texi | 6 +++- etc/NEWS | 12 +++++++ lisp/icomplete.el | 77 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 87 insertions(+), 8 deletions(-) diff --git a/doc/emacs/buffers.texi b/doc/emacs/buffers.texi index 3a166e404a..00e73d800a 100644 --- a/doc/emacs/buffers.texi +++ b/doc/emacs/buffers.texi @@ -718,6 +718,7 @@ Icomplete @subsection Fast minibuffer selection @findex icomplete-mode +@findex icomplete-vertical-mode @cindex Icomplete mode Icomplete global minor mode provides a convenient way to quickly select an @@ -740,7 +741,10 @@ Icomplete To enable Icomplete mode, type @kbd{M-x icomplete-mode}, or customize the variable @code{icomplete-mode} to @code{t} (@pxref{Easy -Customization}). +Customization}). This will display the list of possible completions +on the same line as the prompt. To display the completion candidates +vertically under the prompt instead, type @kbd{M-x icomplete-vertical-mode}, +or customize the variable @code{icomplete-vertical-mode} to @code{t}. @findex fido-mode @cindex fido mode diff --git a/etc/NEWS b/etc/NEWS index 411ea72e7c..fbf25b68c3 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -485,6 +485,18 @@ documented. SMIE is now always enabled and 'ruby-use-smie' only controls whether indentation is done using SMIE or with the old ad-hoc code. +** Icomplete + ++++ +*** New minor mode Icomplete-Vertical mode. +This mode is based on and identical to Icomplete, except that it displays +the list of completions candidates vertically. + ++++ +*** New user option 'icomplete-completions-filter-hook'. +This hook is intended to be used for filtering the completion candidate +list returned by 'icomplete-completions'. + --- ** Specific warnings can now be disabled from the warning buffer. When a warning is displayed to the user, the resulting buffer now has diff --git a/lisp/icomplete.el b/lisp/icomplete.el index da589c0064..624818f613 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -140,6 +140,24 @@ icomplete-minibuffer-setup-hook :type 'hook :group 'icomplete) +(defvar icomplete-current-completions nil + "Current completion candidate list.") + +(defcustom icomplete-completions-filter-hook nil + "Filter the completion candidate list returned by `icomplete-completions'. + +This rook is run after Icomplete has stored the completion candidate list +in `icomplete-current-completions'. It is intended to filter that list. +For instance: + + (add-hook \\='icomplete-completions-filter-hook + (lambda () + (setq icomplete-current-completions + (substring-no-properties icomplete-current-completions)))) + +will remove all text properties from the completion candidates." + :type 'hook + :group 'icomplete) ;;;_* Initialization @@ -562,6 +580,48 @@ icomplete--sorted-completions (completion--cache-all-sorted-completions beg end (cons comp all)))) finally return all))) +(defun icomplete-vertical-reformat-completions () + "Reformat the completion candidates returned by `icomplete-completions'." + (save-match-data + (setq icomplete-current-completions + (if (string-match "^\\((.*)\\|\\[.*\\]\\)?{\\(\\(?:.\\|\n\\)+\\)}" + icomplete-current-completions) + (format "%s \n%s" + (or (match-string 1 icomplete-current-completions) "") + (match-string 2 icomplete-current-completions)) + icomplete-current-completions)))) + +(defun icomplete-vertical-minibuffer-setup () + "Setup the minibuffer for vertical display of completion candidates." + (setq-local redisplay-adhoc-scroll-in-resize-mini-windows nil)) + +;;;###autoload +(define-minor-mode icomplete-vertical-mode + "Toggle incremental minibuffer completion with vertical display. + +This global minor mode is identical to `icomplete-mode' (which see), +except that it displays the list of completions candidates vertically. + +As many completion candidates as possible are displayed, depending on +the value of `max-mini-window-height', and the way the mini-window is +resized depends on `resize-mini-windows'." + :global t :group 'icomplete + (remove-hook 'icomplete-minibuffer-setup-hook + #'icomplete-vertical-minibuffer-setup) + (remove-hook 'icomplete-completions-filter-hook + #'icomplete-vertical-reformat-completions) + (icomplete-mode -1) + (when icomplete-vertical-mode + (icomplete-mode 1) + (setq icomplete-separator "\n") + (setq icomplete-hide-common-prefix nil) + ;; ask `icomplete-completions' to return enough completions candidates + (setq icomplete-prospects-height 25) + (add-hook 'icomplete-minibuffer-setup-hook + #'icomplete-vertical-minibuffer-setup) + (add-hook 'icomplete-completions-filter-hook + #'icomplete-vertical-reformat-completions))) + @@ -782,13 +842,16 @@ icomplete-completions ;; Restore the base-size info, since completion-all-sorted-completions ;; is cached. (if last (setcdr last base-size)) - (if prospects - (concat determ - "{" - (mapconcat 'identity prospects icomplete-separator) - (and limit (concat icomplete-separator ellipsis)) - "}") - (concat determ " [Matched]")))))) + (setq icomplete-current-completions + (if prospects + (concat determ + "{" + (mapconcat 'identity prospects icomplete-separator) + (and limit (concat icomplete-separator ellipsis)) + "}") + (concat determ " [Matched]"))) + (run-hooks 'icomplete-completions-filter-hook) + icomplete-current-completions)))) ;;; Iswitchb compatibility -- 2.30.2