Update icicles
[emacs.git] / .emacs.d / elisp / icicle / icicles-mcmd.el
index d0f792c..c2a6f93 100644 (file)
@@ -4,25 +4,30 @@
 ;; Description: Minibuffer commands for Icicles
 ;; Author: Drew Adams
 ;; Maintainer: Drew Adams (concat "drew.adams" "@" "oracle" ".com")
-;; Copyright (C) 1996-2014, Drew Adams, all rights reserved.
+;; Copyright (C) 1996-2015, Drew Adams, all rights reserved.
 ;; Created: Mon Feb 27 09:25:04 2006
-;; Last-Updated: Wed Apr 23 10:49:31 2014 (-0700)
+;; Last-Updated: Wed Jan 21 09:01:17 2015 (-0800)
 ;;           By: dradams
-;;     Update #: 19508
+;;     Update #: 19644
 ;; URL: http://www.emacswiki.org/icicles-mcmd.el
 ;; Doc URL: http://www.emacswiki.org/Icicles
 ;; Keywords: internal, extensions, help, abbrev, local, minibuffer,
 ;;           keys, apropos, completion, matching, regexp, command
-;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x, 24.x
+;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x, 24.x, 25.x
 ;;
 ;; Features that might be required by this library:
 ;;
-;;   `apropos', `apropos-fn+var', `cl', `cus-theme', `doremi',
-;;   `el-swank-fuzzy', `ffap', `ffap-', `fuzzy', `fuzzy-match',
-;;   `hexrgb', `icicles-fn', `icicles-opt', `icicles-var',
-;;   `image-dired', `kmacro', `levenshtein', `mouse3', `mwheel',
-;;   `naked', `regexp-opt', `ring', `thingatpt', `thingatpt+',
-;;   `wid-edit', `wid-edit+', `widget'.
+;;   `apropos', `apropos+', `apropos-fn+var', `avoid', `bookmark',
+;;   `bookmark+', `bookmark+-1', `bookmark+-bmu', `bookmark+-key',
+;;   `bookmark+-lit', `cl', `cmds-menu', `cus-theme', `doremi',
+;;   `el-swank-fuzzy', `ffap', `ffap-', `fit-frame', `frame-fns',
+;;   `fuzzy', `fuzzy-match', `help+20', `hexrgb', `icicles-fn',
+;;   `icicles-opt', `icicles-var', `image-dired', `info', `info+20',
+;;   `kmacro', `levenshtein', `menu-bar', `menu-bar+', `misc-cmds',
+;;   `misc-fns', `mouse3', `mwheel', `naked', `package', `pp', `pp+',
+;;   `regexp-opt', `ring', `second-sel', `strings', `thingatpt',
+;;   `thingatpt+', `unaccent', `w32browser-dlgopen', `wid-edit',
+;;   `wid-edit+', `widget'.
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
@@ -90,7 +95,9 @@
 ;;    `icicle-dispatch-C-^', `icicle-dispatch-C-.',
 ;;    `icicle-dispatch-C-M-/', `icicle-dispatch-C-x.',
 ;;    `icicle-dispatch-M-_', `icicle-dispatch-M-comma',
-;;    `icicle-dispatch-M-q', `icicle-doremi-candidate-width-factor+',
+;;    `icicle-dispatch-M-q',
+;;    `icicle-display-candidates-in-Completions',
+;;    `icicle-doremi-candidate-width-factor+',
 ;;    `icicle-doremi-increment-max-candidates+',
 ;;    `icicle-doremi-increment-swank-prefix-length+',
 ;;    `icicle-doremi-increment-swank-timeout+',
 ;;    `icicle-bind-file-candidate-keys', `icicle-candidate-action-1',
 ;;    `icicle-candidate-set-retrieve-1',
 ;;    `icicle-candidate-set-save-1',
-;;    `icicle-candidate-set-save-selected-1',
+;;    `icicle-candidate-set-save-selected-1', `icicle-cand-preds',
 ;;    `icicle-column-wise-cand-nb',
 ;;    `icicle-isearch-complete-past-string',
 ;;    `icicle-Completions-popup-choice',
 ;;    `icicle-insert-candidate-action', `icicle-insert-dot',
 ;;    `icicle-insert-input', `icicle-insert-thing',
 ;;    `icicle-keep/remove-buffer-cands-for-visible',
-;;    `icicle-looking-at-p', `icicle-looking-back-at-p',
+;;    `icicle-looking-at-p', `icicle-looking-at-literally-p',
+;;    `icicle-looking-back-at-literally-p',
 ;;    `icicle-markers-to-readable',
 ;;    `icicle-maybe-multi-completion-completing-p',
 ;;    `icicle-mouse-candidate-action-1', `icicle-nb-Completions-cols',
 ;; Some defvars to quiet byte-compiler a bit:
 
 (when (< emacs-major-version 22)
-  (defvar overriding-map-is-bound)
+  (defvar icicle-Info-highlight-visited-nodes) ; In `icicles-opt.el' (for Emacs 22+)
   (defvar read-file-name-completion-ignore-case) ; In `minibuffer.el'
   (defvar read-file-name-predicate)
-  (defvar saved-overriding-map))
+  (defvar tooltip-mode))
 
 (when (< emacs-major-version 23)
   (defvar read-buffer-completion-ignore-case)
 (defvar doremi-down-keys)               ; In `doremi.el'
 (defvar doremi-up-keys)                 ; In `doremi.el'
 (defvar filesets-data)                  ; In `filesets.el'.
+(defvar icicle-cand-preds)              ; Here.
 (defvar icicle-ido-like-mode)           ; In `icicles-cmd2.el' (implicit)
+(defvar icicle-Info-hist-list)          ; In `icicles-cmd2.el'
 (defvar ignore-comments-flag)           ; In `hide-comnt.el'.
 (defvar minibuffer-confirm-exit-commands) ; In `minibuffer.el' in Emacs 23+.
 (defvar minibuffer-local-filename-completion-map) ; In Emacs 22+.
 (defvar minibuffer-local-filename-must-match-map) ; In Emacs 23.2 (but not Emacs 24+).
 (defvar minibuffer-local-must-match-filename-map) ; In Emacs 22+.
+(defvar overriding-map-is-bound)        ; In Emacs 22-23.
 (defvar recentf-list)                   ; In `recentf.el' (Emacs 21+).
+(defvar saved-overriding-map)           ; In Emacs 22-23.
 (defvar to-insert)                      ; Here.
+(defvar universal-argument-num-events)  ; Emacs 22-24.3.
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  
@@ -708,7 +721,8 @@ Return the number of the candidate: 0 for first, 1 for second, ..."
                 (insert dir)
                 (setq choice     (concat dir choice)
                       base-size  0))))
