From 93278cb687a2ab25ed67fde026224e6b7d00be70 Mon Sep 17 00:00:00 2001 From: Gregory Heytings Date: Tue, 6 Apr 2021 14:42:25 +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 | 12 +++++-- etc/NEWS | 12 +++++++ lisp/icomplete.el | 82 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 97 insertions(+), 9 deletions(-) diff --git a/doc/emacs/buffers.texi b/doc/emacs/buffers.texi index 3a166e404a..e82bada391 100644 --- a/doc/emacs/buffers.texi +++ b/doc/emacs/buffers.texi @@ -718,6 +718,7 @@ rule or another is easier for you to remember and apply quickly. @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 @@ of directories. 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, also type @kbd{M-x icomplete-vertical-mode}, +or customize the variable @code{icomplete-vertical-mode} to @code{t}. @findex fido-mode @cindex fido mode @@ -763,7 +767,11 @@ your initialization file (@pxref{Init File}): To enable Fido mode, type @kbd{M-x fido-mode}, or customize the variable @code{fido-mode} to @code{t} (@pxref{Easy -Customization}). +Customization}). Like Icomplete mode, Fido mode displays the list of +possible completions on the same line as the prompt. To display the +completion candidates vertically under the prompt, also type +@kbd{M-x icomplete-vertical-mode}, or customize the variable +@code{icomplete-vertical-mode} to @code{t}. @node Buffer Menus @subsection Customizing Buffer Menus diff --git a/etc/NEWS b/etc/NEWS index c8400ba8c2..327c73e73c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -477,6 +477,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 intended to be used with Icomplete or Fido, to display the +list of completions candidates vertically instead of horizontally. + ++++ +*** 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..ec8ad68972 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -140,6 +140,25 @@ icompletion is occurring." :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 + :version "28.1") ;;;_* Initialization @@ -562,6 +581,52 @@ Usually run by inclusion in `minibuffer-setup-hook'." (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)) + +(defvar icomplete--vertical-saved-values nil) + +;;;###autoload +(define-minor-mode icomplete-vertical-mode + "Toggle the use of vertical display in `icomplete-mode'. + +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 + (when icomplete--vertical-saved-values + (eval `(setq ,@icomplete--vertical-saved-values)) + (setq icomplete--vertical-saved-value nil)) + (remove-hook 'icomplete-minibuffer-setup-hook + #'icomplete--vertical-minibuffer-setup) + (remove-hook 'icomplete-completions-filter-hook + #'icomplete--vertical-reformat-completions) + (when icomplete-vertical-mode + (setq icomplete--vertical-saved-values + (list 'icomplete-separator icomplete-separator + 'icomplete-hide-common-prefix icomplete-hide-common-prefix + 'icomplete-prospects-height icomplete-prospects-height)) + (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 +847,16 @@ matches exist." ;; 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