Download
(require 'icomplete)
(defvar completion-all-sorted-completions)
(defvar icomplete-eoinput)
(defvar icomplete-minibuffer-map)
(defvar icomplete-with-completion-tables)
(defvar icompletep-include-menu-items-flag)
(defvar icompletep-ORIG-icomplete-minibuffer-map)
(defvar icompletep-prospects-length)
(defvar icicle-nb-of-other-cycle-candidates)
(defgroup Icomplete-Plus nil
"Icomplete Enhancements."
:prefix "icompletep-"
:group 'completion :group 'convenience :group 'matching :group 'minibuffer
:link `(url-link :tag "Send Bug Report"
,(concat "mailto:" "drew.adams" "@" "oracle" ".com?subject=\
icomplete+.el bug: \
&body=Describe bug here, starting with `emacs -q'. \
Don't forget to mention your Emacs and library versions."))
:link '(url-link :tag "Other Libraries by Drew"
"http://www.emacswiki.org/cgi-bin/wiki/DrewsElispLibraries")
:link '(url-link :tag "Download"
"http://www.emacswiki.org/cgi-bin/wiki/icomplete+.el")
:link '(url-link :tag "Description"
"http://www.emacswiki.org/cgi-bin/wiki/IcompleteMode#IcompleteModePlus")
:link '(emacs-commentary-link :tag "Commentary" "icomplete+"))
(defcustom icompletep-exact-separator (if (> emacs-major-version 22)
(string ?\u2605 ?\ )
"* ")
"String used by to separate exact match from other alternatives."
:type 'string :group 'Icomplete-Plus)
(unless (boundp 'icomplete-show-key-bindings)
(defcustom icomplete-show-key-bindings t
"*Non-nil means show key bindings as well as completion for sole match."
:type 'boolean :group 'icomplete))
(when (boundp 'icomplete-show-key-bindings)
(defcustom icomplete-separator " | "
"String used to separate completion alternatives."
:type 'string :group 'icomplete :version "24.4"))
(when (< emacs-major-version 23)
(defcustom icompletep-prospects-length 100
"*Length of string displaying icompletion candidates."
:type 'integer :group 'Icomplete-Plus))
(when (> emacs-major-version 22)
(defcustom icompletep-include-menu-items-flag t
"*Non-nil means include menu bindings in the list of keys for a command."
:type 'boolean :group 'Icomplete-Plus))
(defface icompletep-choices
'((((background dark)) (:foreground "Snow4"))
(t (:foreground "DarkBlue")))
"*Face for minibuffer reminder of possible completion suffixes."
:group 'Icomplete-Plus)
(defface icompletep-determined
'((t (:foreground "SeaGreen")))
"*Face for minibuffer reminder of possible completion prefix."
:group 'Icomplete-Plus)
(defface icompletep-nb-candidates
'((((background dark)) (:foreground "SpringGreen"))
(t (:foreground "DarkMagenta")))
"*Face for minibuffer reminder of number of completion candidates.
This has no effect unless library `icicles.el' is being used."
:group 'Icomplete-Plus)
(defface icompletep-keys
'((t (:foreground "Red")))
"*Face for minibuffer reminder of possible completion key bindings."
:group 'Icomplete-Plus)
(defvar icomplete-overlay)
(defvar icomplete-prospects-height)
(when (< emacs-major-version 23)
(defun icomplete-exhibit ()
"Insert icomplete completions display.
Should be run via minibuffer `post-command-hook'.
See `icomplete-mode' and `minibuffer-setup-hook'."
(when (icomplete-simple-completing-p)
(save-match-data
(let* ((minibuf-begin (if (< emacs-major-version 21)
(point-min)
(minibuffer-prompt-end)))
(contents (buffer-substring minibuf-begin (point-max)))
(buffer-undo-list t))
(save-excursion
(goto-char (point-max))
(unless (boundp 'icomplete-eoinput)
(make-local-variable 'icomplete-eoinput))
(setq icomplete-eoinput (point))
(when (and (> (point-max) minibuf-begin)
(save-excursion
(goto-char minibuf-begin)
(not (looking-at
"\\(\\s-+$\\|\\s-*\\(\\s(\\|\\s\"\\|\\s'\\|\\s<\\|[0-9]\\)\\)")))
(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
(icomplete-completions contents minibuffer-completion-table
minibuffer-completion-predicate
(not minibuffer-completion-confirm)))))
(setq deactivate-mark nil))))))
(unless (fboundp 'with-local-quit)
(defmacro with-local-quit (&rest body)
"Execute BODY, allowing quits to terminate BODY but not escape further.
When a quit terminates BODY, `with-local-quit' returns nil but
requests another quit. That quit will be processed as soon as quitting
is allowed once again. (Immediately, if `inhibit-quit' is nil.)"
`(condition-case nil
(let ((inhibit-quit nil))
,@body)
(quit (setq quit-flag t)
(eval '(ignore nil)))))
(put 'with-local-quit 'common-lisp-indent-function '(&body)))
(unless (fboundp 'while-no-input)
(defmacro while-no-input (&rest body)
"Execute BODY only as long as there's no pending input.
If input arrives, that ends the execution of BODY,
and `while-no-input' returns t. Quitting makes it return nil.
If BODY finishes, `while-no-input' returns whatever value BODY produced."
(let ((catch-sym (make-symbol "input")))
`(with-local-quit
(catch ',catch-sym
(let ((throw-on-input ',catch-sym))
(or (input-pending-p) (progn ,@body)))))))
(put 'while-no-input 'common-lisp-indent-function '(&body)))
(defun icomplete-get-keys (func-name &optional exactp)
"Return strings naming keys bound to FUNC-NAME, or nil if none.
Examines the prior, not current, buffer, presuming that current buffer
is minibuffer.
Non-nil optional arg EXACTP means FUNC-NAME is an exact match, as
determined by `try-completion' or `completion-try-completion.
If option `icompletep-include-menu-items-flag' is non-nil then include
menu-bar bindings in the l of keys (Emacs 23+ only)."
(when (commandp func-name)
(save-excursion
(let* ((sym (intern func-name))
(buf (other-buffer nil t))
(keys (with-current-buffer buf (where-is-internal sym)))
(max-len (max 0 (- (window-width)
(if (fboundp 'minibuffer-prompt-end)
(minibuffer-prompt-end)
(point-max))
(if (fboundp 'minibuffer-prompt-end) (length func-name) 0)
(if exactp 7 9)
5))))
(when keys
(unless (and (boundp 'icompletep-include-menu-items-flag)
icompletep-include-menu-items-flag)
(setq keys (icompletep-remove-if (lambda (ky)
(and (vectorp ky) (eq (aref ky 0) 'menu-bar)))
keys)))
(setq keys (mapconcat 'key-description
(sort keys #'(lambda (x y) (< (length x) (length y))))
", "))
(cond ((zerop max-len) (setq keys 'TOO-LONG))
((> (length keys) max-len)
(setq keys (concat (substring keys 0 (max 0 (- max-len 5))) "...")))))
keys))))
(defun icompletep-remove-if (pred xs)
"A copy of list XS with no elements that satisfy predicate PRED."
(let ((result ()))
(dolist (x xs) (unless (funcall pred x) (push x result)))
(nreverse result)))
(when (> emacs-major-version 22)
(defun icomplete-exhibit ()
"Insert icomplete completions display.
Should be run via minibuffer `post-command-hook'. See `icomplete-mode'
and `minibuffer-setup-hook'."
(when (and icomplete-mode (icomplete-simple-completing-p))
(save-excursion
(goto-char (point-max))
(when (and (> (point-max) (minibuffer-prompt-end))
buffer-undo-list
(save-excursion
(goto-char (minibuffer-prompt-end))
(save-match-data
(not (looking-at
"\\(\\s-+$\\|\\s-*\\(\\s(\\|\\s\"\\|\\s'\\|\\s<\\|[0-9]\\)\\)"))))
(or
(> (- (point) (field-beginning)) icomplete-max-delay-chars)
completion-all-sorted-completions
(and (sequencep minibuffer-completion-table)
(< (length minibuffer-completion-table)
icomplete-delay-completions-threshold))
(sit-for icomplete-compute-delay)))
(let ((text (while-no-input (icomplete-completions
(field-string)
minibuffer-completion-table
minibuffer-completion-predicate
(not minibuffer-completion-confirm))))
(buffer-undo-list t)
deactivate-mark)
(when (stringp text)
(move-overlay icomplete-overlay (point) (point) (current-buffer))
(put-text-property 0 1 'cursor t text)
(overlay-put icomplete-overlay 'after-string text))))))))
(when (< emacs-major-version 23)
(defun icomplete-completions (name candidates predicate require-match)
"Identify prospective candidates for minibuffer completion.
NAME is the name to complete.
CANDIDATES are the candidates to match.
PREDICATE filters matches: they succeed only if it returns non-nil.
REQUIRE-MATCH non-nil means the input must match a candidate.
The display is updated with each minibuffer keystroke during
minibuffer completion.
Prospective completion suffixes (if any) are displayed, bracketed by
\"()\", \"[]\", or \"{}\". The choice of brackets is as follows:
\(...) - A single prospect is identified, and matching is enforced.
\[...] - A single prospect is identified, and matching is optional.
\{...} - Multiple prospects are indicated, and further input is
needed 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
shown within brackets, [] (without the word \"Matched\"), if there is
room.
When more than one completion is available, the total number precedes
the suffixes display, like this:
M-x forw 14 (ard-) { char line list...}
If library `icicles.el' is also loaded, then you can cycle
completions. When you change cycling direction, the number of
additional cycle candidates, besides the current one, is displayed
following the rest of the icomplete info:
M-x forward-line [Matched] (13 more)."
(when (and (listp candidates) (null (car candidates))) (setq candidates ()))
(let* ((comps (all-completions name candidates predicate))
(open-bracket-determined (if require-match "(" " ["))
(close-bracket-determined (if require-match ") " "] "))
(keys ())
(nb-candidates (length comps))
nb-candidates-string)
(if (null comps) (format (if (fboundp 'icicle-apropos-complete)
"\t%sNo prefix matches%s"
"\t%sNo matches%s")
open-bracket-determined
close-bracket-determined)
(let* ((most-try (try-completion name (mapcar #'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)
prompt prompt-rest prospects most-is-exact comp)
(when determ
(put-text-property 0 (length determ) 'face 'icompletep-determined determ))
(if (eq most-try t)
(setq prospects ())
(while (and comps (< prospects-len icompletep-prospects-length))
(setq comp (substring (car comps) most-len)
comps (cdr comps))
(cond ((string= comp "") (setq most-is-exact t))
((member comp prospects))
(t (setq prospects (cons comp prospects)
prospects-len (+ prospects-len
(string-width comp)
(string-width icomplete-separator)))))))
(setq prompt-rest
(if prospects
(concat open-bracket-prospects
(and most-is-exact icompletep-exact-separator)
(mapconcat 'identity (sort prospects (function string-lessp))
icomplete-separator)
(and comps "...")
close-bracket-prospects)
(setq keys (and icomplete-show-key-bindings
(commandp (intern-soft most))
(icomplete-get-keys most (eq t most-try))))
(if (eq keys 'TOO-LONG)
""
(concat " [ " (and (not keys) "Matched") keys " ]"))))
(unless (string= "" prompt-rest)
(put-text-property 0 (length prompt-rest) 'face 'icompletep-choices prompt-rest))
(cond ((< nb-candidates 2)
(setq prompt (concat " " determ prompt-rest))
(when (eq last-command this-command)
(setq icicle-nb-of-other-cycle-candidates 0)))
(t
(setq nb-candidates-string (format "%7d " nb-candidates))
(put-text-property (string-match "\\S-" nb-candidates-string)
(1- (length nb-candidates-string))
'face 'icompletep-nb-candidates nb-candidates-string)
(setq prompt (concat nb-candidates-string determ prompt-rest))))
(when (stringp keys)
(put-text-property (+ 9 (length determ)) (1- (length prompt))
'face 'icompletep-keys prompt))
(when (and (boundp 'icicle-last-completion-candidate)
(> icicle-nb-of-other-cycle-candidates 0)
(= 1 nb-candidates)
icicle-last-completion-candidate
(not (eq last-command this-command)))
(setq nb-candidates-string
(format " (%d more)" icicle-nb-of-other-cycle-candidates))
(put-text-property (string-match "\\S-" nb-candidates-string)
(length nb-candidates-string)
'face 'icompletep-nb-candidates nb-candidates-string)
(setq prompt (concat prompt nb-candidates-string)))
prompt)))))
(when (= emacs-major-version 23)
(defun icomplete-completions (name collection predicate require-match)
"Identify prospective candidates for minibuffer completion.
NAME is the name to complete.
COLLECTION is the collection of candidates to match.
PREDICATE filters matches: they succeed only if it returns non-nil.
REQUIRE-MATCH non-nil means the input must match a candidate.
The display is updated with each minibuffer keystroke during
minibuffer completion.
Prospective completion suffixes (if any) are displayed, bracketed by
\"()\", \"[]\", or \"{}\". The choice of brackets is as follows:
\(...) - A single prospect is identified, and matching is enforced.
\[...] - A single prospect is identified, and matching is optional.
\{...} - Multiple prospects are indicated, and further input is
needed 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
shown within brackets, [] (without the word \"Matched\"), if there is
room.
When more than one completion is available, the total number precedes
the suffixes display, like this:
M-x forw 14 (ard-) { char line list...}
If library `icicles.el' is also loaded, then you can cycle
completions. When you change cycling direction, the number of
additional cycle candidates, besides the current one, is displayed
following the rest of the icomplete info:
M-x forward-line [Matched] (13 more)."
(when (and (listp collection) (null (car collection))) (setq collection ()))
(let* (
(comps (if (and minibuffer-completing-file-name
icomplete-with-completion-tables)
(completion-pcm--filename-try-filter
(all-completions name collection predicate))
(all-completions name collection predicate)))
(nb-candidates (length comps))
(nb-cands-string (if (< nb-candidates 2) "" (format "%7d " nb-candidates)))
(open-bracket (if require-match "(" " ["))
(close-bracket (if require-match ") " "] ")))
(if (not (consp comps))
(format (if (fboundp 'icicle-apropos-complete)
"\t%sNo prefix matches%s"
"\t%sNo matches%s")
open-bracket close-bracket)
(let* ((keys ())
(most-try
(try-completion name collection predicate))
(most (if (stringp most-try) most-try (car comps)))
(compare (compare-strings name nil nil most nil nil
completion-ignore-case))
(determ (and (not (or (eq t compare) (eq t most-try)
(= (setq compare (1- (abs compare))) (length most))))
(concat open-bracket
(cond ((= compare (length name))
(substring most compare))
((< compare 5) most)
(t (concat "..." (substring most compare))))
close-bracket)))
(prospects-len (+ (if (and (boundp 'icicle-mode) icicle-mode (icicle-completing-p))
2
0)
(string-width (buffer-string))
(string-width nb-cands-string)
(length determ)
2
-2
5))
(prospects-max
(* (+ icomplete-prospects-height
(/ prospects-len (window-width)))
(window-width)))
(prefix-len
(let ((comps-prefix (try-completion "" comps)))
(and (stringp comps-prefix) (string-width comps-prefix))))
prompt prompt-rest prospects most-is-exact comp limit)
(when determ
(put-text-property 0 (length determ) 'face 'icompletep-determined determ))
(if (eq most-try t)
(setq prospects ())
(while (and comps (not limit))
(setq comp (if prefix-len (substring (car comps) prefix-len) (car comps))
comps (cdr comps))
(cond ((string= comp "") (setq most-is-exact t))
((member comp prospects))
(t (setq prospects-len (+ (string-width comp)
(string-width icomplete-separator)
prospects-len))
(if (< prospects-len prospects-max)
(push comp prospects)
(setq limit t))))))
(setq prompt-rest
(if prospects
(concat "{ " (and most-is-exact icompletep-exact-separator)
(mapconcat 'identity (sort prospects (function string-lessp))
icomplete-separator)
(and limit "...")
" }")
(setq keys (and icomplete-show-key-bindings
(commandp (intern-soft most))
(icomplete-get-keys most (eq t most-try))))
(if (eq keys 'TOO-LONG)
""
(concat " [ " (and (not keys) "Matched") keys " ]"))))
(unless (string= "" prompt-rest)
(put-text-property 0 (length prompt-rest) 'face 'icompletep-choices prompt-rest))
(cond ((< nb-candidates 2)
(setq prompt (concat " " determ prompt-rest))
(when (eq last-command this-command)
(setq icicle-nb-of-other-cycle-candidates 0)))
(t
(put-text-property (string-match "\\S-" nb-cands-string)
(1- (length nb-cands-string))
'face 'icompletep-nb-candidates nb-cands-string)
(setq prompt (concat nb-cands-string determ prompt-rest))))
(when (stringp keys)
(put-text-property (+ 9 (length determ)) (1- (length prompt))
'face 'icompletep-keys prompt))
(when (and (boundp 'icicle-last-completion-candidate)
(> icicle-nb-of-other-cycle-candidates 0)
(= 1 nb-candidates)
icicle-last-completion-candidate
(not (eq last-command this-command)))
(setq nb-cands-string
(format " (%d more)" icicle-nb-of-other-cycle-candidates))
(put-text-property (string-match "\\S-" nb-cands-string)
(length nb-cands-string)
'face 'icompletep-nb-candidates nb-cands-string)
(setq prompt (concat prompt nb-cands-string)))
prompt)))))
(when (> emacs-major-version 23)
(defun icomplete-completions (name candidates predicate require-match)
"Identify prospective candidates for minibuffer completion.
NAME is the name to complete.
CANDIDATES is the collection of candidates to match. See
`completing-read' for its possible values.
PREDICATE filters matches: they succeed only if it returns non-nil.
REQUIRE-MATCH non-nil means the input must match a candidate.
The display is updated with each minibuffer keystroke during
minibuffer completion.
Prospective completion suffixes (if any) are displayed, bracketed by
\"()\", \"[]\", or \"{}\". The choice of brackets is as follows:
\(...) - A single prospect is identified, and matching is enforced.
\[...] - A single prospect is identified, and matching is optional.
\{...} - Multiple prospects are indicated, and further input is
needed 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
shown within brackets, [] (without the word \"Matched\"), if there is
room.
When more than one completion is available, the total number precedes
the suffixes display, like this:
M-x forw 14 (ard-) { char line list...}
In Icicle mode:
* The current Icicles sort order is used.
* When cycling candidates and you change direction, the number of
other cycling candidates is shown, as `(N more)'. For example:
M-x forward-line [Matched] (13 more)."
(let* ((non-essential t)
(icyp (and (fboundp 'icicle-mode) icicle-mode))
(open-bracket (if require-match "(" " ["))
(close-bracket (if require-match ") " "] "))
(md (completion--field-metadata (field-beginning)))
(comps (icompletep-completion-all-sorted-completions
(and icyp #'icicle-reversible-sort)))
(last (and (consp comps) (last comps)))
(base-size (cdr last))
nb-candidates nb-cands-string)
(if (not (consp comps))
(format "\t%sNo matches%s" open-bracket close-bracket)
(when last (setcdr last ()))
(setq nb-candidates (length comps)
nb-cands-string (if (< nb-candidates 2) "" (format "%7d " nb-candidates)))
(let* ((most-try (if (and base-size (> base-size 0))
(completion-try-completion name candidates predicate
(length name) md)
(completion-try-completion name comps nil (length name) md)))
(most (if (consp most-try) (car most-try) (if most-try (car comps) "")))
(compare (compare-strings name nil nil most nil nil completion-ignore-case))
(determ (and (not (or (eq t compare) (eq t most-try)
(= (setq compare (1- (abs compare))) (length most))))
(concat open-bracket
(cond ((= compare (length name))
(substring most compare))
((< compare 5) most)
(t (concat "..." (substring most compare))))
close-bracket)))
(prospects-len (+ (if (and icyp (icicle-completing-p))
2
0)
(string-width (buffer-string))
(string-width nb-cands-string)
(length determ)
2
-2
5))
(prospects-max (* (+ icomplete-prospects-height
(/ prospects-len (window-width)))
(window-width)))
(prefix-len (let ((comps-prefix (try-completion "" comps)))
(and (stringp comps-prefix) (string-width comps-prefix))))
(prospects ())
(keys ())
(limit nil)
(most-is-exact nil)
prompt prompt-rest comp)
(when determ (put-text-property 0 (length determ) 'face 'icompletep-determined determ))
(if (eq most-try t)
(setq prospects ())
(while (and comps (not limit))
(setq comp (if prefix-len (substring (car comps) prefix-len) (car comps))
comps (cdr comps))
(cond ((string= comp "") (setq most-is-exact t))
((member comp prospects))
(t (setq prospects-len (+ (string-width comp)
(string-width icomplete-separator)
prospects-len))
(if (< prospects-len prospects-max) (push comp prospects) (setq limit t))))))
(when last (setcdr last base-size))
(setq prompt-rest
(if prospects
(concat "{ " (and most-is-exact icompletep-exact-separator)
(mapconcat 'identity (nreverse prospects) icomplete-separator)
(and limit "...")
" }")
(setq keys (and icomplete-show-key-bindings
(commandp (intern-soft most))
(icomplete-get-keys most (eq t most-try))))
(if (eq keys 'TOO-LONG)
""
(concat " [ " (and (not keys) "Matched") keys " ]"))))
(unless (string= "" prompt-rest)
(put-text-property 0 (length prompt-rest) 'face 'icompletep-choices prompt-rest))
(cond ((< nb-candidates 2)
(setq prompt (concat " " determ prompt-rest))
(when (eq last-command this-command)
(setq icicle-nb-of-other-cycle-candidates 0)))
(t
(put-text-property (string-match "\\S-" nb-cands-string)
(1- (length nb-cands-string))
'face 'icompletep-nb-candidates nb-cands-string)
(setq prompt (concat nb-cands-string determ prompt-rest))))
(when (stringp keys)
(put-text-property (+ 9 (length determ)) (1- (length prompt))
'face 'icompletep-keys prompt))
(when (and (boundp 'icicle-last-completion-candidate)
(> icicle-nb-of-other-cycle-candidates 0)
(= 1 nb-candidates)
icicle-last-completion-candidate
(not (eq last-command this-command)))
(setq nb-cands-string
(format " (%d more)" icicle-nb-of-other-cycle-candidates))
(put-text-property (string-match "\\S-" nb-cands-string) (length nb-cands-string)
'face 'icompletep-nb-candidates nb-cands-string)
(setq prompt (concat prompt nb-cands-string)))
prompt))))
(defun icompletep-completion-all-sorted-completions (&optional sort-function dont-remove-dups)
"Like `completion-all-sorted-completions', but with added optional args.
If SORT-FUNCTION is nil, sort per `completion-all-sorted-completions':
* per property `cycle-sort-function', if defined
* else by shorter length, then by recent use."
(or completion-all-sorted-completions
(let* ((start (field-beginning))
(end (field-end))
(string (buffer-substring start end))
(md (completion--field-metadata start))
(all (completion-all-completions string minibuffer-completion-table
minibuffer-completion-predicate
(- (point) start) md))
(last (last all))
(base-size (or (cdr last) 0))
(all-md (completion--metadata (buffer-substring-no-properties start (point))
base-size md minibuffer-completion-table
minibuffer-completion-predicate))
(sort-fun (or sort-function
(completion-metadata-get all-md 'cycle-sort-function))))
(when last
(setcdr last ())
(when (or minibuffer-completing-file-name
(and (boundp 'icicle-abs-file-candidates) icicle-abs-file-candidates))
(setq all (delete-if (lambda (fl)
(string-match-p (regexp-opt completion-ignored-extensions) fl))
all)))
(unless dont-remove-dups (setq all (delete-dups all)))
(setq last (last all)
all (if sort-fun
(funcall sort-fun all)
(sort all (lambda (c1 c2) (< (length c1) (length c2))))))
(when (and (minibufferp) (not sort-fun))
(let ((hist (symbol-value minibuffer-history-variable)))
(setq all (sort all (lambda (c1 c2) (> (length (member c1 hist))
(length (member c2 hist))))))))
(completion--cache-all-sorted-completions (nconc all base-size)))))))
(defvar icompletep-cycling-mode nil)
(when (boundp 'icomplete-minibuffer-map)
(setq icompletep-ORIG-icomplete-minibuffer-map icomplete-minibuffer-map
icomplete-minibuffer-map nil)
(eval '(define-minor-mode icompletep-cycling-mode
"Icomplete mode, with its cycling keys enabled if on, disabled if off.
If off then the cycling keys of Icomplete mode are free for their
normal minibuffer uses. The default Icomplete-mode cycling keys are:
M-TAB\t- complete to exact match, repeat to cycle
C-j\t- complete to first match and exit minibuffer
C-s\t- cycle first entry to end
C-r\t- cycle last entry to start
If you want Icomplete cycling behavior but do not want to use these
keys for it, customize the bindings in `icomplete-minibuffer-map'.
Turning this mode on also turns on Icomplete mode.
Turning it off does not turn Icomplete mode on or off."
nil nil nil
(when icompletep-cycling-mode (icomplete-mode 99))
(setq icomplete-minibuffer-map (and icompletep-cycling-mode
icompletep-ORIG-icomplete-minibuffer-map))))
(icompletep-cycling-mode -99))
(provide 'icomplete+)