(provide 'icomplete)
(defgroup icomplete nil
"Show completions dynamically in minibuffer."
:prefix "icomplete-"
:group 'minibuffer)
(defcustom icomplete-mode nil
"Toggle incremental minibuffer completion.
As text is typed into the minibuffer, prospective completions are indicated
in the minibuffer.
Setting this variable directly does not take effect;
use either \\[customize] or the function `icomplete-mode'."
:set (lambda (symbol value)
(icomplete-mode (if value 1 -1)))
:initialize 'custom-initialize-default
:type 'boolean
:group 'icomplete
:require 'icomplete)
(defcustom icomplete-compute-delay .3
"*Completions-computation stall, used only with large-number
completions - see `icomplete-delay-completions-threshold'."
:type 'number
:group 'icomplete)
(defcustom icomplete-delay-completions-threshold 400
"*Pending-completions number over which to apply icomplete-compute-delay."
:type 'integer
:group 'icomplete)
(defcustom icomplete-max-delay-chars 3
"*Maximum number of initial chars to apply icomplete compute delay."
:type 'integer
:group 'icomplete)
(defcustom icomplete-show-key-bindings t
"*If non-nil, show key bindings as well as completion for sole matches."
:type 'boolean
:group 'icomplete)
(defcustom icomplete-minibuffer-setup-hook nil
"*Icomplete-specific customization of minibuffer setup.
This hook is run during minibuffer setup iff icomplete will be active.
It is intended for use in customizing icomplete for interoperation
with other packages. For instance:
\(add-hook 'icomplete-minibuffer-setup-hook
\(function
\(lambda ()
\(make-local-variable 'resize-minibuffer-window-max-height)
\(setq resize-minibuffer-window-max-height 3))))
will constrain rsz-mini to a maximum minibuffer height of 3 lines when
icompletion is occurring."
:type 'hook
:group 'icomplete)
(defvar icomplete-eoinput 1
"Point where minibuffer input ends and completion info begins.")
(make-variable-buffer-local 'icomplete-eoinput)
(defvar icomplete-pre-command-hook nil
"Incremental-minibuffer-completion pre-command-hook.
Is run in minibuffer before user input when `icomplete-mode' is non-nil.
Use `icomplete-mode' function to set it up properly for incremental
minibuffer completion.")
(add-hook 'icomplete-pre-command-hook 'icomplete-tidy)
(defvar icomplete-post-command-hook nil
"Incremental-minibuffer-completion post-command-hook.
Is run in minibuffer after user input when `icomplete-mode' is non-nil.
Use `icomplete-mode' function to set it up properly for incremental
minibuffer completion.")
(add-hook 'icomplete-post-command-hook 'icomplete-exhibit)
(defun icomplete-get-keys (func-name)
"Return strings naming keys bound to `func-name', or nil if none.
Examines the prior, not current, buffer, presuming that current buffer
is minibuffer."
(if (commandp func-name)
(save-excursion
(let* ((sym (intern func-name))
(buf (other-buffer))
(map (save-excursion (set-buffer buf) (current-local-map)))
(keys (where-is-internal sym map)))
(if keys
(concat "<"
(mapconcat 'key-description
(sort keys
#'(lambda (x y)
(< (length x) (length y))))
", ")
">"))))))
(defun icomplete-mode (&optional prefix)
"Activate incremental minibuffer completion for this Emacs session.
Deactivates with negative universal argument."
(interactive "p")
(or prefix (setq prefix 0))
(cond ((>= prefix 0)
(setq icomplete-mode t)
(add-hook 'minibuffer-setup-hook 'icomplete-minibuffer-setup))
(t (setq icomplete-mode nil))))
(defun icomplete-simple-completing-p ()
"Non-nil if current window is minibuffer that's doing simple completion.
Conditions are:
the selected window is a minibuffer,
and not in the middle of macro execution,
and minibuffer-completion-table is not a symbol (which would
indicate some non-standard, non-simple completion mechanism,
like file-name and other custom-func completions)."
(and (window-minibuffer-p (selected-window))
(not executing-kbd-macro)
(not (symbolp minibuffer-completion-table))))
(defun icomplete-minibuffer-setup ()
"Run in minibuffer on activation to establish incremental completion.
Usually run by inclusion in `minibuffer-setup-hook'."
(cond ((and icomplete-mode (icomplete-simple-completing-p))
(make-local-hook 'pre-command-hook)
(add-hook 'pre-command-hook
(function (lambda ()
(run-hooks 'icomplete-pre-command-hook)))
nil t)
(make-local-hook 'post-command-hook)
(add-hook 'post-command-hook
(function (lambda ()
(run-hooks 'icomplete-post-command-hook)))
nil t)
(run-hooks 'icomplete-minibuffer-setup-hook))))
(defun icomplete-tidy ()
"Remove completions display \(if any) prior to new user input.
Should be run in on the minibuffer `pre-command-hook'. See `icomplete-mode'
and `minibuffer-setup-hook'."
(if (icomplete-simple-completing-p)
(if (and (boundp 'icomplete-eoinput)
icomplete-eoinput)
(if (> icomplete-eoinput (point-max))
(setq icomplete-eoinput (point-max))
(let ((buffer-undo-list buffer-undo-list )) (delete-region icomplete-eoinput (point-max))))
(make-local-variable 'icomplete-eoinput)
(setq icomplete-eoinput 1))))
(defun icomplete-exhibit ()
"Insert icomplete completions display.
Should be run via minibuffer `post-command-hook'. See `icomplete-mode'
and `minibuffer-setup-hook'."
(if (icomplete-simple-completing-p)
(let ((contents (buffer-substring (point-min)(point-max)))
(buffer-undo-list t))
(save-excursion
(goto-char (point-max))
(if (not (boundp 'icomplete-eoinput))
(make-local-variable 'icomplete-eoinput))
(setq icomplete-eoinput (point))
(if (and (> (point-max) 1)
(or
(> (point-max) icomplete-max-delay-chars)
(if minibuffer-completion-table
(cond ((numberp minibuffer-completion-table)
(< minibuffer-completion-table
icomplete-delay-completions-threshold))
((sequencep minibuffer-completion-table)
(< (length minibuffer-completion-table)
icomplete-delay-completions-threshold))
))
(sit-for icomplete-compute-delay)))
(insert-string
(icomplete-completions contents
minibuffer-completion-table
minibuffer-completion-predicate
(not
minibuffer-completion-confirm))))))))
(defun icomplete-completions (name candidates predicate require-match)
"Identify prospective candidates for minibuffer completion.
The display is updated with each minibuffer keystroke during
minibuffer completion.
Prospective completion suffixes (if any) are displayed, bracketed by
one of \(), \[], or \{} pairs. The choice of brackets is as follows:
\(...) - a single prospect is identified and matching is enforced,
\[...] - a single prospect is identified but matching is optional, or
\{...} - multiple prospects, separated by commas, are indicated, and
further input is required to distinguish a single one.
The displays for unambiguous matches have ` [Matched]' appended
\(whether complete or not), or ` \[No matches]', if no eligible
matches exist. \(Keybindings for uniquely matched commands
are exhibited within the square braces.)"
(if (and (listp candidates) (null (car candidates)))
(setq candidates nil))
(let ((comps (all-completions name candidates predicate))
(open-bracket-determined (if require-match "(" "["))
(close-bracket-determined (if require-match ")" "]"))
(open-bracket-prospects "{")
(close-bracket-prospects "}")
)
(catch 'input
(cond ((null comps) (format " %sNo matches%s"
open-bracket-determined
close-bracket-determined))
((null (cdr comps)) (concat (if (and (> (length (car comps))
(length name)))
(concat open-bracket-determined
(substring (car comps) (length name))
close-bracket-determined)
"")
" [Matched"
(let ((keys (and icomplete-show-key-bindings
(commandp (intern-soft (car comps)))
(icomplete-get-keys (car comps)))))
(if keys
(concat "; " keys)
""))
"]"))
(t (let* ((most
(try-completion name candidates
(and predicate
(function
(lambda (item)
(if (input-pending-p)
(throw 'input "")
(apply predicate
item nil)))))))
(most-len (length most))
most-is-exact
(alternatives
(substring
(apply (function concat)
(mapcar (function
(lambda (com)
(if (input-pending-p)
(throw 'input ""))
(if (= (length com) most-len)
(progn
(setq most-is-exact t)
())
(concat ","
(substring com
most-len)))))
comps))
1)))
(concat (and (> most-len (length name))
(concat open-bracket-determined
(substring most (length name))
close-bracket-determined))
open-bracket-prospects
(if most-is-exact
(concat "," alternatives)
alternatives)
close-bracket-prospects)))))))
(if icomplete-mode
(icomplete-mode 1))