-          (icicle-choose-completion-string choice buffer base-size))
+          ;; $$$$$$$$ (icicle-choose-completion-string choice buffer base-size))
+          (with-current-buffer buffer (icicle-choose-completion-string choice buffer base-size)))
         icicle-candidate-nb))
 
   (defun icicle-choose-completion ()    ; Emacs < 23.2.
@@ -957,13 +971,22 @@ POSITION is a buffer position."
 ;;; All except `icicle-erase-minibuffer' are bound in the minibuffer to whatever the same
 ;;; command without `icicle-' is bound to globally.
 
-(defun icicle-looking-at-p (string)
-  "Return non-nil if STRING immediately succeeds point."
-  (let ((len  (length string)))
-    (save-excursion (save-match-data (search-forward string (min (+ (point) len) (point-max)) t)))))
 
-(defun icicle-looking-back-at-p (string)
+;; Same as `bmkp-looking-at-p' in `bookmark+-bmu.el'.
+;; Do not `defalias' to Emacs `looking-at-p' because it is a `defsubst'.
+(defun icicle-looking-at-p (regexp)
+  "Like `looking-at', but this saves and restores the match data."
+  (save-match-data (looking-at regexp)))
+
+(defun icicle-looking-at-literally-p (string)
   "Return non-nil if STRING immediately precedes point."
+  (save-match-data (looking-at (regexp-quote string))))
+
+(defun icicle-looking-back-at-literally-p (string)
+  "Return non-nil if STRING immediately precedes point.  STRING is
+matched literally - not as a regexp.  In this the function is like
+`icicle-looking-at-literally-p', not `icicle-looking-at-p'.
+Saves and restores the match data."
   (let ((len  (length string)))
     (save-excursion (save-match-data
                       (search-backward string (max (- (point) len) (icicle-minibuffer-prompt-end)) t)))))
@@ -975,18 +998,20 @@ Handles Icicles dots (`.') and `icicle-list-join-string'."
   (interactive "p")
   (let ((len-dot   (length icicle-anychar-regexp))
         (len-join  (length icicle-list-join-string)))
-    (dotimes (i  (abs n))
-      (or (save-match-data
-            (if (wholenump n)
-                (search-forward icicle-anychar-regexp (min (+ (point) len-dot) (point-max)) t)
-              (search-backward icicle-anychar-regexp
-                               (max (- (point) len-dot) (icicle-minibuffer-prompt-end)) t)))
-          (save-match-data
-            (if (wholenump n)
-                (search-forward icicle-list-join-string (min (+ (point) len-join) (point-max)) t)
-              (search-backward icicle-list-join-string
-                               (max (- (point) len-join) (icicle-minibuffer-prompt-end)) t)))
-          (forward-char (if (wholenump n) 1 -1))))))
+    (save-restriction
+      (narrow-to-region (icicle-minibuffer-prompt-end) (point-max))
+      (condition-case nil               ; Ignore errors, e.g. `beginning-of-buffer' from `(forward-char -1)'.
+          (dotimes (i  (abs n))
+            (or (save-match-data
+                  (if (wholenump n)
+                      (search-forward icicle-anychar-regexp (min (+ (point) len-dot) (point-max)) t)
+                    (search-backward icicle-anychar-regexp (max (- (point) len-dot) (point-min)) t)))
+                (save-match-data
+                  (if (wholenump n)
+                      (search-forward icicle-list-join-string (min (+ (point) len-join) (point-max)) t)
+                    (search-backward icicle-list-join-string (max (- (point) len-join) (point-min)) t)))
+                (forward-char (if (wholenump n) 1 -1))))
+        (error nil)))))
 
 ;; Not used.
 (defun icicle-backward-char-magic (&optional n)
@@ -1011,9 +1036,9 @@ That is, handle dots (`.') and `icicle-list-join-string'."
   (let ((len-dot   (length icicle-anychar-regexp))
         (len-join  (length icicle-list-join-string)))
     (dotimes (i  (abs n))
-      (cond ((icicle-looking-back-at-p icicle-anychar-regexp)
+      (cond ((icicle-looking-back-at-literally-p icicle-anychar-regexp)
              (backward-delete-char-untabify len-dot  killflag))
-            ((icicle-looking-at-p icicle-list-join-string)
+            ((icicle-looking-back-at-literally-p icicle-list-join-string)
              (backward-delete-char-untabify len-join killflag))
             (t
              (backward-delete-char-untabify 1        killflag))))))
@@ -1033,9 +1058,12 @@ Handles Icicles dots (`.') and `icicle-list-join-string'."
   (let ((len-dot   (length icicle-anychar-regexp))
         (len-join  (length icicle-list-join-string)))
     (dotimes (i  (abs n))
-      (cond ((icicle-looking-back-at-p icicle-anychar-regexp)   (delete-char (- len-dot)  killflag))
-            ((icicle-looking-back-at-p icicle-list-join-string) (delete-char (- len-join) killflag))
-            (t                                                  (delete-char -1           killflag))))))
+      (cond ((icicle-looking-back-at-literally-p icicle-anychar-regexp)
+             (delete-char (- len-dot)  killflag))
+            ((icicle-looking-back-at-literally-p icicle-list-join-string)
+             (delete-char (- len-join) killflag))
+            (t
+             (delete-char -1           killflag))))))
 
 
 ;; Make delete-selection mode recognize it, so region is deleted.
@@ -1052,9 +1080,12 @@ Handles Icicles dots (`.') and `icicle-list-join-string'."
   (let ((len-dot   (length icicle-anychar-regexp))
         (len-join  (length icicle-list-join-string)))
     (dotimes (i  (abs n))
-      (cond ((icicle-looking-at-p icicle-anychar-regexp)   (delete-char len-dot  killflag))
-            ((icicle-looking-at-p icicle-list-join-string) (delete-char len-join killflag))
-            (t                                             (delete-char 1        killflag))))))
+      (cond ((icicle-looking-at-literally-p icicle-anychar-regexp)
+             (delete-char len-dot  killflag))
+            ((icicle-looking-at-literally-p icicle-list-join-string)
+             (delete-char len-join killflag))
+            (t
+             (delete-char 1        killflag))))))
 
 (defun icicle-backward-kill-word (arg)  ; Bound to `M-DEL' (`M-backspace') in minibuffer.
   "`backward-kill-word' and update `*Completions*' with input matches.
@@ -1374,15 +1405,18 @@ regardless of where you click."
 
 
 ;; Make delete-selection mode recognize self-insertion, so it replaces region text.
-(put 'icicle-self-insert 'delete-selection t)
-
-(defun icicle-self-insert (n) ;; Bound in minibuffer to stuff bound globally to `self-insert-command'.
-  "`self-insert' and update `*Completions*' with regexp input matches.
-See description of `self-insert'."
+(if (or (> emacs-major-version 24)  (and (= emacs-major-version 24)  (> emacs-minor-version 2)))
+    (put 'icicle-self-insert 'delete-selection
+         (lambda () (not (run-hook-with-args-until-success 'self-insert-uses-region-functions))))
+  (put 'icicle-self-insert 'delete-selection t))
+
+(defun icicle-self-insert (ch) ;; Bound in minibuffer to stuff bound globally to `self-insert-command'.
+  "Insert char CH and update `*Completions*' with regexp input matches.
+See description of `self-insert-command'."
   (interactive "p")
   (if executing-kbd-macro
-      (funcall #'self-insert-command n)
-    (icicle-call-then-update-Completions #'self-insert-command n)))
+      (funcall #'self-insert-command ch)
+    (icicle-call-then-update-Completions #'self-insert-command ch)))
 
 (defun icicle-insert-a-space ()
   "Insert a space.
@@ -2066,6 +2100,490 @@ If ALTERNATIVEP is non-nil, the alternative sort order is returned."
 
 ;;; Other commands to be used mainly in the minibuffer . . . . . . . .
 
+
+;; Used as a command only in `icicle-Info-index', currently.  Used mainly as a utility function - the main
+;; function for displaying completion candidates.  This was in `icicles-fn.el' originally.
+;;
+(defun icicle-display-candidates-in-Completions (&optional reverse-p no-display-p)
+  "Refresh the current set of completion candidates in `*Completions*'.
+REVERSE-P non-nil means display the candidates in reverse order.
+NO-DISPLAY-P non-nil means do not display the candidates; just
+  recompute them.  If the value is `no-msg', then do not show a
+  minibuffer message indicating that candidates were updated.
+By default, this is bound to `C-x C-M-l' during completion."
+
+  ;; FREE var used here (bound in `icicle-Info-index'): `icicle-Info-hist-list'.
+
+  ;;$$   ;; Pred is special if `minibuffer-completion-table' is a function.
+  ;;   (when (and (not (functionp minibuffer-completion-table))
+  ;;              (functionp minibuffer-completion-predicate))
+  ;;     (setq icicle-completion-candidates
+  ;;           (icicle-remove-if-not
+  ;;            (lambda (cand)
+  ;;              (funcall minibuffer-completion-predicate
+  ;;                       (if (arrayp minibuffer-completion-table) (intern cand) (list cand))))
+  ;;            icicle-completion-candidates)))
+
+  ;; $$$  (case icicle-incremental-completion
+  ;;     ((t always) (setq icicle-incremental-completion-p  'always))
+  ;;     ((nil) (setq icicle-incremental-completion-p  nil)))
+
+  ;; $$$$$ (unless (input-pending-p)             ; Do nothing if user hit a key.
+
+  ;; Upgrade `icicle-incremental-completion-p' if we are redisplaying, so that completions will
+  ;; be updated by `icicle-call-then-update-Completions' when you edit.
+  (interactive)
+  (setq icicle-incremental-completion-p  icicle-incremental-completion)
+  (when (and (eq t icicle-incremental-completion-p)  (get-buffer-window "*Completions*" 0))
+    (setq icicle-incremental-completion-p  'always))
+  (let ((nb-cands  (length icicle-completion-candidates)))
+    ;; $$$$$$ Could use this binding to prevent frame fitting, to allow room for images.
+    ;; But that is not really the solution.  Really should fit the frame or window in such a way
+    ;; that it takes image sizes into account.  Might need to wait for a fix to Emacs bug #7822.
+    ;; (autofit-frames-flag  (not icicle-image-files-in-Completions)))
+    (cond ((eq no-display-p 'no-msg))   ; No-op.
+          (no-display-p
+           (icicle-msg-maybe-in-minibuffer
+            "Candidates updated (%s matching): %s" icicle-current-completion-mode
+            (icicle-propertize (format "%d" nb-cands) 'face 'icicle-msg-emphasis)))
+          ((null icicle-completion-candidates)
+           (save-selected-window (icicle-remove-Completions-window))
+           (icicle-msg-maybe-in-minibuffer
+            (if (eq 'apropos icicle-current-completion-mode)
+                (let ((typ  (car (rassq icicle-apropos-complete-match-fn
+                                        icicle-S-TAB-completion-methods-alist))))
+                  (concat "No " typ (and typ  " ") "completions"))
+              (case (icicle-current-TAB-method)
+                (fuzzy        "No fuzzy completions")
+                (swank        "No swank (fuzzy symbol) completions")
+                (vanilla      "No vanilla completions")
+                (t            "No prefix completions")))))
+          (t
+           (when (> nb-cands icicle-incremental-completion-threshold)
+             (message "Displaying completion candidates..."))
+           ;; Display `*Completions*' now, so we can get its window's width.
+           ;; We don't wait for `with-output-to-temp-buffer' to display it, because displaying it
+           ;; might lead to splitting the display window, which would change its width.
+           ;; We need to know the width in order to calculate the proper candidate formatting.
+           (when (consp icicle-completion-candidates)
+             (let ((fit-frame-inhibit-fitting-flag  t)
+                   (comp-buf                        (get-buffer-create "*Completions*")))
+               (unless (get-buffer-window comp-buf 'visible)
+                 (save-selected-window (display-buffer comp-buf t 0)
+                                       (deactivate-mark))))) ; Remove any leftover mouse selection.
+           (with-output-to-temp-buffer "*Completions*"
+             ;; Each candidate in `icicle-completion-candidates' is a string, regardless of the
+             ;; original type of candidate used (e.g. symbol, string, alist candidate,...).  Here,
+             ;; provided `icicle-fancy-cands-internal-p' is non-nil, we transform these candidates,
+             ;; replacing each by a string that takes into account symbol properties
+             ;; `icicle-display-string' and `icicle-special-candidate'.
+             ;;
+             ;; Because `icicle-completion-candidates' is affected, changes to the candidate strings
+             ;; (e.g. propertizing) are also reflected in the completion return value chosen by the
+             ;; user.  It is not only the display in `*Completions*' that is affected.
+             ;;
+             ;; The symbol whose properties are used is the one in the current obarray that is named
+             ;; by the string candidate to be transformed.  If there is no such symbol, then no
+             ;; transformation occurs.  Unless `minibuffer-completion-table' is an obarray, the
+             ;; global obarray is used to get the symbol.
+             ;;
+             ;; 1. If the symbol has an `icicle-display-string' property, then that property value
+             ;;    must be a string (possibly propertized).  We replace the candidate by that string.
+             ;;
+             ;; 2. If the symbol has an `icicle-special-candidate' property, then we transfer the
+             ;;    property to the candidate string as a set of text properties.  (If the value is
+             ;;    not a plist, and `icicle-special-candidate-regexp' is nil, then just apply face
+             ;;    `icicle-special-candidate'.)  The effect is similar to using
+             ;;    `icicle-special-candidate-regexp', but the completion return value is also
+             ;;    affected.
+             (when icicle-fancy-cands-internal-p
+               (setq icicle-completion-candidates
+                     (mapcar (lambda (cand)
+                               (let* ((symb          (intern-soft
+                                                      cand (and (arrayp minibuffer-completion-table)
+                                                                minibuffer-completion-table)))
+                                      (display-strg  (and symb
+                                                          (stringp (get symb 'icicle-display-string))
+                                                          (get symb 'icicle-display-string)))
+                                      (new-cand      (or display-strg  cand))
+                                      (spec-prop     (and symb  (get symb 'icicle-special-candidate))))
+                                 ;; Apply `icicle-special-candidate' property's value.
+                                 ;; If the value is a plist, then apply the properties as text props.
+                                 ;; Else (the value is t), apply face `icicle-special-candidate'.
+                                 (when spec-prop
+                                   (setq new-cand  (copy-sequence new-cand))
+                                   (if (consp spec-prop)
+                                       (add-text-properties 0 (length new-cand) spec-prop new-cand)
+                                     (unless icicle-special-candidate-regexp
+                                       (add-text-properties 0 (length new-cand)
+                                                            '(face icicle-special-candidate)
+                                                            new-cand))))
+                                 new-cand))
+                             icicle-completion-candidates)))
+             (icicle-display-completion-list (if reverse-p
+                                                 (reverse icicle-completion-candidates)
+                                               icicle-completion-candidates)
+                                             nil ; IGNORED
+                                             nb-cands))
+           (save-excursion
+             (save-window-excursion
+               (with-current-buffer (get-buffer "*Completions*")
+                 (let* ((buffer-read-only  nil)
+                        (eob               (point-max))
+                        (filep             (or (icicle-file-name-input-p)  icicle-abs-file-candidates))
+                        (dir               (and filep  icicle-last-input
+                                                (icicle-file-name-directory icicle-last-input)))
+                        (histvar           (and (symbolp minibuffer-history-variable)
+                                                (boundp minibuffer-history-variable)
+                                                minibuffer-history-variable))
+                        (hist              (and histvar
+                                                (if filep
+                                                    ;; Need (or DIR  default-directory) instead of DIR
+                                                    ;; because Emacs 20 `expand-file-name' crashes.
+                                                    (let ((default-directory  (or dir  default-directory)))
+                                                      (mapcar #'expand-file-name (symbol-value histvar)))
+                                                  (symbol-value histvar))))
+                        (case-fold-search
+                         ;; Don't bother with buffer completion, `read-buffer-completion-ignore-case'.
+                         (if (and filep  (boundp 'read-file-name-completion-ignore-case))
+                             read-file-name-completion-ignore-case
+                           completion-ignore-case)))
+                   (when (fboundp 'remove-images)  (remove-images (point-min) (point-max)))
+                   (goto-char (icicle-start-of-candidates-in-Completions))
+                   (while (not (eobp))
+                     (let* ((beg    (point))
+                            (end    (next-single-property-change beg 'mouse-face nil eob))
+                            (next   (next-single-property-change end 'mouse-face nil eob))
+                            (faces  ()))
+
+                       ;; Highlight candidate specially if it is a proxy candidate.
+                       (let ((candidate  (icicle-current-completion-in-Completions)))
+                         ;;$$$ (when dir (setq candidate  (expand-file-name candidate dir)))
+                         (when (member candidate icicle-proxy-candidates)
+                           (setq faces  (cons 'icicle-proxy-candidate faces))
+                           (if (not icicle-proxy-candidate-regexp)
+                               (add-text-properties beg end (cons 'face (list faces)))
+                             (save-match-data
+                               (when (string-match icicle-proxy-candidate-regexp candidate)
+                                 (add-text-properties (+ beg (match-beginning 0)) (+ beg (match-end 0))
+                                                      (cons 'face (list faces))))))))
+
+                       ;; Highlight candidate specially if it is an extra candidate.
+                       (let ((candidate  (icicle-current-completion-in-Completions)))
+                         ;;$$$ (when dir (setq candidate  (expand-file-name candidate dir)))
+                         (save-match-data
+                           (when (member candidate icicle-extra-candidates)
+                             (setq faces  (cons 'icicle-extra-candidate faces))
+                             (add-text-properties beg end (cons 'face (list faces))))))
+
+                       ;; Highlight candidate specially if it is a special candidate.
+                       (let ((candidate  (icicle-current-completion-in-Completions)))
+                         ;;$$$ (when dir (setq candidate  (expand-file-name candidate dir)))
+                         (save-match-data
+                           (when (and icicle-special-candidate-regexp
+                                      (string-match icicle-special-candidate-regexp candidate))
+                             (setq faces  (cons 'icicle-special-candidate faces))
+                             (add-text-properties (+ beg (match-beginning 0)) (+ beg (match-end 0))
+                                                  (cons 'face (list faces))))))
+
+                       ;; Highlight candidate (`*-historical-candidate') if it was used previously.
+                       (when icicle-highlight-historical-candidates-flag
+                         (let ((candidate  (icicle-current-completion-in-Completions)))
+                           (when (and (consp hist)  (not (member candidate icicle-hist-cands-no-highlight)))
+                             ;; Need (or DIR  default-directory) instead of DIR
+                             ;; because Emacs 20 `expand-file-name' crashes.
+                             (let ((default-directory  (or dir  default-directory)))
+                               (when (member (if filep
+                                                 (expand-file-name (icicle-transform-multi-completion
+                                                                    candidate))
+                                               candidate)
+                                             hist)
+                                 (add-text-properties
+                                  beg end `(face ,(setq faces  (cons 'icicle-historical-candidate faces)))))))))
+
+                       ;; Highlight Info index-entry cand (using face `icicle-historical-candidate-other')
+                       ;; if its node has been visited.
+                       ;;
+                       ;; FREE var here (bound in `icicle-Info-index'): `icicle-Info-hist-list'.
+                       (when (and (> emacs-major-version 21)
+                                  (memq icicle-last-top-level-command '(Info-index icicle-Info-index))
+                                  (boundp 'icicle-Info-hist-list)  (consp icicle-Info-hist-list)
+                                  (or (eq this-command 'icicle-display-candidates-in-Completions)
+                                      (and icicle-highlight-historical-candidates-flag
+                                           icicle-Info-highlight-visited-nodes
+                                           (or (not (numberp icicle-Info-highlight-visited-nodes))
+                                               (<= nb-cands icicle-Info-highlight-visited-nodes)))))
+                         (message "Highlighting topics in all visited nodes...")
+                         (let ((candidate  (icicle-current-completion-in-Completions)))
+                           (when (or (assoc candidate icicle-Info-index-cache)
+                                     (icicle-some (mapcar 'cadr icicle-Info-hist-list)
+                                                  candidate
+                                                  #'icicle-Info-node-is-indexed-by-topic))
+                             (add-text-properties
+                              beg end `(face ,(setq faces  (cons 'icicle-historical-candidate-other faces)))))))
+
+                       ;; Highlight, inside the candidate, the expanded common match.
+                       (when (and icicle-current-input  (not (string= "" icicle-current-input)))
+                         (save-excursion
+                           (save-restriction
+                             (narrow-to-region beg end) ; Restrict to the completion candidate.
+                             (when (re-search-forward (regexp-quote (icicle-minibuf-input-sans-dir
+                                                                     icicle-current-input))
+                                                      nil t)
+                               (setq faces  (cons 'icicle-common-match-highlight-Completions faces))
+                               (put-text-property (match-beginning 0) (point) 'face faces)))))
+
+                       ;; Hide match for `icicle-current-input' (expanded common match, if available),
+                       ;; if `icicle-hide-common-match-in-Completions-flag' is non-nil.
+                       (save-excursion
+                         (save-restriction
+                           (narrow-to-region beg end) ; Restrict to the completion candidate.
+                           (when (and icicle-hide-common-match-in-Completions-flag  icicle-common-match-string)
+                             (when (re-search-forward (regexp-quote icicle-common-match-string) nil t)
+                               (if (> emacs-major-version 20)
+                                   (put-text-property (match-beginning 0) (point) 'display "...")
+                                 (put-text-property (match-beginning 0) (point) 'invisible t))))))
+
+                       ;; Highlight, inside the candidate, what the input expression matches.
+                       (unless (and icicle-current-raw-input  (string= "" icicle-current-raw-input)
+                                    icicle-apropos-complete-match-fn)
+                         (save-excursion
+                           (save-restriction
+                             (narrow-to-region beg end) ; Restrict to the completion candidate.
+                             (let ((fn  (if (and (eq 'prefix icicle-current-completion-mode)
+                                                 (not (memq (icicle-current-TAB-method) '(fuzzy swank))))
+                                            ;; $$$$$$ What is best for `vanilla' (Emacs 23) completion?
+                                            'search-forward
+                                          (case icicle-apropos-complete-match-fn
+                                            (icicle-scatter-match
+                                             (lambda (input bound noerr)
+                                               (re-search-forward (icicle-scatter input) bound noerr)))
+                                            (icicle-levenshtein-match
+                                             (if (= icicle-levenshtein-distance 1)
+                                                 (lambda (input bound noerr)
+                                                   (re-search-forward (icicle-levenshtein-one-regexp input)
+                                                                      bound noerr))
+                                               're-search-forward))
+                                            (otherwise 're-search-forward)))))
+                               (save-excursion
+                                 (when (and (funcall fn (icicle-minibuf-input-sans-dir icicle-current-raw-input)
+                                                     nil t)
+                                            (not (eq (match-beginning 0) (point))))
+                                   (setq faces  (cons 'icicle-match-highlight-Completions faces))
+                                   (put-text-property (match-beginning 0) (point) 'face faces)))
+
+                               ;; If `icicle-hide-non-matching-lines-flag' then hide all lines
+                               ;; of candidate that do not match current input.
+                               (let ((candidate  (icicle-current-completion-in-Completions))
+                                     (input      (icicle-minibuf-input-sans-dir
+                                                  icicle-current-raw-input))
+                                     (cbeg       beg))
+                                 (when (and icicle-hide-non-matching-lines-flag
+                                            (string-match "\n" candidate)
+                                            (not (string= "\n" candidate)))
+                                   (goto-char cbeg)
+                                   (while (not (eobp))
+                                     (unless (funcall fn input (line-end-position) t)
+                                       (if (> emacs-major-version 20)
+                                           (put-text-property (line-beginning-position)
+                                                              (min (1+ (line-end-position)) (point-max))
+                                                              'display "...\n")
+                                         (put-text-property (line-beginning-position)
+                                                            (min (1+ (line-end-position)) (point-max))
+                                                            'invisible t)))
+                                     (forward-line 1))))))))
+
+                       ;; Highlight candidate if it has been saved.
+                       (when (and icicle-highlight-saved-candidates-flag  icicle-saved-completion-candidates)
+                         (let ((candidate  (icicle-current-completion-in-Completions)))
+                           (when (member candidate icicle-saved-completion-candidates)
+                             (let ((ov  (make-overlay beg end)))
+                               (push ov icicle-saved-candidate-overlays)
+                               (overlay-put ov 'face 'icicle-saved-candidate)
+                               (overlay-put ov 'priority '10)))))
+
+                       ;; Treat `icicle-candidate-properties-alist'.
+                       ;; A `face' prop will unfortunately wipe out any `face' prop we just applied.
+                       (when icicle-candidate-properties-alist
+                         (save-excursion
+                           (save-restriction
+                             (narrow-to-region beg end) ; Restrict to the completion candidate.
+                             (let* ((candidate  (buffer-substring (point-min) (point-max)))
+                                    (orig-pt    (point))
+                                    (start      0)
+                                    (end        0)
+                                    (partnum    1)
+                                    (join       (concat "\\(" icicle-list-join-string "\\|\\'\\)"))
+                                    (len-cand   (length candidate))
+                                    (len-join   (length icicle-list-join-string))
+                                    (first      t))
+                               (save-match-data
+                                 (while (and (or first
+                                                 (not (= end (match-beginning 0)))
+                                                 (< (+ end len-join) len-cand))
+                                             (string-match join candidate (if (and (not first)
+                                                                                   (= end (match-beginning 0))
+                                                                                   (< end len-cand))
+                                                                              (+ end len-join)
+                                                                            end))
+                                             (< end len-cand))
+                                   (setq first  nil
+                                         end    (or (match-beginning 0)  len-cand))
+                                   (let* ((entry                   (assq partnum
+                                                                         icicle-candidate-properties-alist))
+                                          (properties              (cadr entry))
+                                          (propertize-join-string  (car (cddr entry))))
+                                     (when properties
+                                       (add-text-properties (+ start orig-pt) (+ end orig-pt) properties))
+                                     (when propertize-join-string
+                                       (add-text-properties (+ end orig-pt) (+ end orig-pt len-join)
+                                                            properties)))
+                                   (setq partnum  (1+ partnum)
+                                         start    (match-end 0))))))))
+
+                       ;; Thumbnail image for an image file or image-file bookmark (Bookmark+): Maybe show it
+                       ;; in `*Completions*'; maybe show it only in `*Completions*' mouseover tooltip.
+                       (when (or (and icicle-image-files-in-Completions
+                                      (if (fboundp 'display-graphic-p) (display-graphic-p) window-system)
+                                      (or (and filep  (fboundp 'image-file-name-regexp))
+                                          (and icicle-show-multi-completion-flag
+                                               (symbolp icicle-last-top-level-command)
+                                               (string-match "^icicle-bookmark-"
+                                                             (symbol-name icicle-last-top-level-command)))))
+                                 (and (boundp 'tooltip-mode)  tooltip-mode  icicle-image-preview-in-tooltip))
+                         (let ((image-file
+                                (if (and icicle-show-multi-completion-flag
+                                         (symbolp icicle-last-top-level-command)
+                                         ;; We could alternatively put a property on such symbols and
+                                         ;; test that.  But just matching the cmd name is OK so far.
+                                         (string-match "^icicle-bookmark-"
+                                                       (symbol-name icicle-last-top-level-command)))
+                                    ;; This is bound by the bookmark commands to `(1)': bookmark name.
+                                    ;; The file name is part #2, so we rebind this here.
+                                    (let ((icicle-list-use-nth-parts  '(2)))
+                                      (icicle-transform-multi-completion
+                                       (icicle-current-completion-in-Completions)))
+                                  (icicle-transform-multi-completion
+                                   (icicle-current-completion-in-Completions)))))
+                           (when (and (require 'image-dired nil t)
+                                      (icicle-string-match-p (image-file-name-regexp) image-file))
+                             (let* ((thumb-img  (image-dired-get-thumbnail-image image-file))
+                                    (thumb-img  (and thumb-img
+                                                     (append (image-dired-get-thumbnail-image image-file)
+                                                             '(:margin 2)))))
+                               (when thumb-img
+                                 ;; In `tooltip-mode', show image preview on mouseover,
+                                 ;; unless it is a thumbnail and `*Completions*' already shows thumbnails.
+                                 (when (and (boundp 'tooltip-mode)  tooltip-mode
+                                            (or (not icicle-image-files-in-Completions)
+                                                (not (numberp icicle-image-preview-in-tooltip))))
+                                   (with-current-buffer "*Completions*"
+                                     (put-text-property
+                                      (point) (+ (point) (length (icicle-current-completion-in-Completions)))
+                                      'help-echo 'icicle-mouseover-help)))
+                                 (when icicle-image-files-in-Completions
+                                   (let ((img-ov  (overlays-in (point) (min (point-max) (1+ (point))))))
+                                     (if img-ov
+                                         (delete-overlay (car img-ov))
+                                       (put-image thumb-img beg)
+                                       (setq img-ov  (loop for ov in (overlays-in
+                                                                      (point) (min (point-max) (1+ (point))))
+                                                           when (overlay-get ov 'put-image) collect ov into ovs
+                                                           finally return (car ovs)))
+                                       (overlay-put img-ov 'image-file image-file)
+                                       (overlay-put img-ov 'thumb-img thumb-img)
+                                       (overlay-put img-ov 'image-size (image-size thumb-img))))
+                                   ;; `image-only'.  Replace file name with a space.
+                                   ;;                And hide mouse-face highlighting, as it just confuses.
+                                   (when (eq 'image-only icicle-image-files-in-Completions)
+                                     (with-current-buffer "*Completions*"
+                                       (put-text-property
+                                        (point) (+ (point) (length (icicle-current-completion-in-Completions)))
+                                        'mouse-face 'default))
+                                     (let ((name-ov  (overlays-in end end)))
+                                       (if name-ov
+                                           (delete-overlay (car name-ov))
+                                         (setq name-ov  (make-overlay beg end))
+                                         (overlay-put name-ov 'display " "))))))))))
+                       (goto-char next)))
+
+                   ;; Remove all newlines for images-only display.
+                   (when (eq icicle-image-files-in-Completions 'image-only)
+                     (save-excursion (goto-char (icicle-start-of-candidates-in-Completions))
+                                     (while (and (re-search-forward "$")  (not (eobp))) (delete-char 1)))))
+                 (set-buffer-modified-p nil)
+                 (setq buffer-read-only  t))))
+
+           ;; Put lighter, number of candidates, completion mode, and sort order in mode line.
+           (with-current-buffer (get-buffer "*Completions*")
+             (set (make-local-variable 'mode-line-format)
+                  (format "  %s%s%s, sorting %s%s"
+                          (icicle-propertize (format "%d" nb-cands) 'face 'icicle-mode-line-help)
+                          (if (and icicle-max-candidates
+                                   (integerp icicle-max-candidates) ; Not `RESET'.
+                                   (< icicle-max-candidates icicle-nb-candidates-before-truncation))
+                              (format "%s candidates shown"
+                                      (icicle-propertize (format "/%d" icicle-nb-candidates-before-truncation)
+                                                         'face 'icicle-mode-line-help))
+                            " candidates")
+                          (if (memq icicle-current-completion-mode '(prefix apropos))
+                              (format ", %s completion"
+                                      (icicle-propertize
+                                       (cond ((eq 'apropos icicle-current-completion-mode)
+                                              ;; If nil, COLLECTION arg is probably a fn and we set it to nil
+                                              ;; to prevent automatic input matching in
+                                              ;; `icicle-unsorted-apropos-candidates', because COLLECTION fn
+                                              ;; does everything.  So here we treat nil like `apropos'.
+                                              (if icicle-apropos-complete-match-fn
+                                                  (or (car (rassq icicle-apropos-complete-match-fn
+                                                                  icicle-S-TAB-completion-methods-alist))
+                                                      "")
+                                                "apropos"))
+                                             ((eq 'prefix icicle-current-completion-mode)
+                                              (case (icicle-current-TAB-method)
+                                                (fuzzy    "fuzzy")
+                                                (swank    "swank (fuzzy symbol)")
+                                                (vanilla  "vanilla")
+                                                (t        "prefix"))))
+                                       'face 'icicle-mode-line-help))
+                            "")
+                          (icicle-propertize (or (car (rassoc icicle-sort-comparer icicle-sort-orders-alist))
+                                                 "turned OFF")
+                                             'face 'icicle-mode-line-help)
+                          (if (and icicle-reverse-sort-p  icicle-sort-comparer)
+                              (icicle-propertize " (reversed)" 'face 'icicle-mode-line-help)
+                            "")))
+             (let* ((lighter  (cadr (assoc 'icicle-mode minor-mode-alist)))
+                    (regexp   (and lighter  (concat (regexp-quote icicle-lighter-truncation) "$")))
+                    props)
+               (when lighter
+                 (setq lighter  (concat lighter " ")
+                       props    (text-properties-at 0 lighter))
+                 (when (string-match regexp lighter) (setq lighter  (substring lighter 0 (match-beginning 0))))
+                 (add-text-properties 0 (length lighter) props lighter))
+               (setq mode-line-format  (concat lighter mode-line-format)))
+             (goto-char (icicle-start-of-candidates-in-Completions))
+             (set-window-point (get-buffer-window "*Completions*" 0) (point))
+             (icicle-fit-completions-window))
+
+           ;; Use the same font family as the starting buffer.  This is particularly for picking up
+           ;; the proper font for Unicode chars in `*Completions*'.  Emacs 23+ only.
+           ;; But skip this if using `oneonone.el', since `1on1-display-*Completions*-frame' does it.
+           (when (and (not (fboundp '1on1-display-*Completions*-frame))
+                      (get-buffer-window "*Completions*" 'visible)
+                      icicle-pre-minibuffer-buffer
+                      (> emacs-major-version 22))
+             (save-window-excursion
+               (select-window (get-buffer-window "*Completions*" 'visible))
+               (when (one-window-p t)   ; $$$$$ Also this? (window-dedicated-p (selected-window))
+                 (let* ((orig-win       (get-buffer-window icicle-pre-minibuffer-buffer 'visible))
+                        (orig-font-fam  (and (window-live-p orig-win)
+                                             (save-window-excursion (select-window orig-win)
+                                                                    (face-attribute 'default :family)))))
+                   (when orig-font-fam (set-face-attribute 'default (selected-frame) :family orig-font-fam))))))
+           (message nil)))))            ; Clear out any "Looking for..."
+
+
 ;; $$ Probably need to do something to work around problem of Windows
 ;; selecting the new frame, when `pop-up-frames' is non-nil.  Need to
 ;; redirect focus back to the frame with the minibuffer.  Leave it as
@@ -2076,7 +2594,7 @@ If ALTERNATIVEP is non-nil, the alternative sort order is returned."
   (interactive)
   (let ((cur-buf        (current-buffer))
         (icicles-cmd-p  (or icicle-candidate-action-fn icicle-multi-completing-p)))
-    (with-output-to-temp-buffer "*Help*"
+    (icicle-with-help-window "*Help*"
       (help-setup-xref (list #'icicle-minibuffer-help) (interactive-p))
       (when (icicle-completing-p)
         (princ (format "You are completing input%s.%s"
@@ -2915,7 +3433,7 @@ e.g., `C-u C-RET' then that candidate is so wrapped."
 (defun icicle-insert-candidate-action (cand)
   "Action function for `icicle-insert-history-element' and `icicle-roundup'."
   ;; FREE here: TO-INSERT, COUNT.
-  (when (and cand  (not (equal cand "")))
+  (unless (equal cand "")
     (let ((prefix-arg  (if current-prefix-arg (prefix-numeric-value current-prefix-arg) icicle-pref-arg)))
       (push (if (and prefix-arg  (natnump prefix-arg)) (format "\"%s\"" cand) cand) to-insert)
       (unless (and prefix-arg  (<= prefix-arg 0)) (push " " to-insert))
@@ -3845,9 +4363,10 @@ Optional argument WORD-P non-nil means complete only a word at a time."
           ;; beyond a complete candidate - e.g. `forwar-char' to `forward-char-'.
           (setq word-complete-input   (icicle-input-from-minibuffer)
                 return-value
-                (let ((temp-buffer-show-hook       nil) ; Don't let it fit frame here.
-                      (completion-auto-help        nil) ; Don't show `*Completions*'.
-                      (minibuffer-message-timeout  0)) ; No timeout.
+                (let ((temp-buffer-show-hook         nil) ; Don't let it fit frame here.
+                      (temp-buffer-window-show-hook  nil) ; Don't let it fit frame here (Emacs 24.4+).
+                      (completion-auto-help          nil) ; Don't show `*Completions*'.
+                      (minibuffer-message-timeout    0)) ; No timeout.
                   (icicle-clear-minibuffer)
                   (insert icicle-current-input)
                   (save-selected-window (minibuffer-complete-word)))
@@ -4500,18 +5019,30 @@ Otherwise, after expanding input:
 ;; $$$$$$ Gets thrown off if user clicks in another frame.  Presumably more than one Emacs bug involved
 ;;        here, with frame focus, input focus, minibuffer msgs, etc.  See also Emacs bug #14810.
 (defun icicle-switch-to/from-minibuffer () ; Bound to `pause' in Icicle mode.
-  "Switch to minibuffer or previous buffer, in other window.
+  "Switch input focus to minibuffer or previous buffer, in other window.
 If current buffer is the minibuffer, then switch to the buffer that
 was previously current.  Otherwise, switch to the minibuffer."
   (interactive)
   (cond ((not (active-minibuffer-window))
-         (icicle-msg-maybe-in-minibuffer "Cannot switch buffer: minibuffer is not active"))
-        ((eq (selected-window) (active-minibuffer-window))
-         (switch-to-buffer-other-window icicle-pre-minibuffer-buffer)
-         (icicle-msg-maybe-in-minibuffer "Input in `%s' now" icicle-pre-minibuffer-buffer))
+         (message "Cannot switch focus: minibuffer is not active"))
+        ;; Do not use this test: (eq (selected-window) (active-minibuffer-window)).
+        ;; Instead, test for anything other than `icicle-pre-minibuffer-buffer'.  E.g., even if user
+        ;; manually selected (e.g. clicked in) another buffer then switch to `icicle-pre-minibuffer-buffer'.
+        ((not (eq (window-buffer) icicle-pre-minibuffer-buffer))
+         (let ((minibuffer-message-timeout  1))
+           (icicle-msg-maybe-in-minibuffer "Wait a sec - changing input focus to `%s'..."
+                                           icicle-pre-minibuffer-buffer))
+         (switch-to-buffer-other-window icicle-pre-minibuffer-buffer))
         (t
          (select-window (active-minibuffer-window))
-         (icicle-msg-maybe-in-minibuffer "Input in MINIBUFFER now"))))
+         (let ((minibuffer-message-timeout  1))
+           (icicle-msg-maybe-in-minibuffer "Wait a sec - changing input focus to MINIBUFFER..."))
+         ;; If standalone minibuffer frame had focus when minibuffer was entered, then this helps.
+         ;; Otherwise, the command does not bring focus back to the minibuffer frame.  Likewise,
+         ;; if some other frame has been selected manually while the minibuffer is active.
+         ;; But this breaks use when minibuffer frame did not have the initial focus.  So we don't use it.
+         ;; (select-frame-set-input-focus (window-frame (selected-window)))
+         )))
 
 (defun icicle-switch-to-Completions-buf () ; Bound to `C-insert' in minibuffer.
   "Select the completion list window.
@@ -4966,7 +5497,7 @@ ALTP is passed to `icicle-candidate-action-1'."
           (when error-msg (setq failures  (cons (cons (car candidates) error-msg) failures)))
           (setq candidates  (cdr candidates))))
       (when failures
-        (with-output-to-temp-buffer "*Help*"
+        (icicle-with-help-window "*Help*"
           (princ "Action failures:")(terpri)(terpri)
           (mapcar (lambda (entry)
                     (princ (car entry)) (princ ":") (terpri) (princ "  ")
@@ -5801,7 +6332,7 @@ Non-nil optional arg NO-ERROR-P prints an error message but does not
                  (format "Inode:                      %S\n" inode)
                  (format "Device number:              %s\n" device)
                  image-info)))
-          (with-output-to-temp-buffer "*Help*"
+          (icicle-with-help-window "*Help*"
             (when bmk
               (if internal-form-p
                   (let* ((bname     (bookmark-name-from-full-record bmk))
@@ -5861,8 +6392,6 @@ You can use this command only from the minibuffer (`\\<minibuffer-local-completi
   (run-hooks 'mouse-leave-buffer-hook)  ; Give temp modes such as isearch a chance to turn off.
   (let (;;$$$$$$ (buffer    (window-buffer))
         (posn-win  (posn-window (event-start event)))
-        (posn-col  (car (posn-col-row (event-start event))))
-        (posn-row  (cdr (posn-col-row (event-start event))))
         choice base-size)
     ;; (read-event)                 ; Swallow mouse up event. $$ Not needed if bound to up event.
     (with-current-buffer (window-buffer posn-win)
@@ -5954,8 +6483,6 @@ which can position mouse pointer on a standalone minibuffer frame."
   (run-hooks 'mouse-leave-buffer-hook)  ; Give temp modes such as isearch a chance to turn off.
   (let (;; $$$$$$ (buffer    (window-buffer))
         (posn-win  (posn-window (event-start event)))
-        (posn-col  (car (posn-col-row (event-start event))))
-        (posn-row  (cdr (posn-col-row (event-start event))))
         candidate base-size)
     ;; (read-event)                 ; Swallow mouse up event. $$ Not needed if bound to up event.
     (with-current-buffer (window-buffer posn-win)
@@ -6083,7 +6610,8 @@ This, in effect, performs a set intersection operation on 1) the set
 of candidates in effect before the operation and 2) the set of
 candidates that match the current input.  You can repeatedly use this
 command to continue intersecting candidate sets, progressively
-narrowing the set of matches.
+narrowing the set of matches.  A recursive minibuffer is entered each
+time this command is used.
 
 You can use this command only from the minibuffer (`\\<minibuffer-local-completion-map>\
 \\[icicle-narrow-candidates]')."
@@ -6168,8 +6696,8 @@ You can use this command only from the minibuffer (`\\<minibuffer-local-completi
                                                           (funcall icicle-get-alist-candidate-function
                                                                    (car cand)))
                                                         (icicle-filter-alist minibuffer-completion-table
-                                                                             icicle-completion-candidates))
-                                                     (mapcar #'list icicle-completion-candidates))
+                                                                             icicle-cands-to-narrow))
+                                                     (mapcar #'list icicle-cands-to-narrow))
                                                    nil icicle-require-match-p nil
                                                    minibuffer-history-variable)))))
              ;; Normally, `icicle-narrow-candidates' is called from the minibuffer.
@@ -6214,11 +6742,14 @@ You can use this command only from the minibuffer (`\\<minibuffer-local-completi
 
 (put 'icicle-apropos-complete-and-narrow 'icicle-completing-command t)
 (put 'icicle-apropos-complete-and-narrow 'icicle-apropos-completing-command t)
-(defun icicle-apropos-complete-and-narrow () ; Bound to `S-SPC' in minibuffer.
-  "Apropos complete, then `icicle-narrow-candidates'.
-You can use this command only from the minibuffer (`\\<minibuffer-local-completion-map>\
-\\[icicle-apropos-complete-and-narrow]')."
-  (interactive)
+(defun icicle-apropos-complete-and-narrow (&optional with-predicate-p) ; Bound to `S-SPC' in minibuffer.
+  "Apropos complete, then narrow to the current set of completions.
+You can use this command only during minibuffer completion, when it is
+bound to `\\<minibuffer-local-completion-map>\\[icicle-apropos-complete-and-narrow]'.
+
+This is the same as using `S-TAB' followed by `\\[icicle-narrow-candidates]' or, with a prefix
+arg, `\\[icicle-narrow-candidates-with-predicate]'.  In the latter case you are prompted for a predicate."
+  (interactive "P")
   (when (interactive-p) (icicle-barf-if-outside-minibuffer))
   ;; $$$$$ (let ((icicle-top-level-when-sole-completion-flag  t))
   (when (and (eq icicle-current-completion-mode 'prefix)
@@ -6236,23 +6767,58 @@ You can use this command only from the minibuffer (`\\<minibuffer-local-completi
   (if (eq icicle-last-completion-command 'icicle-apropos-complete-no-display)
       (icicle-apropos-complete-no-display)
     (icicle-apropos-complete))
-  (icicle-narrow-candidates))
+  (if with-predicate-p (icicle-narrow-candidates-with-predicate) (icicle-narrow-candidates)))
 
-(defun icicle-narrow-candidates-with-predicate (&optional predicate) ; Bound to `M-&' in minibuffer.
+;; $$$$$$$$ Would it be good to use `icicle-must-pass-after-match-predicate'?
+;;
+(defun icicle-narrow-candidates-with-predicate (&optional predicate allp) ; Bound to `M-&' in minibuffer.
   "Narrow the set of completion candidates by applying a predicate.
 You can repeatedly use this command to apply additional predicates,
 progressively narrowing the set of candidates.
 
+A recursive minibuffer is entered each time this is used.  Only the
+current candidates for which the predicate is true are retained.
+
+You are prompted for the filtering predicate, which can be a function
+name or a lambda expression.  You can use completion to choose from
+some existing predicate names.
+
+The predicates available for completion depend on the current type of
+completion (input).  For example, buffer-name predicates are available
+for buffer-name completion.  With a prefix arg, predicates of
+additional types are also available for completion.
+
+You can customize the predicates available for a given completion type
+TYPE using option `icicle-cand-preds-for-TYPE'.  You can customize the
+predicates available with a prefix arg by customizing option
+`icicle-cand-preds-all'.
+
+You can define a new completion (input) type TYPE, by defining the
+corresponding new option `icicle-cand-preds-for-TYPE'.  If you do
+that, you will likely want to also customize `icicle-cand-preds-all',
+adding the predicates for TYPE to the value.
+
+\(For Emacs 20-23, completion is not available, but you can use \
+\\<minibuffer-local-map>`\\[next-history-element]'
+to retrieve the same predicates as default values.)
+
+To compose a lambda expression, you can use any keys in
+`icicle-read-expression-map' that do not conflict with completion
+keys.  In addition, since `TAB' conflicts here, you can use `C-M-i' or
+`ESC tab' to complete a Lisp symbol.
+
 You can use this command only from the minibuffer (`\\<minibuffer-local-completion-map>\
 \\[icicle-narrow-candidates-with-predicate]').
 
 When called from Lisp with non-nil arg PREDICATE, use that to narrow."
-  (interactive)
-  (when (interactive-p) (icicle-barf-if-outside-minibuffer))
+  (interactive "i\nP")
+  (when (interactive-p)
+    (icicle-barf-if-outside-minibuffer)
+    (message "Gathering predicates to choose from (or enter a lambda expression)..."))
+  (setq icicle-current-completion-mode  'apropos)
   (let (;; Restore match function, in case it was bound to nil, e.g., by `C-h C-o'.
         (icicle-apropos-complete-match-fn  icicle-last-apropos-complete-match-fn)
-        (icicle-progressive-completing-p   t) ; Inhibit completion by `icicle-minibuffer-setup'.
-        (last-completion-cmd               (or icicle-last-completion-command  'icicle-apropos-complete))
+        ;; $$$$$$$$ (icicle-progressive-completing-p   t) ; Inhibit completion by `icicle-minibuffer-setup'.
         (enable-recursive-minibuffers      t))
     (cond ((null icicle-completion-candidates)
            (icicle-user-error "No completion candidates.  Did you use `TAB' or `S-TAB'?"))
@@ -6264,7 +6830,7 @@ When called from Lisp with non-nil arg PREDICATE, use that to narrow."
                                                     (symbol-value minibuffer-history-variable)))
              ;; $$$$$$ Should this now use `icicle-current-input'
              ;;        instead of (car icicle-completion-candidates), for PCM?
-             (icicle-condition-case-no-debug i-narrow-candidates
+             (icicle-condition-case-no-debug i-narrow-candidates-with-predicate
                  (throw 'icicle-read-top
                    (if (and (icicle-file-name-input-p)
                             insert-default-directory
@@ -6275,43 +6841,118 @@ When called from Lisp with non-nil arg PREDICATE, use that to narrow."
                (no-catch (setq icicle-current-input  (car icicle-completion-candidates))
                          (icicle-retrieve-last-input)
                          icicle-current-input)
-               (error (message "%s" (error-message-string i-narrow-candidates))))))
+               (error (message "%s" (error-message-string i-narrow-candidates-with-predicate)))))
+           (funcall (or icicle-last-completion-command  'icicle-apropos-complete)))
           (t                            ; Read new predicate and incorporate it.
-           (let ((pred  (or predicate
-                            (icicle-read-from-minibuf-nil-default
-                             "Additional predicate to apply: "
-                             nil read-expression-map t (if (boundp 'function-name-history)
-                                                           'function-name-history
-                                                         'icicle-function-name-history)))))
-             ;; Update `minibuffer-completion-predicate' or `read-file-name-predicate' to also use new
-             ;; predicate, PRED.  The logic here is like that for `icicle-remove-cand-from-lists'.
-             (cond (;; File name input, Emacs 22+.
-                    ;; Update `read-file-name-predicate' if prior to Emacs 23.2.
-                    ;; Else update `minibuffer-completion-predicate'.
-                    (and (icicle-file-name-input-p)  (> emacs-major-version 21))
-                    (let ((var  (if (or (> emacs-major-version 23)
-                                        (and (= emacs-major-version 23)  (> emacs-minor-version 1)))
-                                    'minibuffer-completion-predicate
-                                  'read-file-name-predicate)))
-                      (set var (if (symbol-value var)
-                                   (lexical-let ((curr-pred  (symbol-value var)))
-                                     `(lambda (file-cand)
-                                       (and (funcall ',curr-pred file-cand)  (funcall ',pred file-cand))))
-                                 pred))))
-
-                   ;; File name input, Emacs 20 or 21.  We cannot do anything for file names.
-                   ;; `TAB' or `S-TAB' will unfortunately bring it back as a candidate.
-                   ((icicle-file-name-input-p))
-
-                   ;; Non-file name input, all versions.  Update `minibuffer-completion-predicate'.
-                   (t (setq minibuffer-completion-predicate
-                            (if minibuffer-completion-predicate
-                                ;; Add PRED to the existing predicate.
-                                (lexical-let ((curr-pred  minibuffer-completion-predicate))
-                                  `(lambda (cand) (and (funcall ',curr-pred cand)  (funcall ',pred cand))))
-                              ;; Set predicate to PRED.
-                              pred)))))))
-    (funcall last-completion-cmd)))
+           (let* ((minibuffer-setup-hook   (cons ; Make sure new minibuffer is completion reference buf.
+                                            (lambda ()
+                                              (with-current-buffer (get-buffer-create "*Completions*")
+                                                (set (make-local-variable 'completion-reference-buffer)
+                                                     (window-buffer (active-minibuffer-window)))))
+                                            minibuffer-setup-hook))
+                  ;; If `icicle-display-string' was used, then get back the original candidates.
+                  ;; However, this also means that the candidates will no longer be displayed according
+                  ;; to `icicle-display-string'.  $$$$$$ FIXME?  To fix we would need to do something
+                  ;; like what is done in `icicle-display-candidates-in-Completions'.
+                  (icicle-cands-to-narrow  (mapcar (lambda (cc)
+                                                     (or (get-text-property 0 'icicle-orig-cand cc)  cc))
+                                                   icicle-completion-candidates))
+                  (icicle-narrow-regexp    (and icicle-compute-narrowing-regexp-p
+                                                ;; (regexp-opt ()) returns nil in older Emacs versions.
+                                                icicle-cands-to-narrow
+                                                (regexp-opt icicle-cands-to-narrow)))
+                  (icicle-cand-preds       (if allp icicle-cand-preds-all (icicle-cand-preds)))
+                  (pred
+                   (or predicate
+                       (if (fboundp 'make-composed-keymap) ; Emacs 24+
+                           (let ((temp-map                                (make-composed-keymap
+                                                                           minibuffer-local-completion-map
+                                                                           icicle-read-expression-map))
+                                 (icicle-show-Completions-initially-flag  t)
+                                 (icicle-candidate-properties-alist       ())
+                                 (icicle-current-input                    icicle-current-input)
+                                 (icicle-last-input                       icicle-last-input)
+                                 (icicle-must-pass-after-match-predicate  nil)
+                                 (icicle-apropos-complete-match-fn        'string-match)
+                                 (icicle-sort-orders-alist
+                                  '(("turned OFF")
+                                    ("by abbrev frequency" . icicle-command-abbrev-used-more-p)
+                                    ("by previous use alphabetically" . icicle-historical-alphabetic-p)
+                                    ("by last use as input" . icicle-latest-input-first-p)
+                                    ("by last use" . icicle-latest-use-first-p)
+                                    ("alphabetical" . icicle-case-string-less-p))))
+                             (define-key temp-map (icicle-kbd "C-M-i")   'lisp-indent-line)
+                             (define-key temp-map (icicle-kbd "ESC tab") 'lisp-indent-line)
+                             (read
+                              (condition-case nil
+                                  (icicle-completing-read "Additional predicate to apply: "
+                                                          (mapcar #'list icicle-cand-preds)
+                                                          nil nil nil (if (boundp 'function-name-history)
+                                                                          'function-name-history
+                                                                        'icicle-function-name-history)
+                                                          nil nil temp-map)
+                                (error nil))))
+                         (condition-case nil
+                             (icicle-read-from-minibuf-nil-default
+                              (substitute-command-keys
+                               "Additional predicate to apply (`\\[next-history-element]' for defaults): ")
+                              nil icicle-read-expression-map t (if (boundp 'function-name-history)
+                                                                   'function-name-history
+                                                                 'icicle-function-name-history)
+                              icicle-cand-preds)
+                           (error nil)))))
+                  (result                  (let ((icicle-must-pass-predicate  
+                                                  `(lambda (c)
+                                                     (and (member c ',icicle-cands-to-narrow)
+                                                          (funcall ',pred c))))
+                                                 (icicle-show-Completions-initially-flag  t))
+                                             (cond ((icicle-file-name-input-p)
+                                                    (read-file-name "Match also (regexp): "
+                                                                    (icicle-file-name-directory-w-default
+                                                                     icicle-current-input)
+                                                                    nil icicle-require-match-p))
+                                                   ((functionp minibuffer-completion-table)
+                                                    (completing-read "Match also (regexp): "
+                                                                     minibuffer-completion-table
+                                                                     nil icicle-require-match-p nil
+                                                                     minibuffer-history-variable))
+                                                   (t ; cons, obarray, etc.
+                                                    (completing-read
+                                                     "Match also (regexp): "
+                                                     (if icicle-whole-candidate-as-text-prop-p
+                                                         (mapcar
+                                                          (lambda (cand)
+                                                            (funcall icicle-get-alist-candidate-function
+                                                                     (car cand)))
+                                                          (icicle-filter-alist minibuffer-completion-table
+                                                                               icicle-cands-to-narrow))
+                                                       (mapcar #'list icicle-cands-to-narrow))
+                                                     nil icicle-require-match-p nil
+                                                     minibuffer-history-variable))))))
+             ;; Normally, `icicle-narrow-candidates-predicate' is called from the minibuffer.
+             ;; If not, just return the result read.
+             (if (> (minibuffer-depth) 0)
+                 (icicle-condition-case-no-debug i-narrow-candidates-with-predicate
+                     (throw 'icicle-read-top result)
+                   (no-catch (setq icicle-current-input  result)
+                             (icicle-retrieve-last-input)
+                             icicle-current-input)
+                   (error (message "%s" (error-message-string i-narrow-candidates-with-predicate))))
+               result))))))
+
+(defun icicle-cand-preds ()
+  "Predicates currently available for `M-&'."
+  (let ((preds  ())
+        comp-p)
+    (mapatoms (lambda (sy)
+                (let ((sname  (symbol-name sy)))
+                  (when (and (string-match "\\`icicle-cand-preds-for-\\([^ \t\n]+\\)" sname)
+                             (setq comp-p  (intern-soft (format "icicle-%s-completing-p"
+                                                                (match-string 1 sname))))
+                             (condition-case nil (symbol-value comp-p) (error nil)))
+                    (dolist (ps  (symbol-value sy)) (push ps preds))))))
+    (dolist (ps  icicle-cand-preds-for-misc) (push ps preds))
+    (nreverse preds)))
 
 (defun icicle-save-predicate-to-variable (askp) ; Bound to `C-M-&' in minibuffer.
   "Save the current completion predicate to a variable.
@@ -6661,9 +7302,10 @@ You can use this command only from the minibuffer (`\\<minibuffer-local-completi
   "Helper function for `icicle-candidate-set-retrieve(-more)'.
 ARG is the same as the raw prefix arg for `icicle-candidate-set-retrieve'.
 MOREP non-nil means add the saved candidates, don't replace existing."
-  (let ((name        nil)
-        (variablep   (and arg  (atom arg)))
-        (curr-cands  icicle-completion-candidates)
+  (let ((name            nil)
+        (variablep       (and arg  (atom arg)))
+        (curr-cands      icicle-completion-candidates)
+        (added/restored  (if morep "ADDED" "RESTORED"))
         saved-cands)
     (if arg
         (let ((icicle-whole-candidate-as-text-prop-p  nil)
@@ -6695,7 +7337,7 @@ MOREP non-nil means add the saved candidates, don't replace existing."
     (cond ((null saved-cands)
            (deactivate-mark)
            (icicle-display-candidates-in-Completions)
-           (message "No saved candidates to restore") (sit-for 2))
+           (message "No saved candidates to %s" (if morep "add" "restore")) (sit-for 2))
           (t
            (setq icicle-completion-candidates ; Remove directory part if completing file names
                  (if (icicle-file-name-input-p) ; using `read-file-name'.
@@ -6716,9 +7358,10 @@ MOREP non-nil means add the saved candidates, don't replace existing."
                   (save-selected-window
                     (select-window (minibuffer-window))
                     (minibuffer-message (if name
-                                            (format "  [Saved candidates RESTORED from %s `%s']"
+                                            (format "  [Saved candidates %s from %s `%s']"
+                                                    added/restored
                                                     (if variablep "variable" "cache file") name)
-                                          "  [Saved candidates RESTORED]")))
+                                          (format "  [Saved candidates %s]" added/restored))))
                   (let ((icicle-minibuffer-setup-hook ; Pre-complete
                          (cons (if (eq icicle-last-completion-command
                                        'icicle-apropos-complete-no-display)
@@ -8600,6 +9243,8 @@ This includes buffers in iconified frames."
   (interactive)
   (icicle-keep/remove-buffer-cands-for-visible 'KEEP-P))
 
+
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (provide 'icicles-mcmd)