;;; icomplete.el --- minibuffer completion incremental feedback
-;; Copyright (C) 1992-1994, 1997, 1999, 2001-2012
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1992-1994, 1997, 1999, 2001-2013 Free Software
+;; Foundation, Inc.
;; Author: Ken Manheimer <klm@i.am>
;; Maintainer: Ken Manheimer <klm@i.am>
:type 'string
:version "24.4")
+(defcustom icomplete-hide-common-prefix t
+ "When non-nil, hide common prefix from completion candidates.
+When nil, show candidates in full."
+ :type 'boolean
+ :version "24.4"
+ :group 'icomplete)
+
+(defface icomplete-first-match '((t :weight bold))
+ "Face used by icomplete for highlighting first match."
+ :version "24.4"
+ :group 'icomplete)
+
;;;_* User Customization variables
(defcustom icomplete-prospects-height
;; 20 is an estimated common size for the prompt + minibuffer content, to
(let ((map (make-sparse-keymap)))
(define-key map [?\M-\t] 'minibuffer-force-complete)
(define-key map [?\C-j] 'minibuffer-force-complete-and-exit)
- (define-key map [?\C-s] 'icomplete-forward-completions)
- (define-key map [?\C-r] 'icomplete-backward-completions)
+ (define-key map [?\C-.] 'icomplete-forward-completions)
+ (define-key map [?\C-,] 'icomplete-backward-completions)
map))
(defun icomplete-forward-completions ()
(interactive)
(let* ((comps (completion-all-sorted-completions))
(last (last comps)))
- (setcdr last (cons (car comps) (cdr last)))
- (completion--cache-all-sorted-completions (cdr comps))))
+ (when comps
+ (setcdr last (cons (car comps) (cdr last)))
+ (completion--cache-all-sorted-completions (cdr comps)))))
(defun icomplete-backward-completions ()
"Step backward completions by one entry.
(let* ((comps (completion-all-sorted-completions))
(last-but-one (last comps 2))
(last (cdr last-but-one)))
- (when last
+ (when (consp last) ; At least two elements in comps
(setcdr last-but-one (cdr last))
(push (car last) comps)
(completion--cache-all-sorted-completions comps))))
((= compare (length name))
;; Typical case: name is a prefix.
(substring most compare))
- ((< compare 5) most)
- (t (concat "..." (substring most compare))))
+ ;; Don't bother truncating if it doesn't gain
+ ;; us at least 2 columns.
+ ((< compare 3) most)
+ (t (concat "…" (substring most compare))))
close-bracket)))
;;"-prospects" - more than one candidate
- (prospects-len (+ (length determ) 6 ;; take {,...} into account
- (string-width (buffer-string))))
+ (prospects-len (+ (string-width
+ (or determ (concat open-bracket close-bracket)))
+ (string-width icomplete-separator)
+ 3 ;; take {…} into account
+ (string-width (buffer-string))))
(prospects-max
;; Max total length to use, including the minibuffer content.
(* (+ icomplete-prospects-height
;; one line, increase the allowable space accordingly.
(/ prospects-len (window-width)))
(window-width)))
+ (prefix (when icomplete-hide-common-prefix
+ (try-completion "" comps)))
(prefix-len
;; Find the common prefix among `comps'.
;; We can't use the optimization below because its assumptions
;; ;; Common case.
;; (length most)
;; Else, use try-completion.
- (let ((comps-prefix (try-completion "" comps)))
- (and (stringp comps-prefix)
- (length comps-prefix)))) ;;)
-
- prospects most-is-exact comp limit)
+ (and (stringp prefix) (length prefix))) ;;)
+ prospects comp limit)
(if (eq most-try t) ;; (or (null (cdr comps))
(setq prospects nil)
+ (when (member name comps)
+ ;; NAME is complete but not unique. This scenario poses
+ ;; following UI issues:
+ ;;
+ ;; - When `icomplete-hide-common-prefix' is non-nil, NAME
+ ;; is stripped empty. This would make the entry
+ ;; inconspicuous.
+ ;;
+ ;; - Due to sorting of completions, NAME may not be the
+ ;; first of the prospects and could be hidden deep in
+ ;; the displayed string.
+ ;;
+ ;; - Because of `icomplete-prospects-height' , NAME may
+ ;; not even be displayed to the user.
+ ;;
+ ;; To circumvent all the above problems, provide a visual
+ ;; cue to the user via an "empty string" in the try
+ ;; completion field.
+ (setq determ (concat open-bracket "" close-bracket)))
+ ;; Compute prospects for display.
(while (and comps (not limit))
(setq comp
(if prefix-len (substring (car comps) prefix-len) (car comps))
comps (cdr comps))
- (cond ((string-equal comp "") (setq most-is-exact t))
- ((member comp prospects))
- (t (setq prospects-len
- (+ (string-width comp) 1 prospects-len))
+ (setq prospects-len
+ (+ (string-width comp)
+ (string-width icomplete-separator)
+ prospects-len))
(if (< prospects-len prospects-max)
(push comp prospects)
- (setq limit t))))))
+ (setq limit t))))
+ (setq prospects (nreverse prospects))
+ ;; Decorate first of the prospects.
+ (when prospects
+ (let ((first (copy-sequence (pop prospects))))
+ (put-text-property 0 (length first)
+ 'face 'icomplete-first-match first)
+ (push first prospects)))
;; Restore the base-size info, since completion-all-sorted-completions
;; is cached.
(if last (setcdr last base-size))
(if prospects
(concat determ
"{"
- (and most-is-exact
- (substring icomplete-separator
- (string-match "[^ ]" icomplete-separator)))
- (mapconcat 'identity (nreverse prospects)
- icomplete-separator)
+ (mapconcat 'identity prospects icomplete-separator)
(and limit (concat icomplete-separator "…"))
"}")
(concat determ " [Matched]"))))))