(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-prospects-length 80
"*Length of string displaying the prospects."
:type 'integer
:group '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 features and packages. For instance:
\(add-hook 'icomplete-minibuffer-setup-hook
\(function
\(lambda ()
\(make-local-variable 'max-mini-window-height)
\(setq max-mini-window-height 3))))
will constrain Emacs 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 arg)
"Toggle incremental minibuffer completion for this Emacs session.
With a numeric argument, turn Icomplete mode on iff ARG is positive."
(interactive "P")
(let ((on-p (if (null arg)
(not icomplete-mode)
(> (prefix-numeric-value arg) 0))))
(setq icomplete-mode on-p)
(when on-p
(add-hook 'minibuffer-setup-hook 'icomplete-minibuffer-setup))))
(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 (minibuffer-prompt-end)(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 ")" "]")))
(if (null comps) (format " %sNo matches%s"
open-bracket-determined
close-bracket-determined)
(let* ((most-try (try-completion name (mapcar (function list) comps)))
(most (if (stringp most-try) most-try (car comps)))
(most-len (length most))
(determ (and (> most-len (length name))
(concat open-bracket-determined
(substring most (length name))
close-bracket-determined)))
(open-bracket-prospects "{")
(close-bracket-prospects "}")
(prospects-len 0)
prospects most-is-exact comp)
(if (eq most-try t)
(setq prospects nil)
(while (and comps (< prospects-len icomplete-prospects-length))
(setq comp (substring (car comps) most-len)
comps (cdr comps))
(cond ((string-equal comp "") (setq most-is-exact t))
((member comp prospects))
(t (setq prospects (cons comp prospects)
prospects-len (+ (length comp) 1 prospects-len))))))
(if prospects
(concat determ
open-bracket-prospects
(and most-is-exact ",")
(mapconcat 'identity
(sort prospects (function string-lessp))
",")
(and comps ",...")
close-bracket-prospects)
(concat determ
" [Matched"
(let ((keys (and icomplete-show-key-bindings
(commandp (intern-soft most))
(icomplete-get-keys most))))
(if keys
(concat "; " keys)
""))
"]"))))))
(if icomplete-mode
(icomplete-mode 1))