HideIfDef mode bug fixes and enhancements. This is #2 of 3 patches based
[bpt/emacs.git] / lisp / icomplete.el
index 0493a5b..0c5a2ba 100644 (file)
@@ -1,12 +1,11 @@
 ;;; icomplete.el --- minibuffer completion incremental feedback
 
 ;;; icomplete.el --- minibuffer completion incremental feedback
 
-;; Copyright (C) 1992-1994, 1997, 1999, 2001-2013 Free Software
-;; Foundation, Inc.
+;; Copyright (C) 1992-1994, 1997, 1999, 2001-2014
+;;   Free Software Foundation, Inc.
 
 ;; Author: Ken Manheimer <klm@i.am>
 ;; Maintainer: Ken Manheimer <klm@i.am>
 ;; Created: Mar 1993 Ken Manheimer, klm@nist.gov - first release to usenet
 
 ;; Author: Ken Manheimer <klm@i.am>
 ;; Maintainer: Ken Manheimer <klm@i.am>
 ;; Created: Mar 1993 Ken Manheimer, klm@nist.gov - first release to usenet
-;; Last update: Ken Manheimer <klm@i.am>, 11/18/1999.
 ;; Keywords: help, abbrev
 
 ;; This file is part of GNU Emacs.
 ;; Keywords: help, abbrev
 
 ;; This file is part of GNU Emacs.
@@ -26,7 +25,7 @@
 
 ;;; Commentary:
 
 
 ;;; Commentary:
 
-;; Loading this package implements a more fine-grained minibuffer
+;; Enabling this package implements a more fine-grained minibuffer
 ;; completion feedback scheme.  Prospective completions are concisely
 ;; indicated within the minibuffer itself, with each successive
 ;; keystroke.
 ;; completion feedback scheme.  Prospective completions are concisely
 ;; indicated within the minibuffer itself, with each successive
 ;; keystroke.
 ;; customize icomplete setup for interoperation with other
 ;; minibuffer-oriented packages.
 
 ;; customize icomplete setup for interoperation with other
 ;; minibuffer-oriented packages.
 
-;; To activate icomplete mode, load the package and use the
-;; `icomplete-mode' function.  You can subsequently deactivate it by
-;; invoking the function icomplete-mode with a negative prefix-arg
-;; (C-U -1 ESC-x icomplete-mode).  Also, you can prevent activation of
-;; the mode during package load by first setting the variable
-;; `icomplete-mode' to nil.  Icompletion can be enabled any time after
-;; the package is loaded by invoking icomplete-mode without a prefix
-;; arg.
+;; To enable/disable icomplete mode, use the `icomplete-mode' function.
 
 ;; Thanks to everyone for their suggestions for refinements of this
 ;; package.  I particularly have to credit Michael Cook, who
 
 ;; Thanks to everyone for their suggestions for refinements of this
 ;; package.  I particularly have to credit Michael Cook, who
 
 ;;; Code:
 
 
 ;;; Code:
 
-;;;_* Provide
-(provide 'icomplete)
-
-
 (defgroup icomplete nil
   "Show completions dynamically in minibuffer."
   :prefix "icomplete-"
 (defgroup icomplete nil
   "Show completions dynamically in minibuffer."
   :prefix "icomplete-"
+  :link '(info-link "(emacs)Icomplete")
   :group 'minibuffer)
 
 (defvar icomplete-prospects-length 80)
   :group 'minibuffer)
 
 (defvar icomplete-prospects-length 80)
  'icomplete-prospects-length 'icomplete-prospects-height "23.1")
 
 (defcustom icomplete-separator " | "
  'icomplete-prospects-length 'icomplete-prospects-height "23.1")
 
 (defcustom icomplete-separator " | "
-  "String used by icomplete to separate alternatives in the minibuffer."
+  "String used by Icomplete to separate alternatives in the minibuffer."
   :type 'string
   :version "24.4")
 
   :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")
+
+(defcustom icomplete-show-matches-on-no-input nil
+  "When non-nil, show completions when first prompting for input."
+  :type 'boolean
+  :version "24.4")
+
+(defcustom icomplete-with-completion-tables t
+  "Specialized completion tables with which Icomplete should operate.
+If this is t, Icomplete operates on all tables.
+Otherwise this should be a list of the completion tables (e.g.,
+`internal-complete-buffer') on which Icomplete should operate."
+  ;; Prior to 24.4, not a user-option, default '(internal-complete-buffer).
+  :version "24.4"
+  :type '(choice (const :tag "All" t)
+                (repeat function)))
+
+(defface icomplete-first-match '((t :weight bold))
+  "Face used by Icomplete for highlighting first match."
+  :version "24.4")
+
 ;;;_* User Customization variables
 (defcustom icomplete-prospects-height
   ;; 20 is an estimated common size for the prompt + minibuffer content, to
 ;;;_* User Customization variables
 (defcustom icomplete-prospects-height
   ;; 20 is an estimated common size for the prompt + minibuffer content, to
   (+ 1 (/ (+ icomplete-prospects-length 20) (window-width)))
   "Maximum number of lines to use in the minibuffer."
   :type 'integer
   (+ 1 (/ (+ icomplete-prospects-length 20) (window-width)))
   "Maximum number of lines to use in the minibuffer."
   :type 'integer
-  :group 'icomplete
   :version "23.1")
 
 (defcustom icomplete-compute-delay .3
   "Completions-computation stall, used only with large-number completions.
 See `icomplete-delay-completions-threshold'."
   :version "23.1")
 
 (defcustom icomplete-compute-delay .3
   "Completions-computation stall, used only with large-number completions.
 See `icomplete-delay-completions-threshold'."
-  :type 'number
-  :group 'icomplete)
+  :type 'number)
 
 (defcustom icomplete-delay-completions-threshold 400
   "Pending-completions number over which to apply `icomplete-compute-delay'."
 
 (defcustom icomplete-delay-completions-threshold 400
   "Pending-completions number over which to apply `icomplete-compute-delay'."
-  :type 'integer
-  :group 'icomplete)
+  :type 'integer)
 
 (defcustom icomplete-max-delay-chars 3
 
 (defcustom icomplete-max-delay-chars 3
-  "Maximum number of initial chars to apply icomplete compute delay."
-  :type 'integer
-  :group 'icomplete)
+  "Maximum number of initial chars to apply `icomplete-compute-delay'."
+  :type 'integer)
+
+(defvar icomplete-in-buffer nil
+  "If non-nil, also use Icomplete when completing in non-mini buffers.")
 
 (defcustom icomplete-minibuffer-setup-hook nil
   "Icomplete-specific customization of minibuffer setup.
 
 
 (defcustom icomplete-minibuffer-setup-hook nil
   "Icomplete-specific customization of minibuffer setup.
 
-This hook is run during minibuffer setup if icomplete is active.
-It is intended for use in customizing icomplete for interoperation
+This hook is run during minibuffer setup if Icomplete is active.
+It is intended for use in customizing Icomplete for interoperation
 with other features and packages.  For instance:
 
 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))))
+  (add-hook 'icomplete-minibuffer-setup-hook
+            (lambda () (setq-local max-mini-window-height 3)))
 
 will constrain Emacs to a maximum minibuffer height of 3 lines when
 icompletion is occurring."
 
 will constrain Emacs to a maximum minibuffer height of 3 lines when
 icompletion is occurring."
@@ -128,60 +138,50 @@ icompletion is occurring."
 (defvar icomplete-overlay (make-overlay (point-min) (point-min) nil t t)
   "Overlay used to display the list of completions.")
 
 (defvar icomplete-overlay (make-overlay (point-min) (point-min) nil t t)
   "Overlay used to display the list of completions.")
 
-;;;_  = icomplete-pre-command-hook
-(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)
-;;;_  = icomplete-post-command-hook
-(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)
-
-;;;_  = icomplete-with-completion-tables
-(defvar icomplete-with-completion-tables '(internal-complete-buffer)
-  "Specialized completion tables with which icomplete should operate.
+(defun icomplete-pre-command-hook ()
+ (let ((non-essential t))
+   (icomplete-tidy)))
 
 
-Icomplete does not operate with any specialized completion tables
-except those on this list.")
+(defun icomplete-post-command-hook ()
+  (let ((non-essential t)) ;E.g. don't prompt for password!
+    (icomplete-exhibit)))
 
 (defvar icomplete-minibuffer-map
   (let ((map (make-sparse-keymap)))
     (define-key map [?\M-\t] 'minibuffer-force-complete)
     (define-key map [?\C-j]  'minibuffer-force-complete-and-exit)
 
 (defvar icomplete-minibuffer-map
   (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)
-    map))
+    (define-key map [?\C-.]  'icomplete-forward-completions)
+    (define-key map [?\C-,]  'icomplete-backward-completions)
+    map)
+  "Keymap used by `icomplete-mode' in the minibuffer.")
 
 (defun icomplete-forward-completions ()
   "Step forward completions by one entry.
 Second entry becomes the first and can be selected with
 `minibuffer-force-complete-and-exit'."
   (interactive)
 
 (defun icomplete-forward-completions ()
   "Step forward completions by one entry.
 Second entry becomes the first and can be selected with
 `minibuffer-force-complete-and-exit'."
   (interactive)
-  (let* ((comps (completion-all-sorted-completions))
+  (let* ((beg (icomplete--field-beg))
+         (end (icomplete--field-end))
+         (comps (completion-all-sorted-completions beg end))
         (last (last comps)))
         (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 beg end (cdr comps)))))
 
 (defun icomplete-backward-completions ()
   "Step backward completions by one entry.
 Last entry becomes the first and can be selected with
 `minibuffer-force-complete-and-exit'."
   (interactive)
 
 (defun icomplete-backward-completions ()
   "Step backward completions by one entry.
 Last entry becomes the first and can be selected with
 `minibuffer-force-complete-and-exit'."
   (interactive)
-  (let* ((comps (completion-all-sorted-completions))
+  (let* ((beg (icomplete--field-beg))
+         (end (icomplete--field-end))
+         (comps (completion-all-sorted-completions beg end))
         (last-but-one (last comps 2))
         (last (cdr last-but-one)))
         (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)
       (setcdr last-but-one (cdr last))
       (push (car last) comps)
-      (completion--cache-all-sorted-completions comps))))
+      (completion--cache-all-sorted-completions beg end comps))))
 
 ;;;_ > icomplete-mode (&optional prefix)
 ;;;###autoload
 
 ;;;_ > icomplete-mode (&optional prefix)
 ;;;###autoload
@@ -189,32 +189,66 @@ Last entry becomes the first and can be selected with
   "Toggle incremental minibuffer completion (Icomplete mode).
 With a prefix argument ARG, enable Icomplete mode if ARG is
 positive, and disable it otherwise.  If called from Lisp, enable
   "Toggle incremental minibuffer completion (Icomplete mode).
 With a prefix argument ARG, enable Icomplete mode if ARG is
 positive, and disable it otherwise.  If called from Lisp, enable
-the mode if ARG is omitted or nil."
+the mode if ARG is omitted or nil.
+
+When this global minor mode is enabled, typing in the minibuffer
+continuously displays a list of possible completions that match
+the string you have typed.  See `icomplete-completions' for a
+description of how prospective completions are displayed.
+
+For more information, see Info node `(emacs)Icomplete'.
+For options you can set, `\\[customize-group] icomplete'.
+
+You can use the following key bindings to navigate and select
+completions:
+
+\\{icomplete-minibuffer-map}"
   :global t :group 'icomplete
   :global t :group 'icomplete
-  (if icomplete-mode
-      ;; The following is not really necessary after first time -
-      ;; no great loss.
-      (add-hook 'minibuffer-setup-hook 'icomplete-minibuffer-setup)
-    (remove-hook 'minibuffer-setup-hook 'icomplete-minibuffer-setup)))
+  (remove-hook 'minibuffer-setup-hook #'icomplete-minibuffer-setup)
+  (remove-hook 'completion-in-region-mode-hook #'icomplete--in-region-setup)
+  (when icomplete-mode
+    (when icomplete-in-buffer
+      (add-hook 'completion-in-region-mode-hook #'icomplete--in-region-setup))
+    (add-hook 'minibuffer-setup-hook #'icomplete-minibuffer-setup)))
+
+(defun icomplete--completion-table ()
+  (if (window-minibuffer-p) minibuffer-completion-table
+    (or (nth 2 completion-in-region--data)
+       (message "In %S (w=%S): %S"
+                (current-buffer) (selected-window) (window-minibuffer-p)))))
+(defun icomplete--completion-predicate ()
+  (if (window-minibuffer-p) minibuffer-completion-predicate
+    (nth 3 completion-in-region--data)))
+(defun icomplete--field-string ()
+  (if (window-minibuffer-p) (minibuffer-contents)
+    (buffer-substring-no-properties
+     (nth 0 completion-in-region--data)
+     (nth 1 completion-in-region--data))))
+(defun icomplete--field-beg ()
+  (if (window-minibuffer-p) (minibuffer-prompt-end)
+    (nth 0 completion-in-region--data)))
+(defun icomplete--field-end ()
+  (if (window-minibuffer-p) (point-max)
+    (nth 1 completion-in-region--data)))
 
 ;;;_ > icomplete-simple-completing-p ()
 (defun icomplete-simple-completing-p ()
 
 ;;;_ > icomplete-simple-completing-p ()
 (defun icomplete-simple-completing-p ()
-  "Non-nil if current window is minibuffer that's doing simple completion.
+  "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,
 
 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
+   and the completion table is not a function (which would
        indicate some non-standard, non-simple completion mechanism,
        indicate some non-standard, non-simple completion mechanism,
-       like file-name and other custom-func completions)."
+       like file-name and other custom-func completions),
+   and `icomplete-with-completion-tables' doesn't restrict completion."
 
 
-  (and (window-minibuffer-p (selected-window))
-       (not executing-kbd-macro)
-       minibuffer-completion-table
-       (or (not (functionp minibuffer-completion-table))
-           (eq icomplete-with-completion-tables t)
-           (member minibuffer-completion-table
-                   icomplete-with-completion-tables))))
+  (unless executing-kbd-macro
+    (let ((table (icomplete--completion-table)))
+      (and table
+           (or (not (functionp table))
+               (eq icomplete-with-completion-tables t)
+               (member table icomplete-with-completion-tables))))))
 
 ;;;_ > icomplete-minibuffer-setup ()
 (defun icomplete-minibuffer-setup ()
 
 ;;;_ > icomplete-minibuffer-setup ()
 (defun icomplete-minibuffer-setup ()
@@ -224,58 +258,83 @@ Usually run by inclusion in `minibuffer-setup-hook'."
     (set (make-local-variable 'completion-show-inline-help) nil)
     (use-local-map (make-composed-keymap icomplete-minibuffer-map
                                         (current-local-map)))
     (set (make-local-variable 'completion-show-inline-help) nil)
     (use-local-map (make-composed-keymap icomplete-minibuffer-map
                                         (current-local-map)))
-    (add-hook 'pre-command-hook
-             (lambda () (let ((non-essential t))
-                      (run-hooks 'icomplete-pre-command-hook)))
-             nil t)
-    (add-hook 'post-command-hook
-             (lambda () (let ((non-essential t)) ;E.g. don't prompt for password!
-                      (run-hooks 'icomplete-post-command-hook)))
-             nil t)
-    (run-hooks 'icomplete-minibuffer-setup-hook)))
-;\f
+    (add-hook 'pre-command-hook  #'icomplete-pre-command-hook  nil t)
+    (add-hook 'post-command-hook #'icomplete-post-command-hook nil t)
+    (run-hooks 'icomplete-minibuffer-setup-hook)
+    (when icomplete-show-matches-on-no-input
+      (icomplete-exhibit))))
+
+(defvar icomplete--in-region-buffer nil)
+
+(defun icomplete--in-region-setup ()
+  (when (or (not completion-in-region-mode)
+           (and icomplete--in-region-buffer
+                (not (eq icomplete--in-region-buffer (current-buffer)))))
+    (with-current-buffer (or icomplete--in-region-buffer (current-buffer))
+      (setq icomplete--in-region-buffer nil)
+      (delete-overlay icomplete-overlay)
+      (kill-local-variable 'completion-show-inline-help)
+      (remove-hook 'pre-command-hook  'icomplete-pre-command-hook  t)
+      (remove-hook 'post-command-hook 'icomplete-post-command-hook t)
+      (message nil)))
+  (when (and completion-in-region-mode
+            icomplete-mode (icomplete-simple-completing-p))
+    (setq icomplete--in-region-buffer (current-buffer))
+    (set (make-local-variable 'completion-show-inline-help) nil)
+    (let ((tem (assq 'completion-in-region-mode
+                    minor-mode-overriding-map-alist)))
+      (unless (memq icomplete-minibuffer-map (cdr tem))
+       (setcdr tem (make-composed-keymap icomplete-minibuffer-map
+                                         (cdr tem)))))
+    (add-hook 'pre-command-hook  'icomplete-pre-command-hook  nil t)
+    (add-hook 'post-command-hook 'icomplete-post-command-hook nil t)))
+\f
 
 
 ;;;_* Completion
 
 ;;;_ > icomplete-tidy ()
 (defun icomplete-tidy ()
 
 
 ;;;_* Completion
 
 ;;;_ > icomplete-tidy ()
 (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'."
+  "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'."
   (delete-overlay icomplete-overlay))
 
 ;;;_ > icomplete-exhibit ()
 (defun icomplete-exhibit ()
   (delete-overlay icomplete-overlay))
 
 ;;;_ > icomplete-exhibit ()
 (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))
+  "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)) ;Shouldn't be necessary.
     (save-excursion
       (goto-char (point-max))
                                         ; Insert the match-status information:
     (save-excursion
       (goto-char (point-max))
                                         ; Insert the match-status information:
-      (if (and (> (point-max) (minibuffer-prompt-end))
-               buffer-undo-list         ; Wait for some user input.
+      (if (and (or icomplete-show-matches-on-no-input
+                   (> (icomplete--field-end) (icomplete--field-beg)))
                (or
                 ;; Don't bother with delay after certain number of chars:
                (or
                 ;; Don't bother with delay after certain number of chars:
-                (> (- (point) (field-beginning)) icomplete-max-delay-chars)
+                (> (- (point) (icomplete--field-beg))
+                   icomplete-max-delay-chars)
                 ;; Don't delay if the completions are known.
                 completion-all-sorted-completions
                 ;; Don't delay if alternatives number is small enough:
                 ;; Don't delay if the completions are known.
                 completion-all-sorted-completions
                 ;; Don't delay if alternatives number is small enough:
-                (and (sequencep minibuffer-completion-table)
-                     (< (length minibuffer-completion-table)
+                (and (sequencep (icomplete--completion-table))
+                     (< (length (icomplete--completion-table))
                         icomplete-delay-completions-threshold))
                 ;; Delay - give some grace time for next keystroke, before
                ;; embarking on computing completions:
                (sit-for icomplete-compute-delay)))
                         icomplete-delay-completions-threshold))
                 ;; Delay - give some grace time for next keystroke, before
                ;; embarking on computing completions:
                (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)
+         (let* ((field-string (icomplete--field-string))
+                 (text (while-no-input
+                         (icomplete-completions
+                          field-string
+                          (icomplete--completion-table)
+                          (icomplete--completion-predicate)
+                          (if (window-minibuffer-p)
+                              (not minibuffer-completion-confirm)))))
+                 (buffer-undo-list t)
+                 deactivate-mark)
            ;; Do nothing if while-no-input was aborted.
             (when (stringp text)
               (move-overlay icomplete-overlay (point) (point) (current-buffer))
            ;; Do nothing if while-no-input was aborted.
             (when (stringp text)
               (move-overlay icomplete-overlay (point) (point) (current-buffer))
@@ -293,27 +352,31 @@ The display is updated with each minibuffer keystroke during
 minibuffer completion.
 
 Prospective completion suffixes (if any) are displayed, bracketed by
 minibuffer completion.
 
 Prospective completion suffixes (if any) are displayed, bracketed by
-one of \(), \[], or \{} pairs.  The choice of brackets is as follows:
+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
+  (...) - 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.
 
           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 there are multiple possibilities, `icomplete-separator' separates them.
 
 
-  (let* ((md (completion--field-metadata (field-beginning)))
-        (comps (completion-all-sorted-completions))
+The displays for unambiguous matches have ` [Matched]' appended
+\(whether complete or not), or ` [No matches]', if no eligible
+matches exist."
+  (let* ((minibuffer-completion-table candidates)
+        (minibuffer-completion-predicate predicate)
+        (md (completion--field-metadata (icomplete--field-beg)))
+        (comps (completion-all-sorted-completions
+                 (icomplete--field-beg) (icomplete--field-end)))
          (last (if (consp comps) (last comps)))
          (base-size (cdr last))
          (open-bracket (if require-match "(" "["))
          (close-bracket (if require-match ")" "]")))
     ;; `concat'/`mapconcat' is the slow part.
     (if (not (consp comps))
          (last (if (consp comps) (last comps)))
          (base-size (cdr last))
          (open-bracket (if require-match "(" "["))
          (close-bracket (if require-match ")" "]")))
     ;; `concat'/`mapconcat' is the slow part.
     (if (not (consp comps))
-        (format " %sNo matches%s" open-bracket close-bracket)
+       (progn ;;(debug (format "Candidates=%S field=%S" candidates name))
+              (format " %sNo matches%s" open-bracket close-bracket))
       (if last (setcdr last nil))
       (let* ((most-try
               (if (and base-size (> base-size 0))
       (if last (setcdr last nil))
       (let* ((most-try
               (if (and base-size (> base-size 0))
@@ -329,6 +392,7 @@ are exhibited within the square braces.)"
              ;; a prefix of most, or something else.
             (compare (compare-strings name nil nil
                                       most nil nil completion-ignore-case))
              ;; a prefix of most, or something else.
             (compare (compare-strings name nil nil
                                       most nil nil completion-ignore-case))
+            (ellipsis (if (char-displayable-p ?…) "…" "..."))
             (determ (unless (or (eq t compare) (eq t most-try)
                                 (= (setq compare (1- (abs compare)))
                                    (length most)))
             (determ (unless (or (eq t compare) (eq t most-try)
                                 (= (setq compare (1- (abs compare)))
                                    (length most)))
@@ -339,12 +403,15 @@ are exhibited within the square braces.)"
                                 (substring most compare))
                                 ;; Don't bother truncating if it doesn't gain
                                 ;; us at least 2 columns.
                                 (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))))
+                               ((< compare (+ 2 (string-width ellipsis))) most)
+                               (t (concat ellipsis (substring most compare))))
                               close-bracket)))
             ;;"-prospects" - more than one candidate
                               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)
+                              (+ 2 (string-width ellipsis)) ;; take {…} into account
+                              (string-width (buffer-string))))
              (prospects-max
               ;; Max total length to use, including the minibuffer content.
               (* (+ icomplete-prospects-height
              (prospects-max
               ;; Max total length to use, including the minibuffer content.
               (* (+ icomplete-prospects-height
@@ -352,48 +419,77 @@ are exhibited within the square braces.)"
                     ;; one line, increase the allowable space accordingly.
                     (/ prospects-len (window-width)))
                  (window-width)))
                     ;; one line, increase the allowable space accordingly.
                     (/ prospects-len (window-width)))
                  (window-width)))
+             ;; Find the common prefix among `comps'.
+             ;; We can't use the optimization below because its assumptions
+             ;; aren't always true, e.g. when completion-cycling (bug#10850):
+             ;; (if (eq t (compare-strings (car comps) nil (length most)
+             ;;                         most nil nil completion-ignore-case))
+             ;;     ;; Common case.
+             ;;     (length most)
+             ;; Else, use try-completion.
+            (prefix (when icomplete-hide-common-prefix
+                      (try-completion "" comps)))
              (prefix-len
              (prefix-len
-              ;; Find the common prefix among `comps'.
-             ;; We can't use the optimization below because its assumptions
-             ;; aren't always true, e.g. when completion-cycling (bug#10850):
-             ;; (if (eq t (compare-strings (car comps) nil (length most)
-             ;;                         most nil nil completion-ignore-case))
-             ;;     ;; 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)
-       (if (eq most-try t) ;; (or (null (cdr comps))
+             (and (stringp prefix)
+                   ;; Only hide the prefix if the corresponding info
+                   ;; is already displayed via `most'.
+                   (string-prefix-p prefix most t)
+                   (length prefix))) ;;)
+            prospects comp limit)
+       (if (or (eq most-try t) (not (consp (cdr comps))))
            (setq prospects nil)
            (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))
          (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)
                     (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
                    "{"
         ;; 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)
-                   (and limit (concat icomplete-separator "…"))
+                   (mapconcat 'identity prospects icomplete-separator)
+                   (and limit (concat icomplete-separator ellipsis))
                    "}")
          (concat determ " [Matched]"))))))
 
                    "}")
          (concat determ " [Matched]"))))))
 
+;;;_* Provide
+(provide 'icomplete)
+
 ;;_* Local emacs vars.
 ;;Local variables:
 ;;allout-layout: (-2 :)
 ;;_* Local emacs vars.
 ;;Local variables:
 ;;allout-layout: (-2 :)