initial commit
[emacs-init.git] / auto-install / icicles-cmd2.el
1 ;;; icicles-cmd2.el --- Top-level commands for Icicles
2 ;;
3 ;; Filename: icicles-cmd2.el
4 ;; Description: Top-level commands for Icicles
5 ;; Author: Drew Adams
6 ;; Maintainer: Drew Adams
7 ;; Copyright (C) 1996-2011, Drew Adams, all rights reserved.
8 ;; Created: Thu May 21 13:31:43 2009 (-0700)
9 ;; Version: 22.0
10 ;; Last-Updated: Fri Sep  9 13:53:30 2011 (-0700)
11 ;;           By: dradams
12 ;;     Update #: 4206
13 ;; URL: http://www.emacswiki.org/cgi-bin/wiki/icicles-cmd2.el
14 ;; Keywords: extensions, help, abbrev, local, minibuffer,
15 ;;           keys, apropos, completion, matching, regexp, command
16 ;; Compatibility: GNU Emacs: 20.x, 21.x, 22.x, 23.x
17 ;;
18 ;; Features that might be required by this library:
19 ;;
20 ;;   `apropos', `apropos-fn+var', `avoid', `backquote', `bytecomp',
21 ;;   `cl', `cus-edit', `cus-face', `cus-load', `cus-start', `doremi',
22 ;;   `easymenu', `el-swank-fuzzy', `ffap', `ffap-', `frame-cmds',
23 ;;   `frame-fns', `fuzzy', `fuzzy-match', `hexrgb', `icicles-cmd1',
24 ;;   `icicles-face', `icicles-fn', `icicles-mac', `icicles-mcmd',
25 ;;   `icicles-opt', `icicles-var', `image-dired', `kmacro',
26 ;;   `levenshtein', `misc-fns', `mouse3', `mwheel', `pp', `pp+',
27 ;;   `regexp-opt', `ring', `ring+', `strings', `thingatpt',
28 ;;   `thingatpt+', `wid-edit', `wid-edit+', `widget'.
29 ;;
30 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
31 ;;
32 ;;; Commentary:
33 ;;
34 ;;  This is a helper library for library `icicles.el'.  It defines
35 ;;  top-level commands (and a few non-interactive functions used in
36 ;;  those commands).  This is a continuation of library
37 ;;  `icicles-cmd1.el' (a single file for all top-level commands would
38 ;;  be too large to upload to Emacs Wiki).
39 ;;
40 ;;  For commands to be used mainly in the minibuffer or buffer
41 ;;  `*Completions*', see `icicles-mcmd.el'.
42 ;;
43 ;;  For Icicles documentation, see `icicles-doc1.el' and
44 ;;  `icicles-doc2.el'.
45 ;;
46 ;;  If you use the byte-compiled version of this library,
47 ;;  `icicles-cmd2.elc', in Emacs 23, then it must be byte-compiled
48 ;;  using Emacs 23.  Otherwise, Icicles key completion (and perhaps
49 ;;  other things?) will not work correctly.
50 ;;
51 ;;  Macros defined here:
52 ;;
53 ;;    `icicle-define-search-bookmark-command',
54 ;;    `icicle-with-comments-hidden'.
55 ;;
56 ;;  Commands defined here - (+) means a multi-command:
57 ;;
58 ;;    (+)`a', (+)`any', (+)`buffer', (+)`file', (+)`icicle-anything',
59 ;;    (+)`icicle-apply', `icicle-apropos', `icicle-apropos-command',
60 ;;    `icicle-apropos-function', `icicle-apropos-option',
61 ;;    `icicle-apropos-variable', `icicle-apropos-zippy',
62 ;;    (+)`icicle-bookmark-a-file', (+)`icicle-choose-faces',
63 ;;    (+)`icicle-choose-invisible-faces',
64 ;;    (+)`icicle-choose-visible-faces', (+)`icicle-comint-command',
65 ;;    (+)`icicle-comint-search', (+)`icicle-compilation-search',
66 ;;    (+)`icicle-complete-keys', `icicle-complete-thesaurus-entry',
67 ;;    (+)`icicle-describe-option-of-type', (+)`icicle-doc',
68 ;;    (+)`icicle-exchange-point-and-mark',
69 ;;    (+)`icicle-find-file-all-tags',
70 ;;    (+)`icicle-find-file-all-tags-other-window',
71 ;;    (+)`icicle-find-file-all-tags-regexp',
72 ;;    (+)`icicle-find-file-all-tags-regexp-other-window',
73 ;;    (+)`icicle-find-file-some-tags',
74 ;;    (+)`icicle-find-file-some-tags-other-window',
75 ;;    (+)`icicle-find-file-some-tags-regexp',
76 ;;    (+)`icicle-find-file-some-tags-regexp-other-window',
77 ;;    (+)`icicle-find-file-tagged',
78 ;;    (+)`icicle-find-file-tagged-other-window', (+)`icicle-font',
79 ;;    (+)`icicle-frame-bg', (+)`icicle-frame-fg', (+)`icicle-fundoc',
80 ;;    (+)`icicle-goto-global-marker',
81 ;;    (+)`icicle-goto-global-marker-or-pop-global-mark',
82 ;;    (+)`icicle-goto-marker',
83 ;;    (+)`icicle-goto-marker-or-set-mark-command',
84 ;;    (+)`icicle-hide-faces', (+)`icicle-hide-only-faces',
85 ;;    `icicle-hide/show-comments', (+)`icicle-imenu',
86 ;;    (+)`icicle-imenu-command', (+)`icicle-imenu-command-full',
87 ;;    (+)`icicle-imenu-face-full', (+)`icicle-imenu-face-full',
88 ;;    (+)`icicle-imenu-full', (+)`icicle-imenu-key-explicit-map',
89 ;;    (+)`icicle-imenu-key-explicit-map-full',
90 ;;    (+)`icicle-imenu-key-implicit-map',
91 ;;    (+)`icicle-imenu-key-implicit-map-full',
92 ;;    (+)`icicle-imenu-macro', (+)`icicle-imenu-macro-full',
93 ;;    (+)`icicle-imenu-non-interactive-function',
94 ;;    (+)`icicle-imenu-non-interactive-function-full',
95 ;;    (+)`icicle-imenu-user-option',
96 ;;    (+)`icicle-imenu-user-option-full', (+)`icicle-imenu-variable',
97 ;;    (+)`icicle-imenu-variable-full', `icicle-ido-like-mode',
98 ;;    (+)`icicle-Info-goto-node', (+)`icicle-Info-index',
99 ;;    (+)`icicle-Info-index-20', (+)`icicle-Info-menu',
100 ;;    `icicle-Info-virtual-book', (+)`icicle-insert-thesaurus-entry',
101 ;;    (+)`icicle-keyword-list', (+)`icicle-map',
102 ;;    `icicle-next-visible-thing', `icicle-non-whitespace-string-p',
103 ;;    (+)`icicle-object-action', (+)`icicle-occur',
104 ;;    (+)`icicle-pick-color-by-name', (+)`icicle-plist',
105 ;;    `icicle-previous-visible-thing', `icicle-read-color',
106 ;;    `icicle-read-kbd-macro', (+)`icicle-regexp-list',
107 ;;    `icicle-save-string-to-variable', (+)`icicle-search',
108 ;;    (+)`icicle-search-all-tags-bookmark',
109 ;;    (+)`icicle-search-all-tags-regexp-bookmark',
110 ;;    (+)`icicle-search-autofile-bookmark',
111 ;;    (+)`icicle-search-bookmark',
112 ;;    (+)`icicle-search-bookmark-list-bookmark',
113 ;;    `icicle-search-bookmark-list-marked',
114 ;;    (+)`icicle-search-bookmarks-together',
115 ;;    (+)`icicle-search-buffer', (+)`icicle-search-buff-menu-marked',
116 ;;    (+)`icicle-search-char-property', (+)`icicle-search-defs',
117 ;;    (+)`icicle-search-defs-full',
118 ;;    (+)`icicle-search-desktop-bookmark',
119 ;;    (+)`icicle-search-dired-bookmark',
120 ;;    (+)`icicle-search-dired-marked', (+)`icicle-search-file',
121 ;;    (+)`icicle-search-file-bookmark', (+)`icicle-search-generic',
122 ;;    (+)`icicle-search-gnus-bookmark',
123 ;;    `icicle-search-highlight-cleanup',
124 ;;    (+)`icicle-search-ibuffer-marked',
125 ;;    (+)`icicle-search-info-bookmark', (+)`icicle-search-keywords',
126 ;;    (+)`icicle-search-lines',
127 ;;    (+)`icicle-search-local-file-bookmark',
128 ;;    (+)`icicle-search-man-bookmark',
129 ;;    (+)`icicle-search-non-file-bookmark',
130 ;;    (+)`icicle-search-overlay-property',
131 ;;    (+)`icicle-search-paragraphs', (+)`icicle-search-pages',
132 ;;    (+)`icicle-search-region-bookmark',
133 ;;    (+)`icicle-search-remote-file-bookmark',
134 ;;    (+)`icicle-search-sentences',
135 ;;    (+)`icicle-search-some-tags-bookmark',
136 ;;    (+)`icicle-search-some-tags-regexp-bookmark',
137 ;;    (+)`icicle-search-specific-buffers-bookmark',
138 ;;    (+)`icicle-search-specific-files-bookmark',
139 ;;    (+)`icicle-search-text-property', (+)`icicle-search-thing',
140 ;;    (+)`icicle-search-this-buffer-bookmark',
141 ;;    (+)`icicle-search-url-bookmark',
142 ;;    `icicle-search-w-isearch-string',
143 ;;    (+)`icicle-search-w3m-bookmark', (+)`icicle-search-word',
144 ;;    (+)`icicle-search-xml-element',
145 ;;    (+)`icicle-search-xml-element-text-node',
146 ;;    (+)`icicle-select-frame', `icicle-select-frame-by-name',
147 ;;    `icicle-set-S-TAB-methods-for-command',
148 ;;    `icicle-set-TAB-methods-for-command', (+)`icicle-show-faces',
149 ;;    (+)`icicle-show-only-faces', (+)`icicle-synonyms',
150 ;;    (+)`icicle-tag-a-file', (+)`icicle-tags-search',
151 ;;    (+)`icicle-untag-a-file', (+)`icicle-vardoc',
152 ;;    (+)`icicle-where-is', (+)`synonyms', (+)`what-which-how'.
153 ;;
154 ;;  Non-interactive functions defined here:
155 ;;
156 ;;    `icicle-add-key+cmd', `icicle-anything-candidate-value',
157 ;;    `icicle-apply-action', `icicle-apply-list-action',
158 ;;    `icicle-char-properties-in-buffer',
159 ;;    `icicle-char-properties-in-buffers',
160 ;;    `icicle-choose-anything-candidate',
161 ;;    `icicle-choose-candidate-of-type', `icicle-color-blue-lessp',
162 ;;    `icicle-color-completion-setup',
163 ;;    `icicle-color-distance-hsv-lessp',
164 ;;    `icicle-color-distance-rgb-lessp', `icicle-color-green-lessp',
165 ;;    `icicle-color-help', `icicle-color-hsv-lessp',
166 ;;    `icicle-color-hue-lessp', `icicle-color-red-lessp',
167 ;;    `icicle-color-saturation-lessp', `icicle-color-value-lessp',
168 ;;    `icicle-comint-hook-fn',
169 ;;    `icicle-comint-search-get-final-choice',
170 ;;    `icicle-comint-search-get-minibuffer-input',
171 ;;    `icicle-comint-search-send-input', `icicle-compilation-hook-fn',
172 ;;    `icicle-compilation-search-in-context-fn',
173 ;;    `icicle-complete-keys-1', `icicle-complete-keys-action',
174 ;;    `icicle-defined-thing-p', `icicle-describe-opt-action',
175 ;;    `icicle-describe-opt-of-type-complete', `icicle-doc-action',
176 ;;    `icicle-edmacro-parse-keys', `icicle-flat-list',
177 ;;    `icicle-fn-doc-minus-sig', `icicle-font-w-orig-size',
178 ;;    `icicle-get-anything-actions-for-type',
179 ;;    `icicle-get-anything-cached-candidates',
180 ;;    `icicle-get-anything-candidates',
181 ;;    `icicle-get-anything-candidates-of-type',
182 ;;    `icicle-get-anything-default-actions-for-type',
183 ;;    `icicle-get-anything-input-delay',
184 ;;    `icicle-get-anything-req-pat-chars',
185 ;;    `icicle-get-anything-types', `icicle-goto-marker-1',
186 ;;    `icicle-goto-marker-1-action', `icicle-group-regexp',
187 ;;    `icicle-imenu-command-p', `icicle-imenu-in-buffer-p',
188 ;;    `icicle-imenu-non-interactive-function-p',
189 ;;    `icicle-Info-book-order-p',
190 ;;    `icicle-Info-build-node-completions',
191 ;;    `icicle-Info-build-node-completions-1',
192 ;;    `icicle-Info-goto-node-1', `icicle-Info-goto-node-action',
193 ;;    `icicle-Info-index-action', `icicle-Info-read-node-name',
194 ;;    `icicle-insert-thesaurus-entry-cand-fn',
195 ;;    `icicle-invisible-face-p', `icicle-invisible-p',
196 ;;    `icicle-keys+cmds-w-prefix', `icicle-make-color-candidate',
197 ;;    `icicle-marker+text', `icicle-markers',
198 ;;    `icicle-next-single-char-property-change',
199 ;;    `icicle-next-visible-thing-1', `icicle-next-visible-thing-2',
200 ;;    `icicle-next-visible-thing-and-bounds',
201 ;;    `icicle-pick-color-by-name-action',
202 ;;    `icicle-previous-single-char-property-change',
203 ;;    `icicle-read-args-for-set-completion-methods',
204 ;;    `icicle-read-single-key-description',
205 ;;    `icicle-read-var-value-satisfying',
206 ;;    `icicle-region-or-buffer-limits', `icicle-search-action',
207 ;;    `icicle-search-action-1', `icicle-search-bookmark-action',
208 ;;    `icicle-search-char-property-scan',
209 ;;    `icicle-search-choose-buffers', `icicle-search-cleanup',
210 ;;    `icicle-search-define-candidates',
211 ;;    `icicle-search-define-candidates-1', `icicle-search-final-act',
212 ;;    `icicle-search-help',
213 ;;    `icicle-search-highlight-all-input-matches',
214 ;;    `icicle-search-highlight-and-maybe-replace',
215 ;;    `icicle-search-highlight-input-matches-here',
216 ;;    `icicle-search-in-context-default-fn',
217 ;;    `icicle-search-property-args', `icicle-search-quit-or-error',
218 ;;    `icicle-search-read-context-regexp', `icicle-search-read-word',
219 ;;    `icicle-search-regexp-scan',
220 ;;    `icicle-search-replace-all-search-hits',
221 ;;    `icicle-search-replace-cand-in-alist',
222 ;;    `icicle-search-replace-cand-in-mct',
223 ;;    `icicle-search-replace-fixed-case-p',
224 ;;    `icicle-search-replace-match',
225 ;;    `icicle-search-replace-search-hit', `icicle-search-thing-args',
226 ;;    `icicle-search-thing-scan', `icicle-search-where-arg',
227 ;;    `icicle-set-completion-methods-for-command',
228 ;;    `icicle-things-alist', `icicle-this-command-keys-prefix'.
229 ;;
230 ;;  Internal variables defined here:
231 ;;
232 ;;    `icicle-active-map', `icicle-info-buff', `icicle-info-window',
233 ;;    `icicle-key-prefix', `icicle-key-prefix-2',
234 ;;    `icicle-last-thing-type', `icicle-named-colors',
235 ;;    `icicle-orig-buff-key-complete', `icicle-orig-extra-cands',
236 ;;    `icicle-orig-font', `icicle-orig-frame', `icicle-orig-menu-bar',
237 ;;    `icicle-orig-pixelsize', `icicle-orig-pointsize',
238 ;;    `icicle-orig-show-initially-flag',
239 ;;    `icicle-orig-sort-orders-alist', `icicle-orig-win-key-complete',
240 ;;    `icicle-this-cmd-keys'.
241 ;;
242 ;;
243 ;;  ***** NOTE: The following functions defined in `cus-edit.el' have
244 ;;              been REDEFINED HERE:
245 ;;
246 ;;  `customize-face', `customize-face-other-window' - Multi-commands.
247 ;;
248 ;;
249 ;;  Key bindings made by Icicles: See "Key Bindings" in
250 ;;  `icicles-doc2.el'.
251 ;;
252 ;;  For descriptions of changes to this file, see `icicles-chg.el'.
253  
254 ;;(@> "Index")
255 ;;
256 ;;  If you have library `linkd.el' and Emacs 22 or later, load
257 ;;  `linkd.el' and turn on `linkd-mode' now.  It lets you easily
258 ;;  navigate around the sections of this doc.  Linkd mode will
259 ;;  highlight this Index, as well as the cross-references and section
260 ;;  headings throughout this file.  You can get `linkd.el' here:
261 ;;  http://dto.freeshell.org/notebook/Linkd.html.
262 ;;
263 ;;  (@> "Icicles Top-Level Commands, Part 2")
264 ;;    (@> "Icicles Commands for Other Packages")
265  
266 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
267 ;;
268 ;; This program is free software; you can redistribute it and/or
269 ;; modify it under the terms of the GNU General Public License as
270 ;; published by the Free Software Foundation; either version 3, or
271 ;; (at your option) any later version.
272 ;;
273 ;; This program is distributed in the hope that it will be useful,
274 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
275 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
276 ;; General Public License for more details.
277 ;;
278 ;; You should have received a copy of the GNU General Public License
279 ;; along with this program; see the file COPYING.  If not, write to
280 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
281 ;; Floor, Boston, MA 02110-1301, USA.
282 ;;
283 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
284 ;;
285 ;;; Code:
286
287 (eval-when-compile (require 'cl)) ;; case, loop
288                                   ;; plus, for Emacs < 21: dolist, push
289 (eval-when-compile (when (>= emacs-major-version 22) (require 'edmacro))) ;; edmacro-subseq
290 (eval-when-compile (require 'comint))
291   ;; comint-check-proc, comint-copy-old-input, comint-get-old-input, comint-input-ring,
292   ;; comint-prompt-regexp, comint-send-input
293 (eval-when-compile (require 'imenu)) ;; imenu-syntax-alist
294 (eval-when-compile (require 'compile)) ;; compilation-find-buffer
295 (eval-when-compile (require 'info)) ;; Info-goto-node
296 (eval-when-compile (require 'etags)) ;; tags-case-fold-search, tags-table-files,
297                                      ;; visit-tags-table-buffer
298 (eval-when-compile (when (> emacs-major-version 21)
299                      (require 'anything nil t))) ;; (no error if not found):
300   ;; anything-candidate-cache, anything-get-sources, anything-idle-delay, anything-pattern,
301   ;; anything-sources, anything-transform-candidates
302 (eval-when-compile (require 'yow nil t)) ;; (no error if not found):
303   ;; apropos-zippy, yow-after-load-message, yow-file, yow-load-message
304 (eval-when-compile (require 'cookie1 nil t)) ;; (no error if not found): cookie-cache
305 (require 'apropos-fn+var nil t) ;; (no error if not found):
306   ;; apropos-command, apropos-function, apropos-option, apropos-variable
307 (require 'strings nil t) ;; (no error if not found): read-number (my version)
308 (eval-when-compile (require 'bookmark+ nil t)) ;; (no error if not found):
309   ;; bmkp-bmenu-barf-if-not-in-menu-list, bmkp-bmenu-get-marked-files, bmkp-bookmark-last-access-cp,
310   ;; bmkp-buffer-last-access-cp, bmkp-describe-bookmark, bmkp-describe-bookmark-internals,
311   ;; bmkp-file-alpha-cp, bmkp-get-buffer-name, bmkp-get-end-position, bmkp-get-tags, bmkp-gnus-cp,
312   ;; bmkp-handler-cp, bmkp-info-cp, bmkp-local-file-accessed-more-recently-cp,
313   ;; bmkp-local-file-size-cp, bmkp-local-file-type-cp, bmkp-local-file-updated-more-recently-cp,
314   ;; bmkp-marked-cp, bmkp-non-file-filename, bmkp-read-tags-completing, bmkp-region-alist-only,
315   ;; bmkp-region-bookmark-p, bmkp-sorted-alist, bmkp-sort-omit, bmkp-url-cp, bmkp-visited-more-cp
316 (eval-when-compile (require 'hexrgb nil t)) ;; (no error if not found):
317   ;; hexrgb-color-name-to-hex, hexrgb-defined-colors, hexrgb-defined-colors-alist, hexrgb-hex-to-hsv,
318   ;; hexrgb-hex-to-rgb, hexrgb-read-color, hexrgb-(red|green|blue|hue|saturation|value),
319   ;; hexrgb-rgb-hex-string-p, hexrgb-rgb-to-hsv, hexrgb-value
320 (eval-when-compile (require 'highlight nil t)) ;; (no error if not found):
321   ;; hlt-act-on-any-face-flag, hlt-hide-default-face, hlt-highlight-faces-in-buffer,
322   ;; hlt-region-or-buffer-limits, hlt-show-default-face
323 (eval-when-compile
324  (or (condition-case nil
325          (load-library "icicles-mac")   ; Use load-library to ensure latest .elc.
326        (error nil))
327      (require 'icicles-mac)))           ; Require, so can load separately if not on `load-path'.
328   ;; icicle-bind-file-candidate-keys, icicle-define-command, icicle-define-file-command,
329   ;; icicle-file-bindings, icicle-maybe-byte-compile-after-load, icicle-unbind-file-candidate-keys
330 (require 'icicles-mcmd)
331   ;; icicle-search-define-replacement
332 (require 'icicles-opt)                  ; (This is required anyway by `icicles-var.el'.)
333   ;; icicle-alternative-sort-comparer, icicle-buffer-extras, icicle-buffer-ignore-space-prefix-flag,
334   ;; icicle-buffer-match-regexp, icicle-buffer-no-match-regexp, icicle-buffer-predicate,
335   ;; icicle-buffer-require-match-flag, icicle-buffer-sort, icicle-complete-keys-self-insert-ranges,
336   ;; icicle-ignore-space-prefix-flag, icicle-key-descriptions-use-<>-flag, icicle-recenter,
337   ;; icicle-require-match-flag, icicle-saved-completion-sets,
338   ;; icicle-search-cleanup-flag, icicle-search-highlight-all-current-flag,
339   ;; icicle-search-highlight-threshold, icicle-search-hook, icicle-sort-comparer,
340   ;; icicle-transform-function
341 (require 'icicles-var)                  ; (This is required anyway by `icicles-fn.el'.)
342   ;; icicle-candidate-action-fn, icicle-candidate-entry-fn, icicle-candidate-nb,
343   ;; icicle-candidates-alist, icicle-char-property-value-history, icicle-complete-keys-alist,
344   ;; icicle-completion-candidates, icicle-current-input, icicle-extra-candidates,
345   ;; icicle-get-alist-candidate-function, icicle-must-match-regexp, icicle-must-not-match-regexp,
346   ;; icicle-must-pass-predicate, icicle-saved-completion-candidates, icicle-search-command,
347   ;; icicle-search-current-overlay, icicle-search-final-choice, icicle-search-overlays,
348   ;; icicle-search-refined-overlays
349 (require 'icicles-fn)                   ; (This is required anyway by `icicles-mcmd.el'.)
350   ;; icicle-candidate-short-help, icicle-completing-read-history,
351   ;; icicle-highlight-lighter, icicle-insert-cand-in-minibuffer, icicle-kill-a-buffer
352 (require 'icicles-cmd1)
353   ;; custom-variable-p, icicle-bookmark-cleanup,
354   ;; icicle-bookmark-cleanup-on-quit, icicle-bookmark-cmd, icicle-bookmark-help-string,
355   ;; icicle-bookmark-history, icicle-bookmark-propertize-candidate, icicle-buffer-list,
356   ;; icicle-explore, icicle-face-list, icicle-file-list, icicle-make-frame-alist,
357   ;; icicle-select-bookmarked-region
358
359
360
361 ;; Byte-compiling this file, you will likely get some byte-compiler warning messages.
362 ;; These are probably benign - ignore them.  Icicles is designed to work with multiple
363 ;; versions of Emacs, and that fact provokes compiler warnings.  If you get byte-compiler
364 ;; errors (not warnings), then please report a bug, using `M-x icicle-send-bug-report'.
365
366 ;;; Some defvars to quiet byte-compiler a bit:
367
368 (defvar anything-sources)               ; In `anything.el'
369 (defvar anything-candidate-cache)       ; In `anything.el'
370 (defvar anything-idle-delay)            ; In `anything.el'
371 (defvar apropos-do-all)                 ; In `apropos.el'
372 (defvar bmkp-non-file-filename)         ; In `bookmark+-1.el'
373 (defvar bmkp-sorted-alist)              ; In `bookmark+-1.el'
374 (defvar hlt-act-on-any-face-flag)       ; In `highlight.el'
375 (defvar icicle-complete-keys-self-insert-ranges) ; In `icicles-var.el' (Emacs 22+)
376 (defvar icicle-search-ecm)              ; In `icicle-search'
377 (defvar icicle-track-pt)                ; In `icicle-insert-thesaurus-entry'
378 (defvar replace-count)                  ; In `replace.el'.
379
380 ;; (< emacs-major-version 21)
381 (defvar tooltip-mode)                   ; In `tooltip.el'
382
383 ;; (< emacs-major-version 22)
384 (defvar compilation-current-error)
385 (defvar cookie-cache)
386 (defvar Info-menu-entry-name-re)        ; In `info.el'
387 (defvar Info-read-node-completion-table) ; In `info.el'
388 (defvar palette-current-color)          ; In `palette.el'
389 (defvar palette-last-color)             ; In `palette.el'
390 (defvar palette-mode-map)               ; In `palette.el'
391 (defvar palette-popup-map)              ; In `palette.el'
392 (defvar read-file-name-completion-ignore-case) ; In `minibuffer.el'
393 (defvar synonyms-obarray)               ; In `synonyms.el'
394 (defvar tags-case-fold-search)          ; In `etags.el'
395 (defvar yow-after-load-message)
396 (defvar yow-file)
397 (defvar yow-load-message)
398
399 ;; (> emacs-major-version 21)
400 (defvar Info-saved-nodes)               ; In `info+.el'
401
402 ;; (< emacs-major-version 23)
403 (defvar read-buffer-completion-ignore-case)
404
405 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
406  
407 ;;(@* "Icicles Top-Level Commands, Part 2")
408 ;;; Icicles Top-Level Commands, Part 2 .   .   .   .   .   .   .   .   .
409
410
411 (defvar icicle-orig-font nil
412   "Font of selected frame, before command.")
413
414 (defvar icicle-orig-frame nil
415   "Selected frame, before command.")
416
417 (defvar icicle-orig-menu-bar nil
418   "`menu-bar-lines' of selected frame, before command.")
419
420 (defvar icicle-orig-pixelsize nil
421   "Size of font of selected frame in pixels, before command.")
422
423 (defvar icicle-orig-pointsize nil
424   "Size of font of selected frame in points, before command.")
425
426 ;;;###autoload (autoload 'icicle-font "icicles-cmd2.el")
427 (icicle-define-command icicle-font      ; Command name
428   "Change font of current frame."       ; Doc string
429   (lambda (font) (modify-frame-parameters icicle-orig-frame (list (cons 'font font)))) ; Action fn
430   "Font: "                              ; `completing-read' args
431   (let ((fonts  ())
432         fws)
433     (dolist (ft  (x-list-fonts "*")  fonts) ; Just avoiding two traversals, one to remove nil elts.
434       (when (setq fws  (icicle-font-w-orig-size ft)) (push fws fonts)))) ; Ignore nil entries.
435   nil t nil (if (boundp 'font-name-history) 'font-name-history 'icicle-font-name-history) nil nil
436   ((icicle-orig-frame      (selected-frame)) ; Bindings
437    (icicle-orig-font       (frame-parameter nil 'font))
438    (icicle-orig-pixelsize  (aref (x-decompose-font-name icicle-orig-font)
439                                  xlfd-regexp-pixelsize-subnum))
440    (icicle-orig-pointsize  (aref (x-decompose-font-name icicle-orig-font)
441                                  xlfd-regexp-pointsize-subnum))
442    (icicle-orig-menu-bar   (assq 'menu-bar-lines (frame-parameters icicle-orig-frame))))
443   ;; First code - remove menu-bar, to avoid Emacs bug that resizes frame.
444   (modify-frame-parameters icicle-orig-frame (list '(menu-bar-lines . 0)))
445   (modify-frame-parameters icicle-orig-frame ; Undo code.
446                            (list (cons 'font icicle-orig-font) icicle-orig-menu-bar))
447   (modify-frame-parameters icicle-orig-frame (list icicle-orig-menu-bar))) ; Last code.
448
449 ;; Free var here: `icicle-orig-pixelsize' is bound in `icicle-font'.
450 (defun icicle-font-w-orig-size (font)
451   "Return a font like FONT, but with pixel size `icicle-orig-pixelsize'.
452 Return nil if `x-decompose-font-name' returns nil for FONT.
453 `icicle-orig-pixelsize' is the original pixel size for `icicle-font'."
454   (let ((xlfd-fields  (x-decompose-font-name font)))
455     (if (not xlfd-fields)               ; Can't handle such font names - return nil.
456         nil
457       (aset xlfd-fields xlfd-regexp-pixelsize-subnum icicle-orig-pixelsize)
458       (aset xlfd-fields xlfd-regexp-pointsize-subnum icicle-orig-pointsize)
459       (let* ((sized-font   (x-compose-font-name xlfd-fields))
460              (font-info    (and (or (> icicle-help-in-mode-line-delay 0) ; Only if user will see it.
461                                     (and (boundp 'tooltip-mode) tooltip-mode))
462                                 (font-info sized-font)))
463              (iii          (if (< emacs-major-version 21) 3 2))
464              (help-string  (if font-info
465                                (format "width: %s, height: %s, offset: %s, compose: %s"
466                                        (aref font-info iii) (aref font-info (+ iii 1))
467                                        (aref font-info (+ iii 2)) (aref font-info (+ iii 3)))
468                              "Font is not yet loaded (used)")))
469         (icicle-candidate-short-help help-string sized-font)
470         (list sized-font)))))
471
472 (defvar icicle-named-colors ()
473   "Named colors.")
474
475 ;;;###autoload (autoload 'icicle-frame-bg "icicles-cmd2.el")
476 ;;;###autoload (autoload 'icicle-frame-fg "icicles-cmd2.el")
477 (eval-after-load "hexrgb"
478   '(progn
479
480     (when (and (fboundp 'read-color) (not (fboundp 'old-read-color))) ; Exists starting with Emacs 23.
481       (defalias 'old-read-color (symbol-function 'read-color))) ; Not used, but save it anyway.
482
483     ;; See also `hexrgb-read-color' in `hexrgb.el'.
484     (defun icicle-read-color (&optional arg prompt)
485       "Read a color name or hex RGB color value #RRRRGGGGBBBB.
486 A string value is returned.
487 Interactively, optional argument ARG is the prefix arg.
488 Optional argument PROMPT is the prompt to use (default \"Color: \").
489
490 In addition to standard color names and RGB (red, green, blue) hex
491 values, the following are also available as proxy color candidates,
492 provided `icicle-add-proxy-candidates-flag' is non-nil and library
493 `palette.el' or `eyedropper.el' is used.  In each case, the
494 corresponding color is used.
495
496 * `*copied foreground*'  - last copied foreground, if available
497 * `*copied background*'  - last copied background, if available
498 * `*mouse-2 foreground*' - foreground where you click `mouse-2'
499 * `*mouse-2 background*' - background where you click `mouse-2'
500 * `*point foreground*'   - foreground under the text cursor
501 * `*point background*'   - background under the text cursor
502
503 \(You can copy a color using eyedropper commands such as
504 `eyedrop-pick-foreground-at-mouse'.)
505
506 In addition, the names of user options (variables) whose custom type
507 is `color' are also proxy candidates, but with `'' as a prefix and
508 suffix.  So, for example, option `icicle-region-background' appears as
509 proxy color candidate `'icicle-region-background''.
510
511 As always, you can toggle the use of proxy candidates using `\\<minibuffer-local-completion-map>\
512 \\[icicle-toggle-proxy-candidates]' in
513 the minibuffer.
514
515 With plain `C-u', use `hexrgb-read-color', which lets you complete a
516 color name or input any valid RGB hex value (without completion).
517
518 With no prefix arg, return a string with both the color name and the
519 RGB value, separated by `icicle-list-nth-parts-join-string'.
520
521 With a numeric prefix arg of 0 or 1, return the color name.  With any
522 other numeric prefix arg, return the RGB value.
523
524 In the plain `C-u' case, your input is checked to ensure that it
525 represents a valid color.
526
527 In all other cases:
528
529 - You can complete your input against the color name, the RGB value,
530   or both.
531
532 - If you enter input without completing or cycling, the input is not
533   checked: whatever is entered is returned as the string value.
534
535 From Emacs Lisp, ARG controls what is returned.  If ARG is nil,
536 `icicle-list-use-nth-parts' can also be used to control the behavior.
537
538 Note: Duplicate color names are removed by downcasing and removing
539 whitespace.  For example, \"AliceBlue\" and \"alice blue\" are both
540 treated as \"aliceblue\".  Otherwise, candidates with different names
541 but the same RGB values are not considered duplicates, so, for
542 example, input can match either \"darkred\" or \"red4\", which both
543 have RGB #8b8b00000000.  You can toggle duplicate removal at any time
544 using `C-$'.
545
546 During completion, candidate help (e.g. `C-M-RET') shows you the RGB
547 and HSV (hue, saturation, value) color components.
548
549 This command is intended only for use in Icicle mode (but it can be
550 used with `C-u', with Icicle mode turned off)."
551       (interactive "P")
552       (unless (featurep 'hexrgb) (error "`icicle-read-color' requires library `hexrgb.el'"))
553       (let (color)
554         (if (consp arg)                 ; Plain `C-u': complete against color name only,
555             (setq color  (hexrgb-read-color t)) ; and be able to input any valid RGB string.
556
557           ;; Complete against name+RGB pairs, but user can enter invalid value without completing.
558           (let ((icicle-list-use-nth-parts
559                  (or (and arg (if (< arg 2) '(1) '(2))) ; 1 or 2, by program or via `C-1' or `C-2'.
560                      icicle-list-use-nth-parts ; Bound externally by program.
561                      '(1 2)))           ; Both parts, by default.
562                 (mouse-pseudo-color-p  nil)
563
564                 icicle-candidate-help-fn           completion-ignore-case
565                 icicle-transform-function          icicle-sort-orders-alist
566                 icicle-list-nth-parts-join-string  icicle-list-join-string
567                 ;; $$$$$$ icicle-list-end-string
568                 icicle-proxy-candidate-regexp      icicle-named-colors
569                 icicle-proxy-candidates)
570             ;; Copy the prompt string because `icicle-color-completion-setup' puts a text prop on it.
571             ;; Use `icicle-prompt' from now on, since that's what `icicle-color-completion-setup'
572             ;; sets up.
573             (setq icicle-prompt  (copy-sequence (or prompt "Color: ")))
574             (icicle-color-completion-setup)
575             (setq icicle-proxy-candidates
576                   (append icicle-proxy-candidates
577                           (mapcar       ; Convert multi-completions to strings.
578                            ;; $$$$$$ #'(lambda (entry)
579                            ;;           (concat (mapconcat #'identity (car entry)
580                            ;;                              icicle-list-join-string)
581                            ;;                   icicle-list-end-string)) ; $$$$$$
582                            #'(lambda (entry) (mapconcat #'identity (car entry)
583                                                         icicle-list-join-string))
584                            '((("*mouse-2 foreground*")) (("*mouse-2 background*")))))
585                   color  (icicle-transform-multi-completion
586                           (let ((icicle-orig-window  (selected-window))
587                                 (icicle-candidate-alt-action-fn
588                                  (or icicle-candidate-alt-action-fn
589                                      (icicle-alt-act-fn-for-type "color")))
590                                 (icicle-all-candidates-list-alt-action-fn
591                                  (or icicle-all-candidates-list-alt-action-fn
592                                      (icicle-alt-act-fn-for-type "color"))))
593                             (completing-read icicle-prompt icicle-named-colors))))
594             (when (fboundp 'eyedrop-foreground-at-point)
595               (cond ((string-match "^\*mouse-2 foreground\*" color)
596                      (setq color  (prog1 (eyedrop-foreground-at-mouse
597                                           (read-event
598                                            "Click `mouse-2' anywhere to choose foreground color"))
599                                     (read-event)) ; Discard mouse up event.
600                            mouse-pseudo-color-p  t))
601                     ((string-match "^\*mouse-2 background\*" color)
602                      (setq color  (prog1 (eyedrop-background-at-mouse
603                                           (read-event
604                                            "Click `mouse-2' anywhere to choose background color"))
605                                     (read-event)) ; Discard mouse up event.
606                            mouse-pseudo-color-p  t))))
607             (when mouse-pseudo-color-p
608               (let ((icicle-list-nth-parts-join-string  ": ")
609                     (icicle-list-join-string            ": ")
610                     ;; $$$$$$ (icicle-list-end-string             "")
611                     (icicle-list-use-nth-parts
612                      (or (and arg
613                               (if (< arg 2) '(1) '(2))) ; 1 or 2, by program or via `C-1' or `C-2'.
614                          icicle-list-use-nth-parts ; Bound externally by program.
615                          '(1 2))))      ; Both parts, by default.
616                 (setq color  (icicle-transform-multi-completion
617                               (concat color ": " (hexrgb-color-name-to-hex color))))))))
618         (when (interactive-p) (message "Color: `%s'" color))
619         color))
620
621     (icicle-maybe-byte-compile-after-load icicle-read-color)
622
623
624     (icicle-define-command icicle-frame-bg ; Command name
625       "Change background of current frame.
626 Read color name or hex RGB color value #RRRRGGGGBBBB with completion.
627 In addition to standard color names and RGB (red, green, blue) hex
628 values, the following are also available as proxy color candidates,
629 provided `icicle-add-proxy-candidates-flag' is non-nil and library
630 `palette.el' or `eyedropper.el' is used.  In each case, the
631 corresponding color is used.
632
633 * `*copied foreground*'  - last copied foreground, if available
634 * `*copied background*'  - last copied background, if available
635 * `*point foreground*'   - foreground under the text cursor
636 * `*point background*'   - background under the text cursor
637
638 \(You can copy a color using eyedropper commands such as
639 `eyedrop-pick-foreground-at-mouse'.)
640
641 In addition, the names of user options (variables) whose custom type
642 is `color' are also proxy candidates, but with `'' as a prefix and
643 suffix.  So, for example, option `icicle-region-background' appears as
644 proxy color candidate `'icicle-region-background''.
645
646 As always, you can toggle the use of proxy candidates using `\\<minibuffer-local-completion-map>\
647 \\[icicle-toggle-proxy-candidates]' in
648 the minibuffer.
649
650 You can complete your input against the color name, the RGB value, or
651 both.
652
653 Note: Duplicate color names are removed by downcasing and removing
654 whitespace.  For example, \"AliceBlue\" and \"alice blue\" are both
655 treated as \"aliceblue\".  Otherwise, candidates with different names
656 but the same RGB values are not considered duplicates, so, for
657 example, input can match either \"darkred\" or \"red4\", which both
658 have RGB #8b8b00000000.  You can toggle duplicate removal at any time
659 using `C-$'.
660
661 During completion, candidate help (e.g. `C-M-RET') shows you the RGB
662 and HSV (hue, saturation, value) color components.
663
664 This command is intended only for use in Icicle mode." ; Doc string
665       (lambda (color)                   ; Action function
666         (modify-frame-parameters
667          icicle-orig-frame (list (cons 'background-color (icicle-transform-multi-completion color)))))
668       icicle-prompt icicle-named-colors nil t nil ; `completing-read' args
669       (if (boundp 'color-history) 'color-history 'icicle-color-history) nil nil
670       ((icicle-orig-frame                  (selected-frame)) ; Bindings
671        (orig-bg                            (frame-parameter nil 'background-color))
672        (icicle-prompt                      "Background color: ")
673        (icicle-list-use-nth-parts          '(2)) ; Use RGB part.
674        (icicle-candidate-alt-action-fn
675         (or icicle-candidate-alt-action-fn (icicle-alt-act-fn-for-type "color")))
676        (icicle-all-candidates-list-alt-action-fn
677         (or icicle-all-candidates-list-alt-action-fn (icicle-alt-act-fn-for-type "color")))
678
679        icicle-candidate-help-fn     completion-ignore-case             icicle-transform-function
680        icicle-sort-orders-alist     icicle-list-nth-parts-join-string  icicle-list-join-string
681        ;; $$$$$$ icicle-list-end-string
682        icicle-proxy-candidate-regexp      icicle-named-colors          icicle-proxy-candidates)
683       (icicle-color-completion-setup)   ; First code - needs `hexrgb.el'
684       (modify-frame-parameters icicle-orig-frame (list (cons 'background-color orig-bg))) ; Undo code
685       nil)                              ; Last code
686
687     (icicle-maybe-byte-compile-after-load icicle-frame-bg)
688
689
690     (icicle-define-command icicle-frame-fg ; Command name
691       "Change foreground of current frame.
692 See `icicle-frame-bg' - but this is for foreground, not background." ; Doc string
693       (lambda (color)                   ; Action function
694         (modify-frame-parameters
695          icicle-orig-frame (list (cons 'foreground-color (icicle-transform-multi-completion color)))))
696       icicle-prompt icicle-named-colors nil t nil ; `completing-read' args
697       (if (boundp 'color-history) 'color-history 'icicle-color-history) nil nil
698       ((icicle-orig-frame                  (selected-frame)) ; Bindings
699        (orig-bg                            (frame-parameter nil 'foreground-color))
700        (icicle-prompt                      "Foreground color: ")
701        (icicle-list-use-nth-parts          '(2)) ; Use RGB part.
702        (icicle-candidate-alt-action-fn
703         (or icicle-candidate-alt-action-fn (icicle-alt-act-fn-for-type "color")))
704        (icicle-all-candidates-list-alt-action-fn
705         (or icicle-all-candidates-list-alt-action-fn (icicle-alt-act-fn-for-type "color")))
706
707        icicle-candidate-help-fn     completion-ignore-case             icicle-transform-function
708        icicle-sort-orders-alist     icicle-list-nth-parts-join-string  icicle-list-join-string
709        ;; $$$$$$ icicle-list-end-string
710        icicle-proxy-candidate-regexp      icicle-named-colors          icicle-proxy-candidates)
711       (icicle-color-completion-setup)   ; First code - needs `hexrgb.el'
712       (modify-frame-parameters icicle-orig-frame (list (cons 'foreground-color orig-bg))) ; Undo code
713       nil)                              ; Last code
714
715     (icicle-maybe-byte-compile-after-load icicle-frame-fg)
716
717
718     ;; Free vars here:
719     ;; `icicle-prompt', `icicle-candidate-help-fn', `completion-ignore-case',
720     ;; `icicle-transform-function', `icicle-sort-orders-alist', `icicle-list-nth-parts-join-string',
721     ;; `icicle-list-join-string', `icicle-proxy-candidate-regexp', `icicle-named-colors',
722     ;; `icicle-proxy-candidates'.
723     (defun icicle-color-completion-setup ()
724       "Set up for color-name/RGB-value completion (helper function).
725 Sets these variables, which are assumed to be already `let'-bound:
726   `icicle-prompt'
727   `icicle-candidate-help-fn'
728   `completion-ignore-case'
729   `icicle-transform-function'
730   `icicle-sort-orders-alist'
731   `icicle-list-nth-parts-join-string'
732   `icicle-list-join-string'
733   `icicle-proxy-candidate-regexp'
734   `icicle-named-colors'
735   `icicle-proxy-candidates'
736 Puts property `icicle-fancy-candidates' on string `icicle-prompt'."
737       (if (< emacs-major-version 22)
738           (require 'eyedropper nil t)
739         (or (require 'palette nil t) (require 'eyedropper nil t)))
740       (put-text-property 0 1 'icicle-fancy-candidates t icicle-prompt)
741       (icicle-highlight-lighter)
742       (setq icicle-candidate-help-fn           'icicle-color-help
743             completion-ignore-case             t
744             icicle-sort-orders-alist
745             '(("by color name" . icicle-part-1-lessp)
746               ("by color hue"  . (lambda (s1 s2) (not (icicle-color-hue-lessp s1 s2))))
747               ("by color purity (saturation)"
748                . (lambda (s1 s2) (not (icicle-color-saturation-lessp s1 s2))))
749               ("by color brightness (value)"
750                . (lambda (s1 s2) (not (icicle-color-value-lessp s1 s2))))
751               ("by color hsv"       . (lambda (s1 s2) (not (icicle-color-hsv-lessp s1 s2))))
752               ("by hsv distance"    . (lambda (s1 s2) (icicle-color-distance-hsv-lessp s1 s2)))
753               ("by amount of red"   . (lambda (s1 s2) (not (icicle-color-red-lessp s1 s2))))
754               ("by amount of green" . (lambda (s1 s2) (not (icicle-color-green-lessp s1 s2))))
755               ("by amount of blue"  . (lambda (s1 s2) (not (icicle-color-blue-lessp s1 s2))))
756               ("by color rgb"       . (lambda (s1 s2) (not (icicle-color-rgb-lessp s1 s2))))
757               ("by rgb distance"    . (lambda (s1 s2) (icicle-color-distance-rgb-lessp s1 s2)))
758               ("turned OFF"))
759             ;; Make the two `*-join-string' variables the same, so past inputs are recognized.
760             ;; Do not use " " as the value, because color names such as "white smoke" would be
761             ;; split, and "smoke" would not be recognized as a color name when trying to list
762             ;; candidates in `*Completions*'.
763             icicle-list-nth-parts-join-string  ": "
764             icicle-list-join-string            ": "
765             ;; $$$$$$ icicle-list-end-string             ""
766             icicle-proxy-candidate-regexp      "^[*'].+[*']"
767
768             icicle-named-colors                (mapcar #'icicle-make-color-candidate
769                                                        (hexrgb-defined-colors))
770             icicle-proxy-candidates
771             (mapcar                     ; Convert multi-completions to strings.
772              (lambda (entry)
773                ;; $$$$$$ (concat (mapconcat #'identity (car entry) icicle-list-join-string)
774                ;;                icicle-list-end-string) ; $$$$$$
775                (mapconcat #'identity (car entry) icicle-list-join-string))
776              (append
777               (and (fboundp 'eyedrop-foreground-at-point)
778                    (append
779                     (and eyedrop-picked-foreground ; Multi-completions.
780                          `(,(icicle-make-color-candidate
781                              "*copied foreground*" (downcase (hexrgb-color-name-to-hex
782                                                               eyedrop-picked-foreground)))))
783                     (and eyedrop-picked-background
784                          `(,(icicle-make-color-candidate
785                              "*copied background*" (downcase (hexrgb-color-name-to-hex
786                                                               eyedrop-picked-background)))))
787                     `(,(icicle-make-color-candidate
788                         "*point foreground*" (downcase (hexrgb-color-name-to-hex
789                                                         (eyedrop-foreground-at-point))))
790                       ,(icicle-make-color-candidate
791                         "*point background*" (downcase (hexrgb-color-name-to-hex
792                                                         (eyedrop-background-at-point)))))))
793               (let ((ipc  ()))
794                 (mapatoms
795                  (lambda (cand)
796                    (when (and (user-variable-p cand)
797                               (condition-case nil (icicle-var-is-of-type-p cand '(color)) (error nil))
798                               ;; This should not be necessary, but type `color' isn't
799                               ;; enforced - it just means `string' (so far).
800                               (x-color-defined-p (symbol-value cand)))
801                      (push `,(icicle-make-color-candidate
802                               (concat "'" (symbol-name cand) "'")
803                               (downcase (hexrgb-color-name-to-hex (symbol-value cand))))
804                            ipc))))
805                 ipc)))))
806
807     (icicle-maybe-byte-compile-after-load icicle-color-completion-setup)
808
809
810     (defun icicle-color-help (color)
811       "Display help on COLOR."
812       (let ((icicle-list-use-nth-parts  '(1 2)))
813         (with-output-to-temp-buffer "*Help*"
814           (setq icicle-list-use-nth-parts  '(2)
815                 color                      (icicle-transform-multi-completion color))
816           (princ (format "Color: %s" color)) (terpri) (terpri)
817           (let* ((rgb  (hexrgb-hex-to-rgb color))
818                  (hsv  (apply #'hexrgb-rgb-to-hsv rgb)))
819             (princ "RGB:") (mapcar (lambda (component) (princ (format "  %.18f" component))) rgb)
820             (terpri) (terpri)
821             (princ "HSV:") (mapcar (lambda (component) (princ (format "  %.18f" component))) hsv)))))
822
823     (icicle-maybe-byte-compile-after-load icicle-color-help)
824
825
826     (defun icicle-make-color-candidate (color-name &optional hex-rgb)
827       "Return multi-completion candidate of COLOR-NAME and its hex RGB string.
828 If `icicle-WYSIWYG-Completions-flag' is non-nil, then the hex RGB
829 string has the color as its background text property.
830 Optional arg HEX-RGB is the hex RGB string.
831 If nil, then COLOR-NAME is used to determine the hex RGB string."
832       (let* ((rgb-string  (or hex-rgb (hexrgb-color-name-to-hex color-name)))
833              (value       (hexrgb-value rgb-string)))
834         (when icicle-WYSIWYG-Completions-flag
835           (put-text-property 0 (length rgb-string) 'face
836                              (list (cons 'foreground-color (if (< value 0.6) "White" "Black"))
837                                    (cons 'background-color rgb-string))
838                              rgb-string))
839         (when (or (> icicle-help-in-mode-line-delay 0) ; Construct help only if user will see it.
840                   (and (boundp 'tooltip-mode) tooltip-mode))
841           (let* ((rgb   (hexrgb-hex-to-rgb rgb-string))
842                  (hsv   (apply #'hexrgb-rgb-to-hsv rgb))
843                  (help  (format "RGB: %.6f, %.6f, %.6f;  HSV: %.6f, %.6f, %.6f"
844                                 (nth 0 rgb) (nth 1 rgb) (nth 2 rgb)
845                                 (nth 0 hsv) (nth 1 hsv) (nth 2 hsv))))
846             (icicle-candidate-short-help help color-name)
847             (icicle-candidate-short-help help rgb-string)))
848         (list (list color-name rgb-string))))
849
850     (icicle-maybe-byte-compile-after-load icicle-make-color-candidate)
851
852
853     ;; This predicate is used for color completion.
854     (defun icicle-color-red-lessp (s1 s2)
855       "Non-nil means the RGB in S1 has less red than in S2.
856 The strings are assumed to have at least two parts, with the parts
857 separated by `icicle-list-join-string' The RGB values are assumed to
858 be the second parts of the strings, and they are assumed to start with
859 `#'."
860       (let ((rgb1  (elt (split-string s1 icicle-list-join-string) 1))
861             (rgb2  (elt (split-string s2 icicle-list-join-string) 1)))
862         (and rgb1 rgb2                  ; Just in case strings were not multipart.
863              (< (hexrgb-red rgb1) (hexrgb-red rgb2)))))
864
865     (icicle-maybe-byte-compile-after-load icicle-color-red-lessp)
866
867
868     ;; This predicate is used for color completion.
869     (defun icicle-color-green-lessp (s1 s2)
870       "Non-nil means the RGB in S1 has less green than in S2.
871 The strings are assumed to have at least two parts, with the parts
872 separated by `icicle-list-join-string' The RGB values are assumed to
873 be the second parts of the strings, and they are assumed to start with
874 `#'."
875       (let ((rgb1  (elt (split-string s1 icicle-list-join-string) 1))
876             (rgb2  (elt (split-string s2 icicle-list-join-string) 1)))
877         (and rgb1 rgb2                  ; Just in case strings were not multipart.
878              (< (hexrgb-green rgb1) (hexrgb-green rgb2)))))
879
880     (icicle-maybe-byte-compile-after-load icicle-color-green-lessp)
881
882
883     ;; This predicate is used for color completion.
884     (defun icicle-color-blue-lessp (s1 s2)
885       "Non-nil means the RGB in S1 has less blue than in S2.
886 The strings are assumed to have at least two parts, with the parts
887 separated by `icicle-list-join-string' The RGB values are assumed to
888 be the second parts of the strings, and they are assumed to start with
889 `#'."
890       (let ((rgb1  (elt (split-string s1 icicle-list-join-string) 1))
891             (rgb2  (elt (split-string s2 icicle-list-join-string) 1)))
892         (and rgb1 rgb2                  ; Just in case strings were not multipart.
893              (< (hexrgb-blue rgb1) (hexrgb-blue rgb2)))))
894
895     (icicle-maybe-byte-compile-after-load icicle-color-blue-lessp)
896
897
898     ;; This predicate is used for color completion.
899     (defun icicle-color-distance-rgb-lessp (s1 s2)
900       "Return non-nil if color S1 is RGB-closer than S2 to the base color.
901 S1 and S2 are color names (strings).
902
903 The base color name is the cdr of option `list-colors-sort', whose car
904 must be `rgb-dist'.  If the option value is not already a cons with
905 car `rgb-dist' then it is made so: you are prompted for the base color
906 name to use."
907       (let* ((base-color  (if (and (boundp 'list-colors-sort) ; Emacs 23+
908                                    (consp list-colors-sort) (eq 'rgb-dist (car list-colors-sort)))
909                               (cdr list-colors-sort) ; `list-colors-sort' is free here.
910                             (cdr (setq list-colors-sort
911                                        (cons 'rgb-dist
912                                              (let ((enable-recursive-minibuffers  t)
913                                                    (icicle-sort-comparer          nil))
914                                                (icicle-read-color 0 "With RGB close to color: ")))))))
915              (base-rgb    (hexrgb-hex-to-rgb (hexrgb-color-name-to-hex base-color)))
916              (base-red    (nth 0 base-rgb))
917              (base-green  (nth 1 base-rgb))
918              (base-blue   (nth 2 base-rgb))
919              (s1-rgb      (hexrgb-hex-to-rgb (elt (split-string s1 icicle-list-join-string) 1)))
920              (s2-rgb      (hexrgb-hex-to-rgb (elt (split-string s2 icicle-list-join-string) 1))))
921         (< (+ (expt (- (nth 0 s1-rgb) base-red) 2)
922               (expt (- (nth 1 s1-rgb) base-green) 2)
923               (expt (- (nth 2 s1-rgb) base-blue) 2))
924            (+ (expt (- (nth 0 s2-rgb) base-red) 2)
925               (expt (- (nth 1 s2-rgb) base-green) 2)
926               (expt (- (nth 2 s2-rgb) base-blue) 2)))))
927
928     (icicle-maybe-byte-compile-after-load icicle-color-distance-rgb-lessp)
929
930
931     ;; This predicate is used for color completion.
932     (defun icicle-color-hue-lessp (s1 s2)
933       "Non-nil means the RGB hue in S1 is less than that in S2.
934 The strings are assumed to have at least two parts, with the parts
935 separated by `icicle-list-join-string' The RGB values are assumed to
936 be the second parts of the strings, and they are assumed to start with
937 `#'."
938       (let ((rgb1  (elt (split-string s1 icicle-list-join-string) 1))
939             (rgb2  (elt (split-string s2 icicle-list-join-string) 1)))
940         (and rgb1 rgb2                  ; Just in case strings were not multipart.
941              (< (hexrgb-hue rgb1) (hexrgb-hue rgb2)))))
942
943     (icicle-maybe-byte-compile-after-load icicle-color-hue-lessp)
944
945
946     ;; This predicate is used for color completion.
947     (defun icicle-color-saturation-lessp (s1 s2)
948       "Non-nil means the RGB in S1 is less saturated than in S2.
949 The strings are assumed to have at least two parts, with the parts
950 separated by `icicle-list-join-string' The RGB values are assumed to
951 be the second parts of the strings, and they are assumed to start with
952 `#'."
953       (let ((rgb1  (elt (split-string s1 icicle-list-join-string) 1))
954             (rgb2  (elt (split-string s2 icicle-list-join-string) 1)))
955         (and rgb1 rgb2                  ; Just in case strings were not multipart.
956              (< (hexrgb-saturation rgb1) (hexrgb-saturation rgb2)))))
957
958     (icicle-maybe-byte-compile-after-load icicle-color-saturation-lessp)
959
960
961     ;; This predicate is used for color completion.
962     (defun icicle-color-value-lessp (s1 s2)
963       "Non-nil means the RGB value in S1 is darker than that in S2.
964 The strings are assumed to have at least two parts, with the parts
965 separated by `icicle-list-join-string' The RGB values are assumed to
966 be the second parts of the strings, and they are assumed to start with
967 `#'."
968       (let ((rgb1  (elt (split-string s1 icicle-list-join-string) 1))
969             (rgb2  (elt (split-string s2 icicle-list-join-string) 1)))
970         (and rgb1 rgb2                  ; Just in case strings were not multipart.
971              (< (hexrgb-value rgb1) (hexrgb-value rgb2)))))
972
973     (icicle-maybe-byte-compile-after-load icicle-color-value-lessp)
974
975
976     ;; This predicate is used for color completion.
977     (defun icicle-color-hsv-lessp (s1 s2)
978       "Non-nil means the HSV components of S1 are less than those of S2.
979 Specifically, the hues are compared first, then if hues are equal then
980 saturations are compared, then if those are also equal values are
981 compared.
982 The strings are assumed to have at least two parts, with the parts
983 separated by `icicle-list-join-string' The second parts of the strings
984 are RGB triplets that start with `#'."
985       (let* ((rgb1  (elt (split-string s1 icicle-list-join-string) 1))
986              (hsv1  (and rgb1 (hexrgb-hex-to-hsv rgb1)))
987              (rgb2  (elt (split-string s2 icicle-list-join-string) 1))
988              (hsv2  (and rgb2 (hexrgb-hex-to-hsv rgb2))))
989         (and hsv1 hsv2                  ; Just in case strings were not multipart.
990              (or (< (nth 0 hsv1) (nth 0 hsv2))
991                  (and (= (nth 0 hsv1) (nth 0 hsv2))
992                       (< (nth 1 hsv1) (nth 1 hsv2)))
993                  (and (= (nth 0 hsv1) (nth 0 hsv2))
994                       (= (nth 1 hsv1) (nth 1 hsv2))
995                       (< (nth 2 hsv1) (nth 2 hsv2)))))))
996
997     (icicle-maybe-byte-compile-after-load icicle-color-hsv-lessp)
998
999
1000     ;; This predicate is used for color completion.
1001     (defun icicle-color-distance-hsv-lessp (s1 s2)
1002       "Return non-nil if color S1 is HSV-closer than S2 to the base color.
1003 S1 and S2 are color names (strings).
1004
1005 The base color name is the cdr of option `list-colors-sort', whose car
1006 must be `hsv-dist'.  If the option value is not already a cons with
1007 car `hsv-dist' then it is made so: you are prompted for the base color
1008 name to use."
1009       (let* ((base-color  (if (and (boundp 'list-colors-sort) ; Emacs 23+
1010                                    (consp list-colors-sort) (eq 'hsv-dist (car list-colors-sort)))
1011                               (cdr list-colors-sort) ; `list-colors-sort' is free here.
1012                             (cdr (setq list-colors-sort
1013                                        (cons 'hsv-dist
1014                                              (let ((enable-recursive-minibuffers  t)
1015                                                    (icicle-sort-comparer          nil))
1016                                                (icicle-read-color 0 "With HSV close to color: ")))))))
1017              (base-hsv    (hexrgb-hex-to-hsv (hexrgb-color-name-to-hex base-color)))
1018              (base-hue    (nth 0 base-hsv))
1019              (base-sat    (nth 1 base-hsv))
1020              (base-val    (nth 2 base-hsv))
1021              (s1-hsv      (apply #'hexrgb-rgb-to-hsv
1022                                  (hexrgb-hex-to-rgb
1023                                   (elt (split-string s1 icicle-list-join-string) 1))))
1024              (s2-hsv      (apply #'hexrgb-rgb-to-hsv
1025                                  (hexrgb-hex-to-rgb
1026                                   (elt (split-string s2 icicle-list-join-string) 1)))))
1027         (< (+ (expt (- (nth 0 s1-hsv) base-hue) 2)
1028               (expt (- (nth 1 s1-hsv) base-sat) 2)
1029               (expt (- (nth 2 s1-hsv) base-val) 2))
1030            (+ (expt (- (nth 0 s2-hsv) base-hue) 2)
1031               (expt (- (nth 1 s2-hsv) base-sat) 2)
1032               (expt (- (nth 2 s2-hsv) base-val) 2)))))
1033     ))
1034
1035 (defvar icicle-info-buff nil
1036   "Info buffer before command was invoked.")
1037
1038 (defvar icicle-info-window nil
1039   "Info window before command was invoked.")
1040
1041 ;;;###autoload
1042 (defun icicle-Info-index ()
1043   "Like vanilla `Info-index', but you can use multi-command keys `C-RET', `C-up' etc."
1044   (interactive)
1045   (when (and (boundp 'Info-current-file) (equal Info-current-file "dir"))
1046     (error "The Info directory node has no index; use `m' to select a manual"))
1047   (let ((icicle-info-buff            (current-buffer))
1048         (icicle-info-window          (selected-window))
1049         (icicle-candidate-action-fn  'icicle-Info-index-action)
1050         (C-x-m                       (lookup-key minibuffer-local-completion-map "\C-xm")))
1051     (when (and (require 'bookmark+ nil t) (fboundp 'icicle-bookmark-info-other-window))
1052       (define-key minibuffer-local-completion-map "\C-xm" 'icicle-bookmark-info-other-window))
1053     (unwind-protect
1054          (call-interactively (if (> emacs-major-version 21) 'old-Info-index 'icicle-Info-index-20))
1055       (define-key minibuffer-local-completion-map "\C-xm" C-x-m))))
1056
1057 ;; Thx to Tamas Patrovics for this Emacs 20 version.
1058 ;;;###autoload
1059 (defun icicle-Info-index-20 ()
1060   "Like `Info-index', but you can use completion for the index topic."
1061   (interactive)
1062   (let* ((symb (or (and (fboundp 'symbol-nearest-point) ; Defined in `thingatpt+.el'.
1063                         (symbol-nearest-point))
1064                    (symbol-at-point)))
1065          (topic (and symb (symbol-name symb))))
1066     (old-Info-index "")
1067     (let ((pattern     "\\* +\\([^:]*\\):.")
1068           (candidates  ()))
1069       (goto-char (point-min))
1070       (while (re-search-forward pattern nil t) (push (list (match-string 1)) candidates))
1071       (old-Info-index (completing-read "Index topic: " candidates nil t nil nil topic)))))
1072
1073 ;; Free vars here: `icicle-info-buff' and `icicle-info-window' are bound in `icicle-Info-index'.
1074 (defun icicle-Info-index-action (topic)
1075   "Completion action function for `icicle-Info-index'."
1076   (let ((minibuf-win  (selected-window)))
1077     (set-buffer icicle-info-buff)
1078     (select-window icicle-info-window)
1079     (old-Info-index topic)
1080     (select-window minibuf-win)))
1081
1082 ;; Free vars here: `Info-menu-entry-name-re' is bound in `info.el'.
1083 (icicle-define-command icicle-Info-menu
1084   "Go to a menu node."                  ; Doc string
1085   (lambda (m) (icicle-Info-goto-node (cdr (funcall icicle-get-alist-candidate-function m)))) ; Action
1086   "Menu item: " icicle-candidates-alist ; `completing-read' args
1087   nil t nil nil (save-excursion
1088                   (goto-char (point-min))
1089                   (unless (search-forward "\n* menu:" nil t) (error "No menu in this node"))
1090                   (setq menu-eol  (point))
1091                   (and (< menu-eol opoint)
1092                        (save-excursion
1093                          (goto-char opoint) (end-of-line)
1094                          (and (re-search-backward (concat "\n\\* +\\("
1095                                                           (if (boundp 'Info-menu-entry-name-re)
1096                                                               Info-menu-entry-name-re
1097                                                             "[^:\t\n]*")
1098                                                           "\\):")
1099                                                   menu-eol t)
1100                               (match-string-no-properties 1)))))
1101   nil
1102   ((opoint                                 (point)) ; Bindings
1103    (completion-ignore-case                 t)
1104    (case-fold-search                       t)
1105    (icicle-sort-comparer                   nil)
1106    (icicle-whole-candidate-as-text-prop-p  t)
1107    (Info-complete-menu-buffer              (current-buffer))
1108    (icicle-candidates-alist                (mapcar #'(lambda (m) (cons m (Info-extract-menu-item m)))
1109                                                    (reverse
1110                                                     (all-completions "" 'Info-complete-menu-item))))
1111    menu-eol))
1112
1113 ;;;###autoload
1114 (defun icicle-Info-goto-node (nodename &optional arg)
1115   "Go to Info node named NODENAME.
1116 NODENAME has the form NODE or (FILE)NODE-IN-FILE, where:
1117  NODE names a node in the current Info file or one of its subfiles.
1118  FILE names an Info file containing node NODE-IN-FILE.
1119 Completion is available for node names in the current Info file.
1120
1121 With a prefix argument:
1122
1123  * Plain `C-u' means prepend the current Info file name (manual name)
1124    to each node name.  For example: `(emacs)Paragraphs' instead of
1125    just `Paragraphs'.
1126
1127  * A negative numeric prefix arg (e.g. `C--') means present completion
1128    candidates in book order, and limit the candidates to the current
1129    node and the rest of the book following it.  In this case, the
1130    first candidate is `..', which means go up.
1131
1132  * A negative numeric prefix arg (e.g. `C-1') means show the target
1133    node in a new Info buffer (not available prior to Emacs 21).
1134    (This applies only to the final completion choice, not to
1135    intermediate candidate actions using, e.g., `C-RET'.)
1136
1137 In Lisp code, if optional argument ARG is a string, then show the node
1138 in a new Info buffer named `*info-ARG*'.
1139
1140 With no prefix argument, or with a non-negative prefix arg, you can
1141 use `C-,' to choose how to sort completion candidates.  By default,
1142 they are sorted alphabetically.
1143
1144 Input-candidate completion and cycling are available.  While cycling,
1145 these keys with prefix `C-' are active:
1146
1147 `C-mouse-2', `C-RET' - Go to current completion candidate (node)
1148 `C-down'  - Go to next completion candidate
1149 `C-up'    - Go to previous completion candidate
1150 `C-next'  - Go to next apropos-completion candidate
1151 `C-prior' - Go to previous apropos-completion candidate
1152 `C-end'   - Go to next prefix-completion candidate
1153 `C-home'  - Go to previous prefix-completion candidate
1154
1155 Use `mouse-2', `RET', or `S-RET' to finally choose a candidate, or
1156 `C-g' to quit.
1157
1158 This is an Icicles command - see command `icicle-mode'."
1159   (interactive
1160    (let* ((icicle-info-buff                 (current-buffer))
1161           (icicle-info-window               (selected-window))
1162           (icicle-candidate-action-fn       'icicle-Info-goto-node-action)
1163           (icicle-Info-only-rest-of-book-p  (< (prefix-numeric-value current-prefix-arg) 0))
1164           (icicle-sort-orders-alist         (cons '("in book order" .  icicle-Info-book-order-p)
1165                                                   icicle-sort-orders-alist))
1166           (icicle-sort-comparer             (if icicle-Info-only-rest-of-book-p
1167                                                 #'icicle-Info-book-order-p
1168                                               icicle-sort-comparer)))
1169      (list (icicle-Info-read-node-name "Go to node: " (consp current-prefix-arg))
1170            current-prefix-arg)))
1171   (icicle-Info-goto-node-1 nodename arg))
1172
1173 (defun icicle-Info-goto-node-1 (nodename &optional arg)
1174   "Same as vanilla `Info-goto-node', but go up for `..' pseudo-node."
1175   (if (and (string= nodename "..") (Info-check-pointer "up"))
1176       (Info-up)
1177     (if (> emacs-major-version 20)
1178         (old-Info-goto-node nodename (and (not icicle-Info-only-rest-of-book-p) arg))
1179       (old-Info-goto-node nodename))))
1180
1181 (defun icicle-Info-read-node-name (prompt &optional include-file-p)
1182   "Read a node name, prompting with PROMPT.
1183 Non-nil INCLUDE-FILE-P means include current Info file in the name.
1184 You can use `C-x m' during completion to access Info bookmarks, if you
1185  use library `Bookmark+'."
1186   (let ((C-x-m  (lookup-key minibuffer-local-completion-map "\C-xm")))
1187     (when (and (require 'bookmark+ nil t) (fboundp 'icicle-bookmark-info-other-window))
1188       (define-key minibuffer-local-completion-map "\C-xm" 'icicle-bookmark-info-other-window))
1189     (unwind-protect
1190          (let* ((completion-ignore-case           t)
1191                 (Info-read-node-completion-table  (icicle-Info-build-node-completions include-file-p))
1192                 (nodename                         (completing-read prompt 'Info-read-node-name-1
1193                                                                    nil nil)))
1194            (if (equal nodename "") (icicle-Info-read-node-name prompt) nodename))
1195       (define-key minibuffer-local-completion-map "\C-xm" C-x-m))))
1196
1197 (defun icicle-Info-build-node-completions (&optional include-file-p)
1198   "Build completions list for Info nodes.
1199 This takes `icicle-Info-only-rest-of-book-p' into account.
1200 Non-nil INCLUDE-FILE-P means include current Info file in the name."
1201   (icicle-highlight-lighter)
1202   (if (or (not icicle-Info-only-rest-of-book-p) (string= Info-current-node "Top"))
1203       (icicle-Info-build-node-completions-1 include-file-p)
1204     (reverse (cons '("..")
1205                    (member (list Info-current-node)
1206                            (reverse (icicle-Info-build-node-completions-1 include-file-p)))))))
1207
1208 (defun icicle-Info-build-node-completions-1 (&optional include-file-p)
1209   "Helper function for `icicle-Info-build-node-completions'.
1210 Use `Info-build-node-completions' to build node list for completion.
1211 Non-nil INCLUDE-FILE-P means include current Info file in the name.
1212 Remove pseudo-node `*'.  (This just fixes a bug in Emacs 21 and 22.1.)"
1213   (let ((comps  (Info-build-node-completions)))
1214     (when (equal (car comps) '("*")) (setq comps  (cdr comps)))
1215     (if include-file-p
1216         (let ((file  (concat "(" (cond ((stringp Info-current-file)
1217                                         (replace-regexp-in-string
1218                                          "%" "%%" (file-name-nondirectory Info-current-file)))
1219                                        (Info-current-file (format "*%S*" Info-current-file))
1220                                        (t ""))
1221                              ")")))
1222           (mapcar #'(lambda (node) (cons (concat file (car node)) (cdr node))) comps))
1223       comps)))
1224
1225 ;; Free vars here:
1226 ;; `icicle-info-buff' and `icicle-info-window' are bound in `icicle-Info-goto-node'.
1227 ;; `Info-read-node-completion-table' is bound in `info.el'.
1228 (defun icicle-Info-goto-node-action (node)
1229   "Completion action function for `icicle-Info-goto-node'."
1230   (set-buffer icicle-info-buff)
1231   (select-window icicle-info-window)
1232   (icicle-Info-goto-node-1 node)
1233   (when icicle-Info-only-rest-of-book-p
1234     (setq Info-read-node-completion-table  (icicle-Info-build-node-completions)
1235           icicle-current-input             "")
1236     (icicle-complete-again-update)
1237     (if (and (string= Info-current-node "Top") Info-history)
1238         (let* ((hist  Info-history)
1239                (last  (car (cdr (car hist)))))
1240           (while (string= "Top" (car (cdr (car hist)))) (pop hist))
1241           (setq icicle-candidate-nb
1242                 (1- (length (reverse (member (list (car (cdr (car hist))))
1243                                              (icicle-Info-build-node-completions-1)))))))
1244       (setq icicle-candidate-nb  1))     ; Skip `..'.
1245
1246     ;; $$$$$$ Maybe factor this out. Same thing in several places.  However, here we don't do
1247     ;; `icicle-maybe-sort-and-strip-candidates' at beginning of first clause.
1248     (cond ((and icicle-completion-candidates (cdr icicle-completion-candidates)) ; > 1 left.
1249            (message "Displaying completion candidates...")
1250            (save-selected-window (icicle-display-candidates-in-Completions))
1251            (with-current-buffer "*Completions*"
1252              (goto-char (icicle-start-of-candidates-in-Completions))
1253              (icicle-move-to-next-completion
1254               (mod icicle-candidate-nb (length icicle-completion-candidates)))
1255              (set-window-point (get-buffer-window "*Completions*" 0) (point))
1256              (setq icicle-last-completion-candidate  (icicle-current-completion-in-Completions))
1257              (set-buffer-modified-p nil)))
1258           (icicle-completion-candidates ; Single candidate left
1259            (save-selected-window (icicle-remove-Completions-window))
1260            (let ((completion  (icicle-transform-multi-completion
1261                                (car icicle-completion-candidates))))
1262              (select-window (active-minibuffer-window))
1263              (with-current-buffer (window-buffer) ; Need if `*Completions*' redirected to minibuffer.
1264                (goto-char (icicle-minibuffer-prompt-end))
1265                (icicle-clear-minibuffer)
1266                (insert (if (and (icicle-file-name-input-p) insert-default-directory
1267                                 (or (not (member completion icicle-extra-candidates))
1268                                     icicle-extra-candidates-dir-insert-p))
1269                            (icicle-file-name-directory-w-default icicle-current-input)
1270                          "")
1271                        completion))))
1272           (t                            ; No candidates left
1273            (select-window (active-minibuffer-window))
1274            (with-current-buffer (window-buffer) ; Needed if `*Completions*' redirected to minibuffer.
1275              (goto-char (icicle-minibuffer-prompt-end))
1276              (icicle-clear-minibuffer)))))
1277   (select-window (active-minibuffer-window)))
1278
1279 (defun icicle-Info-book-order-p (s1 s2)
1280   "Non-nil if Info node S1 comes before node S2 in the book."
1281   t)        ; This just reverses the default order, which is reversed.
1282
1283 (when (> emacs-major-version 21)
1284   (defun icicle-Info-virtual-book (nodeset)
1285     "Open Info on a virtual book of saved Info nodes.
1286 You need library `info+.el' to use this command.
1287 With a prefix arg, you are prompted to choose a persistent saved
1288  completion set from `icicle-saved-completion-sets'.  The set you
1289  choose should be a set of saved Info node names.
1290 With no prefix arg, use `icicle-saved-completion-candidates', which
1291  should be a set of Info node names.  If that is empty, then use
1292  `Info-saved-nodes'.
1293 Non-interactively, argument NODESET is a list of Info node names."
1294     (interactive
1295      (progn (unless (and (require 'info+ nil t) (fboundp 'Info-virtual-book))
1296               (error "You need library `info+.el' for this command"))
1297             (list (if (not current-prefix-arg)
1298                       "Virtual Book"
1299                     (save-selected-window
1300                       (completing-read "Saved Info node set: " icicle-saved-completion-sets nil t nil
1301                                        'icicle-completion-set-history))))))
1302     (let ((nodes  (and (consp nodeset) nodeset))) ; (), if interactive - NODESET is a string then.
1303       (when (interactive-p)
1304         (if (not current-prefix-arg)
1305             (setq nodes  icicle-saved-completion-candidates)
1306           (let ((file-name  (cdr (assoc nodeset icicle-saved-completion-sets))))
1307             (unless (icicle-file-readable-p file-name)
1308               (error "Cannot read cache file `%s'" file-name))
1309             (let ((list-buf  (find-file-noselect file-name 'nowarn 'raw)))
1310               (unwind-protect
1311                    (condition-case icicle-Info-virtual-book
1312                        (when (listp (setq nodes  (read list-buf)))
1313                          (message "Set `%s' read from file `%s'" nodeset file-name))
1314                      (error (error "Bad cache file.  %s"
1315                                    (error-message-string icicle-Info-virtual-book))))
1316                 (kill-buffer list-buf))
1317               (unless (consp nodes) (error "Bad data in cache file `%s'" file-name))))))
1318       (unless nodes (setq nodes  Info-saved-nodes)) ; In `info+.el'.
1319       (unless (and nodes (stringp (car nodes))) (error "No saved Info nodes")) ; Minimal check.
1320       (unless (stringp nodeset) (setq nodeset "Virtual Book")) ; Non-interactive - NODESET is a list.
1321       (Info-virtual-book nodeset nodes))))
1322
1323 ;;;###autoload (autoload 'icicle-where-is "icicles-cmd2.el")
1324 (icicle-define-command icicle-where-is  ; Command name
1325   "Show keyboard/menu/mouse sequences that invoke specified command.
1326 This is a multi-command version of `where-is'.
1327
1328 With no prefix argument, only commands actually bound to keys are
1329 completion candidates.  With a prefix argument, all commands are
1330 candidates.  NOTE: This is a significant difference from vanilla
1331 `where-is', which shows all commands as candidates, even those that
1332 are not bound.
1333
1334 With a plain (non-numeric) prefix argument, `C-u', insert the message
1335 in the current buffer.  (This is the same for vanilla `where-is'.)
1336
1337 By default, Icicle mode remaps all key sequences that are normally
1338 bound to `where-is' to `icicle-where-is'.  If you do not want this
1339 remapping, then customize option `icicle-top-level-key-bindings'." ; Doc string
1340   (lambda (x) (let ((symb  (intern-soft x))) ; Action function
1341                 (where-is symb (and pref-arg (consp pref-arg)))))
1342   (if pref-arg "Where is command: " "Where is bound command: ")
1343   obarray nil t nil nil ; `completing-read' args
1344   (let ((fn  (or (and (fboundp 'symbol-nearest-point) (symbol-nearest-point))
1345                  (function-called-at-point))))
1346     (and fn (symbol-name fn)))
1347   t
1348   ((pref-arg  current-prefix-arg)       ; Bindings
1349    (icicle-must-pass-after-match-predicate
1350     (if pref-arg
1351         #'(lambda (c) (commandp (intern c)))
1352       #'(lambda (c)
1353           (setq c  (intern c))
1354           (with-current-buffer icicle-orig-buff
1355             (and (commandp c) (where-is-internal c overriding-local-map 'non-ascii))))))
1356    (icicle-candidate-help-fn
1357     #'(lambda (c)
1358         (with-current-buffer icicle-orig-buff
1359           (let* ((keys   (where-is-internal (intern-soft c) overriding-local-map))
1360                  (keys1  (mapconcat 'key-description keys ", ")))
1361             (message (if (string= "" keys1)
1362                          (format "`%s' is not on any key" c)
1363                        (format "`%s' is on `%s'" c keys1)))
1364             (sit-for 3)))))
1365    (icicle-candidate-alt-action-fn
1366     (or icicle-candidate-alt-action-fn (icicle-alt-act-fn-for-type "command")))
1367    (icicle-all-candidates-list-alt-action-fn
1368     (or icicle-all-candidates-list-alt-action-fn (icicle-alt-act-fn-for-type "command")))))
1369
1370 ;;;###autoload (autoload 'icicle-describe-option-of-type "icicles-cmd2.el")
1371 (icicle-define-command icicle-describe-option-of-type ; Bound to `C-h C-o'.  Command name
1372   "Describe a user option that was defined with a given `defcustom' type.
1373 Enter patterns for the OPTION name and TYPE definition in the
1374 minibuffer, separated by `icicle-list-join-string', which is \"^G^J\",
1375 by default.  (`^G' here means the Control-g character, input using
1376 `C-h C-g'.  Likewise, for `^J'.)
1377
1378 OPTION is a regexp that is matched against option names.
1379
1380 Depending on the prefix arg, TYPE is interpreted as either of these:
1381
1382  - a regexp to match against the option type
1383
1384  - a definition acceptable for `defcustom' :type, or its first symbol,
1385    for example, (choice (integer) (regexp)) or `choice'
1386
1387 In the second case, depending on the prefix arg, TYPE can be matched
1388 against the option type, or it can be matched against either the
1389 option type or one of its subtypes.
1390
1391 In the second case also, depending on the prefix arg, if TYPE does not
1392 match some option's type, that option might still be a candidate, if
1393 its current value satisfies TYPE.
1394
1395 In sum, the prefix arg determines the type-matching behavior, as
1396 follows:
1397
1398  - None:      OPTION is defined with TYPE or a subtype of TYPE.
1399               TYPE is a regexp.
1400
1401  - `C-u':     OPTION is defined with TYPE or a subtype of TYPE,
1402                 or its current value is compatible with TYPE.
1403               TYPE is a type definition or its first symbol.
1404
1405  - Negative:  OPTION is defined with TYPE (exact match).
1406               TYPE is a regexp.
1407
1408  - Positive:  OPTION is defined with TYPE,
1409                 or its current value is compatible with TYPE.
1410               TYPE is a type definition or its first symbol.
1411
1412  - Zero:      OPTION is defined with TYPE or a subtype of TYPE.
1413               TYPE is a type definition or its first symbol.
1414
1415  - `C-u C-u': OPTION is defined with TYPE (exact match).
1416               TYPE is a type definition or its first symbol.
1417
1418 You can change these prefix-arg key sequences by customizing option
1419 `icicle-option-type-prefix-arg-list'.  For example, if you tend to use
1420 the matching defined here for `C-u', you might want to make that the
1421 default behavior (no prefix arg).  You can assign any of the six
1422 behaviors to any of the prefix-arg keys.
1423
1424 If TYPE is nil, then *all* options that match OPTION are candidates.
1425
1426 Note that options defined in libraries that have not been loaded can
1427 be candidates, but their type will appear as nil, since it is not
1428 known before loading the option definition.
1429
1430 You can match your input against the option name or the type
1431 definition or both.  Use `C-M-j' (equivalent here to `C-q C-g C-j') to
1432 input the default separator.
1433
1434 For example, to match all Icicles options whose type matches `string'
1435 \(according to the prefix arg), use `S-TAB' with this input:
1436
1437 icicle.*^G
1438 string$
1439
1440 If you instead want all Icicles options whose type definition contains
1441 `string', as in (repeat string), then use this:
1442
1443 icicle.*^G
1444 \[^^G]*string
1445
1446 Here, `[^^G]' matches any character except ^G, which includes newline.
1447 If you use `.'  here instead of `[^^G]', then only the first lines of
1448 type definitions are searched for `string', because `.' matches any
1449 character except a newline.  (The first `^' in `[^^G]' is a circumflex
1450 character.  The second `^' is part of `^G', the printed representation
1451 of a Control-g character.)
1452
1453 Remember that you can use `\\<minibuffer-local-completion-map>\
1454 \\[icicle-toggle-incremental-completion] to toggle incremental completion." ; Doc string
1455   icicle-describe-opt-action            ; Action function
1456   prompt                                ; `completing-read' args
1457   'icicle-describe-opt-of-type-complete nil nil nil nil nil nil
1458   ((prompt                             "OPTION `C-M-j' TYPE: ") ; Bindings
1459    (icicle-candidate-properties-alist  '((1 (face icicle-candidate-part))))
1460    ;; Bind `icicle-apropos-complete-match-fn' to nil to prevent automatic input matching
1461    ;; in `icicle-unsorted-apropos-candidates' etc., because `icicle-describe-opt-of-type-complete'
1462    ;; does everything.
1463    (icicle-apropos-complete-match-fn   nil)
1464    (icicle-candidate-help-fn           'icicle-describe-opt-action)
1465    ;; $$$ (icicle-highlight-input-completion-failure nil)
1466    (icicle-pref-arg                    current-prefix-arg))
1467   (progn (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code
1468          (icicle-highlight-lighter)
1469          (message "Gathering user options and their types...")))
1470
1471 (defun icicle-describe-opt-action (opt+type)
1472   "Action function for `icicle-describe-option-of-type'."
1473   (let ((icicle-list-use-nth-parts  '(1)))
1474     (describe-variable (intern (icicle-transform-multi-completion opt+type)))))
1475
1476 ;; Free var here: `icicle-pref-arg' - it is bound in `icicle-describe-option-of-type'.
1477 (defun icicle-describe-opt-of-type-complete (strg pred completion-mode)
1478   "Completion function for `icicle-describe-option-of-type'.
1479 This is used as the value of `minibuffer-completion-table'."
1480   (setq strg  icicle-current-input)
1481   ;; Parse strg into its option part and its type part: OPS  and TPS.
1482   ;; Make raw alist of all options and their types: ((a . ta) (b . tb)...).
1483   (let* ((num-prefix  (prefix-numeric-value icicle-pref-arg))
1484          (mode        (cond ((not icicle-pref-arg) ; No prefix arg
1485                              (nth 4 icicle-option-type-prefix-arg-list))
1486                             ((and (consp icicle-pref-arg) (= 16 num-prefix)) ; C-u C-u
1487                              (nth 0 icicle-option-type-prefix-arg-list))
1488                             ((consp icicle-pref-arg) (nth 2 icicle-option-type-prefix-arg-list)) ; C-u
1489                             ((zerop num-prefix) (nth 1 icicle-option-type-prefix-arg-list)) ; C-0
1490                             ((wholenump num-prefix) ; C-9
1491                              (nth 3 icicle-option-type-prefix-arg-list))
1492                             (t (nth 5 icicle-option-type-prefix-arg-list)))) ; C--
1493          (ops         (let ((icicle-list-use-nth-parts  '(1)))
1494                         (icicle-transform-multi-completion strg)))
1495          (tps         (let ((icicle-list-use-nth-parts  '(2)))
1496                         (icicle-transform-multi-completion strg)))
1497          (tp          (and (not (string= "" tps))
1498                            ;; Use regexp if no prefix arg or negative; else use sexp.
1499                            (if (memq mode '(inherit-or-regexp direct-or-regexp)) tps (read tps))))
1500          (result      nil))
1501     (mapatoms
1502      #'(lambda (symb)
1503          (when (if (fboundp 'custom-variable-p) (custom-variable-p symb) (user-variable-p symb))
1504            (condition-case nil
1505                (push (list symb (get symb 'custom-type)) result)
1506              (error nil)))))
1507     ;; Keep only candidates that correspond to input.
1508     (setq result
1509           (let ((ops-re  (if (memq icicle-current-completion-mode '(nil apropos))
1510                              ops
1511                            (concat "^" ops))))
1512             (icicle-remove-if-not
1513              #'(lambda (opt+typ)
1514                  (and (string-match ops-re (symbol-name (car opt+typ)))
1515                       (or (null tp)
1516                           (condition-case nil
1517                               (icicle-var-is-of-type-p (car opt+typ) (list tp)
1518                                                        (case mode
1519                                                          ((inherit inherit-or-regexp) 'inherit)
1520                                                          ((direct  direct-or-regexp)  'direct)
1521                                                          (inherit-or-value     'inherit-or-value)
1522                                                          (direct-or-value      'direct-or-value)))
1523                             (error nil)))))
1524              result)))
1525     ;; Change alist entries to multi-completions: "op^G^Jtp".  Add short help for mode-line, tooltip.
1526     (setq result
1527           (mapcar #'(lambda (entry)
1528                       (let* ((opt+typ-string
1529                               ;; $$$$$$ (concat (mapconcat #'(lambda (e) (pp-to-string e))
1530                               ;;                           entry icicle-list-join-string)
1531                               ;;                icicle-list-end-string)) ; $$$$$$
1532                               (mapconcat #'(lambda (e) (pp-to-string e)) entry
1533                                          icicle-list-join-string))
1534                              (doc       ; Don't bother to look up doc, if user won't see it.
1535                               (and (or (> icicle-help-in-mode-line-delay 0)
1536                                        (and (boundp 'tooltip-mode) tooltip-mode))
1537                                    (documentation-property (car entry) 'variable-documentation t)))
1538                              (doc1  (and (stringp doc)
1539                                          (string-match ".+$" doc) (match-string 0 doc))))
1540                         (when doc1 (icicle-candidate-short-help doc1 opt+typ-string))
1541                         opt+typ-string))
1542                   result))
1543     (if completion-mode
1544         result                          ; `all-completions', `test-completion'
1545       (try-completion strg (mapcar #'list result) pred)))) ; `try-completion'
1546
1547 ;;;###autoload (autoload 'icicle-vardoc "icicles-cmd2.el")
1548 (icicle-define-command icicle-vardoc    ; Command name
1549   "Choose a variable description.
1550 Each candidate for completion is a variable name plus its
1551 documentation.  They are separated by `icicle-list-join-string'
1552 \(\"^G^J\", by default).  You can match an input regexp against the
1553 variable name or the documentation or both.  Use `C-M-j' (equivalent
1554 here to `C-q C-g C-j') to input the default separator.
1555
1556 For example, use input
1557
1558 \"dired.*^G
1559 \[^^G]*list\"
1560
1561 with `S-TAB' to match all variables whose names contain \"dired\" and
1562 whose documentation contains \"list\".  Here, `[^^G]' matches any
1563 character except ^G, which includes newline.  If you use `.*' here,
1564 instead, then only the first lines of doc strings are searched.
1565
1566 With a non-negative prefix argument, use the same documentation that
1567 was gathered the last time `icicle-vardoc' was called.  Use a
1568 non-negative prefix arg to save the time that would be needed to
1569 gather the documentation.
1570
1571 With a non-positive prefix arg, use only user variables (options) as
1572 candidates.
1573
1574 Remember that you can use `\\<minibuffer-local-completion-map>\
1575 \\[icicle-toggle-incremental-completion] to toggle incremental completion." ; Doc string
1576   icicle-doc-action                     ; Action function
1577   prompt                                ; `completing-read' args
1578   (let* ((num-arg         (prefix-numeric-value pref-arg))
1579          (options-only-p  (<= num-arg 0))
1580          (result          (and pref-arg (>= num-arg 0)
1581                                (if options-only-p
1582                                    icicle-vardoc-last-initial-option-cand-set
1583                                  icicle-vardoc-last-initial-cand-set))))
1584     (unless result                      ; COLLECTION arg is an alist whose items are ((SYMB DOC)).
1585       (mapatoms #'(lambda (symb)        ; Each completion candidate is a list of strings.
1586                     (when (and (boundp symb)
1587                                (or (wholenump (prefix-numeric-value pref-arg))
1588                                    (user-variable-p symb)))
1589                       (let ((doc  (documentation-property symb 'variable-documentation)))
1590                         (when (icicle-non-whitespace-string-p doc)
1591                           (push (list (list (symbol-name symb) doc)) result))))))
1592       (if options-only-p
1593           (setq icicle-vardoc-last-initial-option-cand-set  result)
1594         (setq icicle-vardoc-last-initial-cand-set  result)))
1595     result)
1596   nil nil nil 'icicle-doc-history nil nil
1597   ((prompt                             "VAR `C-M-j' DOC: ") ; Bindings
1598    (icicle-candidate-properties-alist  '((1 (face icicle-candidate-part))))
1599    (icicle-list-use-nth-parts          '(1))
1600    (pref-arg                           current-prefix-arg))
1601   (progn
1602     (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code
1603     (icicle-highlight-lighter)
1604     (message "Gathering variable descriptions...")))
1605
1606 ;;; $$$$$$ (defun icicle-funvardoc-action (entry)
1607 ;;;   "Action function for `icicle-vardoc', `icicle-fundoc', `icicle-plist'."
1608 ;;;   (with-output-to-temp-buffer "*Help*" (princ entry)))
1609
1610 ;;;###autoload (autoload 'icicle-fundoc "icicles-cmd2.el")
1611 (icicle-define-command icicle-fundoc    ; Command name
1612   "Choose a function description.
1613 Each candidate for completion is a function name plus its
1614 documentation.  They are separated by `icicle-list-join-string'
1615 \(\"^G^J\", by default).  You can match an input regexp against the
1616 function name or the documentation or both.  Use `C-M-j' (equivalent
1617 here to `C-q C-g C-j') to input the default separator.
1618
1619 For example, use input
1620
1621 \"dired.*^G
1622 \[^^G]*file\"
1623
1624 with `S-TAB' to match all functions whose names contain \"dired\" and
1625 whose documentation contains \"file\".  Here, `[^^G]' matches any
1626 character except ^G, which includes newline.  If you use `.*' here,
1627 instead, then only the first lines of doc strings are searched.
1628
1629 With a prefix argument, use the same documentation that was gathered
1630 the last time `icicle-fundoc' was called.  Use a prefix arg to save
1631 the time that would be needed to gather the documentation.
1632
1633 Remember that you can use `\\<minibuffer-local-completion-map>\
1634 \\[icicle-toggle-incremental-completion] to toggle incremental completion." ; Doc string
1635   icicle-doc-action                     ; Action function
1636   prompt                                ; `completing-read' args
1637   (let ((result  (and pref-arg icicle-fundoc-last-initial-cand-set)))
1638     (unless result                      ; COLLECTION arg is an alist whose items are ((symb doc)).
1639       (mapatoms
1640        #'(lambda (symb)                 ; Each completion candidate is a list of strings.
1641            (when (fboundp symb)
1642              ;; Ignore symbols that produce errors.  Example: In Emacs 20, `any', which is defalias'd
1643              ;; to `icicle-anything', raises this error: "Symbol's function definition is void: any".
1644              ;; This is caused by the `after' advice `ad-advised-docstring' that is defined by Emacs
1645              ;; itself for function `documentation'.  It is not a problem for Emacs 22+.
1646              (let ((doc  (condition-case nil (documentation symb) (error nil))))
1647                (when (and doc (icicle-non-whitespace-string-p (icicle-fn-doc-minus-sig doc)))
1648                  (push (list (list (symbol-name symb) doc)) result))))))
1649       (setq icicle-fundoc-last-initial-cand-set  result))
1650     result)
1651   nil nil nil 'icicle-doc-history nil nil
1652   ((prompt                             "FUNC `C-M-j' DOC: ") ; Bindings
1653    (icicle-candidate-properties-alist  '((1 (face icicle-candidate-part))))
1654    (icicle-list-use-nth-parts          '(1))
1655    (pref-arg                           current-prefix-arg))
1656   (progn
1657     (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code
1658     (icicle-highlight-lighter)
1659     (message "Gathering function descriptions...")))
1660
1661 (defun icicle-fn-doc-minus-sig (docstring)
1662   "Return DOCSTRING minus the function signature (usage info)."
1663   (let ((sig-p  (string-match "\n\n(fn\\(\\( .*\\)?)\\)\\'" docstring)))
1664     (if sig-p (substring docstring 0 (match-beginning 0)) docstring)))
1665
1666 ;;;###autoload (autoload 'icicle-plist "icicles-cmd2.el")
1667 (icicle-define-command icicle-plist     ; Command name
1668   "Choose a symbol and its property list.
1669 Each candidate for completion is a symbol name plus its property list
1670 \(as a string).  They are separated by `icicle-list-join-string'
1671 \(^G^J, by default).  You can match an input regexp against the symbol
1672 name or the property list or both.  Use `C-M-j' (equivalent here to
1673 `C-q C-g C-j') to input the default separator.
1674
1675 With a positive prefix argument, use the same initial set of
1676 candidates that were gathered the last time `icicle-plist' was called.
1677 Use a positive prefix arg to save the time that would be needed to
1678 gather the plists.
1679
1680 With a negative prefix arg, do not pretty-print each property list, in
1681 buffers `*Help* and `*Completions*'.  Generation of the complete set
1682 of candidates is about twice as fast when not pretty-printed, but the
1683 time to match your input and display candidates is the same, and the
1684 match-and-display time for empty input,is much longer than the
1685 generation time.
1686
1687 The time to repeat (positive prefix arg) is the same, whether or not
1688 candidates were pretty-printed the first time.
1689
1690 Note: Plists are never pretty-printed for Emacs 20, because that seems
1691 to cause an Emacs crash.
1692
1693 Remember that you can use `\\<minibuffer-local-completion-map>\
1694 \\[icicle-toggle-incremental-completion] to toggle incremental completion." ; Doc string
1695   icicle-doc-action                     ; Action function
1696   prompt                                ; `completing-read' args
1697   (let ((result  (and pref-arg (wholenump (prefix-numeric-value pref-arg))
1698                       icicle-plist-last-initial-cand-set)))
1699     (unless result                      ; COLLECTION arg: an alist with items ((symb plist-string))
1700       (mapatoms
1701        #'(lambda (symb)                 ; Each completion candidate is a list of strings.
1702            (condition-case nil          ; Ignore symbols that produce errors.
1703                (let ((plist  (symbol-plist symb)))
1704                  (when plist
1705                    (push (list (list (symbol-name symb)
1706                                      (if (or (< (prefix-numeric-value pref-arg) 0)
1707                                              (< emacs-major-version 21)) ; Emacs 20 crash if pprint.
1708                                          (format "%s" plist)
1709                                        (pp-to-string plist))))
1710                          result)))
1711              (error nil))))
1712       (setq icicle-plist-last-initial-cand-set  result))
1713     result)
1714   nil nil nil nil nil nil
1715   ((prompt                             "SYMB `C-M-j' PLIST: ") ; Bindings
1716    (icicle-candidate-properties-alist  '((1 (face icicle-candidate-part))))
1717    (icicle-list-use-nth-parts          '(1))
1718    (pref-arg                           current-prefix-arg))
1719   (progn
1720     (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code
1721     (icicle-highlight-lighter)
1722     (message "Gathering property lists...")))
1723
1724 ;;;###autoload (autoload 'icicle-doc "icicles-cmd2.el")
1725 (icicle-define-command icicle-doc       ; Command name
1726   "Choose documentation for a symbol.
1727 Each candidate for completion is the description of a function,
1728 variable, or face.  Displays the documentation and returns the symbol.
1729
1730 Each candidate for completion is a symbol name plus its type
1731 \(FUNCTION, VARIABLE, or FACE) and its documentation.  These candidate
1732 components are separated by `icicle-list-join-string' (\"^G^J\", by
1733 default).  You can match an input regexp against the symbol name,
1734 type, or the documentation or any combination of the three.  Use
1735 `C-M-j' (equivalent here to `C-q C-g C-j') to input the default
1736 separator.
1737
1738 With a prefix argument, use the same documentation that was gathered
1739 the last time `icicle-doc' was called.  Use a prefix arg to save the
1740 time that would be needed to gather the documentation.
1741
1742 Remember that you can use \\<minibuffer-local-completion-map>\
1743 `\\[icicle-toggle-incremental-completion]' to toggle incremental completion." ; Doc string
1744   icicle-doc-action                     ; Action function: display the doc.
1745   prompt                                ; `completing-read' args
1746   (let ((result  (and pref-arg icicle-doc-last-initial-cand-set))
1747         doc)                            ; Each completion candidate is a list of strings.
1748     (unless result                      ; COLLECTION arg is an alist with items (doc . symb).
1749       (mapatoms
1750        #'(lambda (symb)
1751            (progn
1752              (when (and (functionp symb) ; Function's doc.
1753                         ;; Ignore symbols that produce errors.  See comment for `icicle-fundoc'.
1754                         (setq doc  (condition-case nil (documentation symb) (error nil)))
1755                         (setq doc  (icicle-fn-doc-minus-sig doc))
1756                         (icicle-non-whitespace-string-p doc)
1757                         (setq doc  (concat doc "\n\n")))
1758                (push (cons (list (concat (symbol-name symb) icicle-list-join-string "FUNCTION") doc)
1759                            symb)
1760                      result))
1761              (when (and (boundp symb)   ; Variable's doc (and keymap var's bindings if remove nil)
1762                         (setq doc  (documentation-property symb 'variable-documentation))
1763                         (icicle-non-whitespace-string-p doc))
1764                (when (and nil           ; $$$ Remove nil to get keymaps, but it slows things down.
1765                           (fboundp 'describe-keymap)
1766                           (keymapp (symbol-value symb)))
1767                  (setq doc  (concat (symbol-name symb) ":\n" doc "\n\n" ; Keymap variable's doc.
1768                                     (substitute-command-keys
1769                                      (concat "\\{" (symbol-name symb) "}"))
1770                                     "\n\n")))
1771                (setq doc  (concat doc "\n\n"))
1772                (push (cons (list (concat (symbol-name symb) icicle-list-join-string "VARIABLE") doc)
1773                            symb)
1774                      result))
1775              (when (and (facep symb)
1776                         (setq doc  (documentation-property symb 'face-documentation)))
1777                (push (cons (list (concat (symbol-name symb) icicle-list-join-string "FACE") doc)
1778                            symb)
1779                      result)))))
1780       (setq icicle-doc-last-initial-cand-set  result))
1781     result)
1782   nil nil nil 'icicle-doc-history nil nil
1783   ((prompt                             "Find doc using regexp: ") ; Bindings
1784    (icicle-candidate-properties-alist  '((1 (face icicle-candidate-part))))
1785    (icicle-list-use-nth-parts          '(1))
1786    (icicle-transform-function          'icicle-remove-duplicates) ; Duplicates are due to `fset's.
1787    (icicle-candidate-help-fn           'icicle-doc-action)
1788    (pref-arg                           current-prefix-arg))
1789   (progn
1790     (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code
1791     (icicle-highlight-lighter)
1792     (message "Gathering documentation...")))
1793
1794 (defun icicle-doc-action (entry)
1795   "Completion action function for `icicle-doc': Display the doc."
1796   (let ((symb  (intern (icicle-transform-multi-completion entry))))
1797     (cond ((fboundp symb) (describe-function symb))
1798           ;; $$$ This works fine, but it slows things down:
1799           ;; ((and (fboundp 'describe-keymap) (boundp symb) (keymapp (symbol-value symb)))
1800           ;;  (describe-keymap symb))
1801           ((and symb (boundp symb)) (describe-variable symb))
1802           ((facep symb) (describe-face symb)))
1803     symb))
1804
1805 ;;;###autoload
1806 (defun icicle-non-whitespace-string-p (string)
1807   "Return non-nil if STRING is a string and contains a non-whitespace char.
1808 The `standard-syntax-table' definition of whitespace is used."
1809   (interactive "s")
1810   (let ((orig-syntable  (syntax-table)))
1811     (unwind-protect
1812        (progn
1813          (set-syntax-table (standard-syntax-table))
1814          (and (stringp string) (> (length string) 0) (string-match "\\S-" string)))
1815       (set-syntax-table orig-syntable))))
1816
1817 ;;;###autoload
1818 (defun icicle-apropos (apropos-regexp &optional do-all)
1819   "Like `apropos', but lets you see the list of matches (with `S-TAB').
1820 Function names are highlighted using face `icicle-special-candidate'."
1821   (interactive
1822    (list
1823     (unwind-protect
1824          (progn
1825            (mapatoms #'(lambda (symb) (when (fboundp symb) (put symb 'icicle-special-candidate t))))
1826            (let ((icicle-fancy-candidates-p  t)
1827                  (icicle-candidate-alt-action-fn
1828                   (or icicle-candidate-alt-action-fn
1829                       (icicle-alt-act-fn-for-type "symbol")))
1830                  (icicle-all-candidates-list-alt-action-fn
1831                   (or icicle-all-candidates-list-alt-action-fn
1832                       (icicle-alt-act-fn-for-type "symbol"))))
1833              (completing-read "Apropos symbol (regexp or words): " obarray
1834                               nil nil nil 'regexp-history)))
1835       (mapatoms #'(lambda (symb) (put symb 'icicle-special-candidate nil))))
1836     current-prefix-arg))
1837   (apropos apropos-regexp do-all))
1838
1839 (cond
1840   ;; Use my versions of the `apropos*' commands, defined in `apropos-fn+var.el'.
1841   ;; Note that unlike my versions of `apropos-option' and `apropos-command', the `icicle-'
1842   ;; versions here do not respect `apropos-do-all': they always work with options and commands.
1843   ((fboundp 'apropos-option)
1844    (defun icicle-apropos-variable (pattern)
1845      "Show variables that match PATTERN.
1846 This includes variables that are not user options.
1847 User options are highlighted using face `icicle-special-candidate'.
1848 You can see the list of matches with `S-TAB'.
1849 See `apropos-variable' for a description of PATTERN."
1850      (interactive
1851       (list
1852        (unwind-protect
1853             (progn
1854               (mapatoms #'(lambda (symb)
1855                             (when (user-variable-p symb) (put symb 'icicle-special-candidate t))))
1856               (let ((icicle-fancy-candidates-p  t)
1857                     (icicle-must-pass-after-match-predicate
1858                      #'(lambda (s)
1859                          (setq s  (intern s))
1860                          (and (boundp s) (get s 'variable-documentation))))
1861                     (icicle-candidate-alt-action-fn
1862                      (or icicle-candidate-alt-action-fn
1863                          (icicle-alt-act-fn-for-type "variable")))
1864                     (icicle-all-candidates-list-alt-action-fn
1865                      (or icicle-all-candidates-list-alt-action-fn
1866                          (icicle-alt-act-fn-for-type "variable"))))
1867                 (completing-read
1868                  (concat "Apropos variable (regexp" (and (>= emacs-major-version 22) " or words")
1869                          "): ")
1870                  obarray nil nil nil 'regexp-history)))
1871          (mapatoms #'(lambda (symb) (put symb 'icicle-special-candidate nil))))))
1872      (apropos-variable pattern))
1873
1874    (defun icicle-apropos-option (pattern)
1875      "Show user options (variables) that match PATTERN.
1876 You can see the list of matches with `S-TAB'.
1877 See `apropos-option' for a description of PATTERN."
1878      (interactive
1879       (let ((icicle-must-pass-after-match-predicate  #'(lambda (s) (user-variable-p (intern s)))))
1880         (list (completing-read
1881                (concat "Apropos user option (regexp" (and (>= emacs-major-version 22) " or words")
1882                        "): ") obarray nil nil nil 'regexp-history))))
1883      (let ((apropos-do-all  nil)
1884            (icicle-candidate-alt-action-fn
1885             (or icicle-candidate-alt-action-fn (icicle-alt-act-fn-for-type "option")))
1886            (icicle-all-candidates-list-alt-action-fn
1887             (or icicle-all-candidates-list-alt-action-fn (icicle-alt-act-fn-for-type "option"))))
1888        (apropos-option pattern)))
1889
1890    (defun icicle-apropos-function (pattern)
1891      "Show functions that match PATTERN.
1892 This includes functions that are not commands.
1893 Command names are highlighted using face `icicle-special-candidate'.
1894 You can see the list of matches with `S-TAB'.
1895 See `apropos-function' for a description of PATTERN."
1896      (interactive
1897       (list
1898        (unwind-protect
1899             (progn
1900               (mapatoms #'(lambda (symb)
1901                             (when (commandp symb) (put symb 'icicle-special-candidate t))))
1902               (let ((icicle-fancy-candidates-p               t)
1903                     (icicle-must-pass-after-match-predicate  #'(lambda (s) (fboundp (intern s))))
1904                     (icicle-candidate-alt-action-fn
1905                      (or icicle-candidate-alt-action-fn
1906                          (icicle-alt-act-fn-for-type "function")))
1907                     (icicle-all-candidates-list-alt-action-fn
1908                      (or icicle-all-candidates-list-alt-action-fn
1909                          (icicle-alt-act-fn-for-type "function"))))
1910                 (completing-read
1911                  (concat "Apropos function (regexp" (and (>= emacs-major-version 22) " or words")
1912                          "): ") obarray nil nil nil 'regexp-history)))
1913          (mapatoms #'(lambda (symb) (put symb 'icicle-special-candidate nil))))))
1914      (apropos-function pattern))
1915
1916    (defun icicle-apropos-command (pattern)
1917      "Show commands (interactively callable functions) that match PATTERN.
1918 You can see the list of matches with `S-TAB'.
1919 See `apropos-command' for a description of PATTERN."
1920      (interactive
1921       (let ((icicle-must-pass-after-match-predicate  #'(lambda (s) (commandp (intern s))))
1922             (icicle-candidate-alt-action-fn
1923              (or icicle-candidate-alt-action-fn (icicle-alt-act-fn-for-type "command")))
1924             (icicle-all-candidates-list-alt-action-fn
1925              (or icicle-all-candidates-list-alt-action-fn (icicle-alt-act-fn-for-type "command"))))
1926         (list (completing-read
1927                (concat "Apropos command (regexp" (and (>= emacs-major-version 22) " or words")
1928                        "): ") obarray nil nil nil 'regexp-history))))
1929      (let ((apropos-do-all  nil))  (apropos-command pattern))))
1930
1931   ;; My versions are not available.  Use the vanilla Emacs versions of the `apropos...' commands.
1932   (t
1933    (defun icicle-apropos-variable (pattern &optional do-all)
1934      "Show variables that match PATTERN.
1935 You can see the list of matches with `S-TAB'.
1936 See `apropos-variable' for a description of PATTERN.
1937
1938 By default, only user options are candidates.  With optional prefix
1939 DO-ALL, or if `apropos-do-all' is non-nil, all variables are
1940 candidates.  In that case, the user-option candidates are highlighted
1941 using face `icicle-special-candidate'."
1942      (interactive
1943       (list
1944        (unwind-protect
1945             (progn
1946               (unless (or (boundp 'apropos-do-all) (require 'apropos nil t))
1947                 (error "Library `apropos' not found"))
1948               (when (or current-prefix-arg apropos-do-all)
1949                 (mapatoms #'(lambda (symb)
1950                               (when (user-variable-p symb) (put symb 'icicle-special-candidate t)))))
1951               (let ((icicle-fancy-candidates-p  (or current-prefix-arg apropos-do-all))
1952                     (icicle-must-pass-after-match-predicate
1953                      (if (or current-prefix-arg apropos-do-all)
1954                          #'(lambda (s)
1955                              (setq s  (intern s))
1956                              (and (boundp s) (get s 'variable-documentation)))
1957                        #'(lambda (s) (user-variable-p (intern s)))))
1958                     (icicle-candidate-alt-action-fn
1959                      (or icicle-candidate-alt-action-fn
1960                          (icicle-alt-act-fn-for-type (if icicle-fancy-candidates-p
1961                                                          "variable"
1962                                                        "option"))))
1963                     (icicle-all-candidates-list-alt-action-fn
1964                      (or icicle-all-candidates-list-alt-action-fn
1965                          (icicle-alt-act-fn-for-type (if icicle-fancy-candidates-p
1966                                                          "variable"
1967                                                        "option")))))
1968                 (completing-read
1969                  (concat "Apropos " (if (or current-prefix-arg apropos-do-all)
1970                                         "variable" "user option")
1971                          " (regexp" (and (>= emacs-major-version 22) " or words") "): ")
1972                  obarray nil nil nil 'regexp-history)))
1973          (when (or current-prefix-arg apropos-do-all)
1974            (mapatoms #'(lambda (symb) (put symb 'icicle-special-candidate nil)))))
1975        current-prefix-arg))
1976      (apropos-variable pattern do-all))
1977
1978    (defun icicle-apropos-command (pattern &optional do-all var-predicate)
1979      "Show commands (interactively callable functions) that match PATTERN.
1980 You can see the list of matches with `S-TAB'.
1981
1982 See `apropos-command' for a description of PATTERN.
1983
1984 With \\[universal-argument] prefix, or if `apropos-do-all' is non-nil,
1985 also show noninteractive functions.  In that case, the command
1986 candidates are highlighted using face `icicle-special-candidate'.
1987
1988 If VAR-PREDICATE is non-nil, show only variables, and only those that
1989 satisfy the predicate VAR-PREDICATE."
1990      (interactive
1991       (list
1992        (unwind-protect
1993             (progn
1994               (unless (boundp 'apropos-do-all)
1995                 (unless (require 'apropos nil t) (error "Library `apropos' not found")))
1996               (when (or current-prefix-arg apropos-do-all)
1997                 (mapatoms #'(lambda (symb)
1998                               (when (commandp symb) (put symb 'icicle-special-candidate t)))))
1999               (let ((icicle-fancy-candidates-p  (or current-prefix-arg apropos-do-all))
2000                     (icicle-must-pass-after-match-predicate
2001                      (if current-prefix-arg
2002                          #'(lambda (s) (fboundp (intern s)))
2003                        #'(lambda (s) (commandp (intern s)))))
2004                     (icicle-candidate-alt-action-fn
2005                      (or icicle-candidate-alt-action-fn
2006                          (icicle-alt-act-fn-for-type (if icicle-fancy-candidates-p
2007                                                          "function"
2008                                                        "command"))))
2009                     (icicle-all-candidates-list-alt-action-fn
2010                      (or icicle-all-candidates-list-alt-action-fn
2011                          (icicle-alt-act-fn-for-type (if icicle-fancy-candidates-p
2012                                                          "function"
2013                                                        "command")))))
2014                 (completing-read
2015                  (concat "Apropos " (if (or current-prefix-arg apropos-do-all)
2016                                         "command or function" "command")
2017                          "(regexp" (and (>= emacs-major-version 22) " or words") "): ")
2018                  obarray nil nil nil 'regexp-history)))
2019          (when (or current-prefix-arg apropos-do-all)
2020            (mapatoms #'(lambda (symb) (put symb 'icicle-special-candidate nil)))))
2021        current-prefix-arg))
2022      (apropos-command pattern do-all var-predicate))))
2023
2024 ;;;###autoload
2025 (defun icicle-apropos-zippy (regexp)
2026   "Show all Zippy quotes matching the regular-expression input REGEXP.
2027 Return the list of matches."
2028   (interactive (progn (unless (boundp 'yow-file)
2029                         (unless (require 'yow nil t) (error "Library `yow' not found")))
2030                       (cookie yow-file yow-load-message yow-after-load-message)
2031                       (let* ((case-fold-search     t)
2032                              (cookie-table-symbol  (intern yow-file cookie-cache))
2033                              (string-table         (symbol-value cookie-table-symbol))
2034                              (table                (nreverse (mapcar #'list string-table))))
2035                         (list (completing-read "Apropos Zippy (regexp): " table
2036                                                nil nil nil 'regexp-history)))))
2037   (let ((matches  (apropos-zippy icicle-current-input)))
2038     (when (interactive-p)
2039       (with-output-to-temp-buffer "*Zippy Apropos*"
2040         (while matches
2041           (princ (car matches))
2042           (setq matches  (cdr matches))
2043           (and matches (princ "\n\n")))))
2044     matches))                           ; Return matching Zippyisms.
2045
2046 ;;;###autoload
2047 (defalias 'icicle-map 'icicle-apply)
2048 ;;;###autoload
2049 (defun icicle-apply (alist fn &optional nomsg predicate initial-input hist def inherit-input-method)
2050   "Selectively apply a function to elements in an alist.
2051 Argument ALIST is an alist such as can be used as the COLLECTION
2052 argument for Icicles `completing-read'.  Its elements can represent
2053 multi-completions, for example.  Interactively, COLLECTION is a
2054 variable (a symbol) whose value is an alist.
2055
2056 Argument FN is a function.
2057
2058 Optional argument NOMSG non-nil means do not display an informative
2059 message each time FN is applied.  If nil, then a message shows the key
2060 of the alist element that FN is applied to and the result of the
2061 application.
2062
2063 The remaining arguments are optional.  They are the arguments
2064 PREDICATE, INITIAL-INPUT, HIST, DEF, and INHERIT-INPUT-METHOD for
2065 `completing-read' (that is, all of the `completing-read' args other
2066 than PROMPT, COLLECTION, and REQUIRE-MATCH).  During `icicle-apply'
2067 completion, a match is required (REQUIRE-MATCH is t).
2068
2069 Interactively, you are prompted for both arguments.  Completion is
2070 available for each.  The completion list for ALIST candidates is the
2071 set of variables whose value is a cons.  With no prefix argument, the
2072 names of these variables must end with \"alist\".  With a prefix
2073 argument, the first car of each variable value must itself be a cons.
2074
2075 After choosing the ALIST and FN, you are prompted to choose one or
2076 more keys of the alist elements, and FN is applied to each element
2077 that has a key that you choose.  Multi-command completion is available
2078 for choosing these candidates: you can apply FN to any number of
2079 elements, any number of times.
2080
2081 Examples: If ALIST is `auto-mode-alist' and FN is `cdr', then the
2082 completion candidates are the keys of the alist, and the result of
2083 applying FN to an alist element is simply the value of that key.  If
2084 you choose, for example, candidate \"\\.el\\'\", then the result is
2085 `cdr' applied to the alist element (\"\\.el\\'\" . emacs-lisp-mode),
2086 which is the symbol `emacs-lisp-mode'.  In this case, the function
2087 performs simple lookup.
2088
2089 If FN were instead (lambda (x) (describe-function (cdr x))), then the
2090 result of choosing candidate \"\\.el\\'\" would be to display the help
2091 for function `emacs-lisp-mode'.
2092
2093 NOTE: `icicle-apply' does not, by itself, impose any particular sort
2094 order.  Neither does it inhibit sorting.  If you call this function
2095 from Lisp code and you want it to use a certain sort order or you want
2096 no sorting, then bind `icicle-sort-comparer' accordingly.
2097
2098 During completion you can use multi-command keys.  Each displays the
2099 value of applying FN to an alist element whose key is a completion
2100 candidate.
2101
2102 `C-RET'   - Act on current completion candidate only
2103 `C-down'  - Move to next completion candidate and act
2104 `C-up'    - Move to previous completion candidate and act
2105 `C-next'  - Move to next apropos-completion candidate and act
2106 `C-prior' - Move to previous apropos-completion candidate and act
2107 `C-end'   - Move to next prefix-completion candidate and act
2108 `C-home'  - Move to previous prefix-completion candidate and act
2109 `C-!'     - Act on *each* candidate (or each that is saved), in turn.
2110 `M-!'     - Act on the list of *all* candidates (or all saved).
2111
2112 Note that `M-!' applies FN to the *list* of chosen alist elements,
2113 whereas `C-!' applies FN to each chosen element, in turn.  For
2114 example, if FN is `length' and your input is `\.el', then `M-!' displays
2115 the result of applying `length' to the list of chosen elements:
2116
2117  ((\"\\.el\\'\" . emacs-lisp-mode) (\"\\.elc'\" . emacs-lisp-mode))
2118
2119 which is 2.
2120
2121 When candidate action and cycling are combined (e.g. `C-next'), option
2122 `icicle-act-before-cycle-flag' determines which occurs first.
2123
2124 With prefix `C-M-' instead of `C-', the same keys (`C-M-mouse-2',
2125 `C-M-RET', `C-M-down', and so on) provide help about candidates.
2126
2127 Use `mouse-2', `RET', or `S-RET' to finally choose a candidate, or
2128 `C-g' to quit.  This is an Icicles command - see command
2129 `icicle-mode'.
2130
2131 `icicle-apply' overrides `icicle-ignore-space-prefix-flag', binding it
2132 to nil so that candidates with initial spaces can be matched."
2133   (interactive
2134    (list (symbol-value
2135           (intern
2136            (let ((icicle-must-pass-after-match-predicate
2137                   `(lambda (s)
2138                       (setq s  (intern s))
2139                       (and (boundp s) (consp (symbol-value s))
2140                            ,(if current-prefix-arg
2141                                 '(consp (car (symbol-value s)))
2142                                 '(string-match "alist$" (symbol-name s))))))
2143                  (icicle-candidate-alt-action-fn
2144                   (or icicle-candidate-alt-action-fn
2145                       (icicle-alt-act-fn-for-type "variable")))
2146                  (icicle-all-candidates-list-alt-action-fn
2147                   (or icicle-all-candidates-list-alt-action-fn
2148                       (icicle-alt-act-fn-for-type "variable"))))
2149              (completing-read "Alist (variable): " obarray nil t nil
2150                               (if (boundp 'variable-name-history)
2151                                   'variable-name-history
2152                                 'icicle-variable-name-history)))))
2153          (read
2154           (let ((icicle-must-pass-after-match-predicate  #'(lambda (s) (functionp (intern s))))
2155                 (icicle-candidate-alt-action-fn
2156                  (or icicle-candidate-alt-action-fn
2157                      (icicle-alt-act-fn-for-type "function")))
2158                 (icicle-all-candidates-list-alt-action-fn
2159                  (or icicle-all-candidates-list-alt-action-fn
2160                      (icicle-alt-act-fn-for-type "function"))))
2161             (completing-read "Function: " obarray nil nil nil (if (boundp 'function-name-history)
2162                                                                   'function-name-history
2163                                                                 'icicle-function-name-history))))))
2164
2165   (setq icicle-candidate-entry-fn  fn)  ; Save in global variable - used by `icicle-apply-action'.
2166   (let ((icicle-candidate-action-fn            'icicle-apply-action)
2167         (icicle-all-candidates-list-action-fn  'icicle-apply-list-action)
2168         (icicle-ignore-space-prefix-flag       nil)
2169         (icicle-apply-nomsg                    nomsg)
2170         (enable-recursive-minibuffers          t))
2171     (icicle-explore
2172      #'(lambda ()
2173          (setq icicle-candidates-alist  ; Ensure that keys of ALIST are strings or conses.
2174                (mapcar #'(lambda (key+val)
2175                            (if (consp (car key+val))
2176                                key+val  ; Multi-completion candidate: (("aaa" "bbb") . ccc)
2177                              (cons (format "%s" (car key+val)) (cdr key+val))))
2178                        alist)))
2179      #'(lambda ()
2180          (let ((result  (funcall icicle-candidate-entry-fn icicle-explore-final-choice-full)))
2181            (unless nomsg
2182              (message "Key: %s,  Result: %s" (car icicle-explore-final-choice-full) result))
2183            result))                     ; Return result.
2184      nil nil nil "Choose an occurrence: " predicate t initial-input hist def inherit-input-method)))
2185
2186 (defun icicle-apply-action (string)
2187   "Completion action function for `icicle-apply'."
2188   (unwind-protect
2189       (icicle-condition-case-no-debug icicle-apply-action
2190           (progn
2191             (icicle-highlight-candidate-in-Completions)
2192             ;; Apply function to candidate element and display it.
2193             (let* ((key+value  (funcall icicle-get-alist-candidate-function string))
2194                    (result     (funcall icicle-candidate-entry-fn key+value)))
2195               (unless icicle-apply-nomsg
2196                 (message "Key: %s,  Result: %s" (car key+value) result)))
2197             nil)                        ; Return nil for success.
2198         (error "%s" (error-message-string icicle-apply-action))) ; Return error msg.
2199     (select-window (minibuffer-window))
2200     (select-frame-set-input-focus (selected-frame))))
2201
2202 (defun icicle-apply-list-action (strings)
2203   "Completion action list function for `icicle-apply'."
2204   (unwind-protect
2205        (icicle-condition-case-no-debug icicle-apply-list-action
2206            (progn                       ; Apply function to candidate element and display it.
2207              (message "Result: %s" (funcall icicle-candidate-entry-fn
2208                                             (mapcar icicle-get-alist-candidate-function strings)))
2209              nil)                       ; Return nil for success.
2210          (error "%s" (error-message-string icicle-apply-list-action))) ; Return error msg.
2211     (select-window (minibuffer-window))
2212     (select-frame-set-input-focus (selected-frame))))
2213
2214 ;;;###autoload
2215 (defun icicle-goto-marker-or-set-mark-command (arg) ; Bound to `C-@', `C-SPC'.
2216   "With prefix arg < 0, `icicle-goto-marker'; else `set-mark-command'.
2217 By default, Icicle mode remaps all key sequences that are normally
2218 bound to `set-mark-command' to
2219 `icicle-goto-marker-or-set-mark-command'.  If you do not want this
2220 remapping, then customize option `icicle-top-level-key-bindings'."
2221   (interactive "P")
2222   (if (not (wholenump (prefix-numeric-value arg)))
2223       (icicle-goto-marker)
2224     (setq this-command 'set-mark-command) ; Let `C-SPC C-SPC' activate if not `transient-mark-mode'.
2225     (set-mark-command arg)))
2226
2227 ;;;###autoload
2228 (defun icicle-goto-global-marker-or-pop-global-mark (arg) ; Bound to `C-x C-@', `C-x C-SPC'.
2229   "With prefix arg < 0, `icicle-goto-global-marker'; else `pop-global-mark'.
2230 By default, Icicle mode remaps all key sequences that are normally
2231 bound to `pop-global-mark' to
2232 `icicle-goto-global-marker-or-pop-global-mark'.  If you do not want
2233 this remapping, then customize option
2234 `icicle-top-level-key-bindings'."
2235   (interactive "P")
2236   (if (wholenump (prefix-numeric-value arg))
2237       (pop-global-mark)
2238     (icicle-goto-global-marker)))
2239
2240 ;;;###autoload
2241 (defun icicle-goto-marker ()            ; Bound to `C-- C-@', `C-- C-SPC'.
2242   "Go to a marker in this buffer, choosing it by the line that includes it.
2243 If `crosshairs.el' is loaded, then the target position is highlighted.
2244
2245 By default, candidates are sorted in marker order, that is, with
2246 respect to their buffer positions.  Use `C-M-,' or `C-,' to change the
2247 sort order.
2248
2249 During completion you can use these keys:
2250
2251 `C-RET'   - Goto marker named by current completion candidate
2252 `C-down'  - Goto marker named by next completion candidate
2253 `C-up'    - Goto marker named by previous completion candidate
2254 `C-next'  - Goto marker named by next apropos-completion candidate
2255 `C-prior' - Goto marker named by previous apropos-completion candidate
2256 `C-end'   - Goto marker named by next prefix-completion candidate
2257 `C-home'  - Goto marker named by previous prefix-completion candidate
2258 `S-delete' - Delete marker named by current completion candidate
2259
2260 When candidate action and cycling are combined (e.g. `C-next'), option
2261 `icicle-act-before-cycle-flag' determines which occurs first.
2262
2263 With prefix `C-M-' instead of `C-', the same keys (`C-M-mouse-2',
2264 `C-M-RET', `C-M-down', and so on) provide help about candidates.
2265
2266 Use `mouse-2', `RET', or `S-RET' to choose a candidate as the final
2267 destination, or `C-g' to quit.  This is an Icicles command - see
2268 command `icicle-mode'."
2269   (interactive)
2270   (let ((icicle-sort-orders-alist  (cons '("by position" .  icicle-cdr-lessp)
2271                                          icicle-sort-orders-alist))
2272         (icicle-sort-comparer      'icicle-cdr-lessp))
2273     (icicle-goto-marker-1 mark-ring)))
2274
2275 ;;;###autoload
2276 (defun icicle-goto-global-marker ()     ; Bound to `C-- C-x C-@', `C-- C-x C-SPC'.
2277   "Like `icicle-goto-marker', but visits global, not local, markers.
2278 If user option `icicle-show-multi-completion-flag' is non-nil, then
2279 each completion candidate is annotated (prefixed) with the name of the
2280 marker's buffer, to facilitate orientation."
2281   (interactive)
2282   (let ((icicle-list-nth-parts-join-string  "\t")
2283         (icicle-list-join-string            "\t")
2284         ;; $$$$$$ (icicle-list-end-string             "")
2285         (icicle-sort-orders-alist
2286          (cons '("by buffer, then by position" . icicle-part-1-cdr-lessp)
2287                icicle-sort-orders-alist))
2288         (icicle-sort-comparer               'icicle-part-1-cdr-lessp)
2289         (icicle-candidate-properties-alist  (and icicle-show-multi-completion-flag
2290                                                  '((1 (face icicle-candidate-part))))))
2291     (icicle-goto-marker-1 global-mark-ring)))
2292
2293 (defun icicle-goto-marker-1 (ring)
2294   "Helper function for `icicle-goto-marker', `icicle-goto-global-marker'.
2295 RING is the marker ring to use."
2296   (unwind-protect
2297        (let* ((global-ring-p
2298                (memq this-command '(icicle-goto-global-marker
2299                                     icicle-goto-global-marker-or-pop-global-mark)))
2300               (markers
2301                (if (and (not global-ring-p) (marker-buffer (mark-marker)))
2302                    (cons (mark-marker) (icicle-markers ring))
2303                  (icicle-markers ring)))
2304               (icicle-delete-candidate-object
2305                #'(lambda (cand)
2306                    (let ((mrkr+txt  (funcall icicle-get-alist-candidate-function cand)))
2307                      (move-marker (cdr mrkr+txt) nil))))
2308               (icicle-alternative-sort-comparer  nil)
2309               (icicle-last-sort-comparer         nil)
2310               (icicle-orig-buff                  (current-buffer)))
2311          (unless (consp markers)
2312            (error (if global-ring-p "No global markers" "No markers in this buffer")))
2313          (cond ((cdr markers)
2314                 (icicle-apply (mapcar #'(lambda (mrkr) (icicle-marker+text mrkr global-ring-p))
2315                                       markers)
2316                               #'icicle-goto-marker-1-action
2317                               'nomsg
2318                               (lambda (cand)
2319                                 (marker-buffer (cdr cand)))))
2320                ((= (point) (car markers)) (message "Already at marker: %d" (point)))
2321                (t
2322                 (icicle-goto-marker-1-action (icicle-marker+text (car markers) global-ring-p)))))
2323     (when (fboundp 'crosshairs-unhighlight) (crosshairs-unhighlight 'even-if-frame-switch))))
2324
2325 (defun icicle-goto-marker-1-action (cand)
2326   "Action function for `icicle-goto-marker-1'."
2327   (pop-to-buffer (marker-buffer (cdr cand)))
2328   (select-frame-set-input-focus (selected-frame))
2329   (goto-char (cdr cand))
2330   (unless (pos-visible-in-window-p) (recenter icicle-recenter))
2331   (when (fboundp 'crosshairs-highlight) (crosshairs-highlight)))
2332
2333 (defun icicle-marker+text (marker &optional globalp)
2334   "Cons of text line that includes MARKER with MARKER itself.
2335 If the marker is on an empty line, then text \"<EMPTY LINE>\" is used.
2336 If both optional argument GLOBALP and option
2337 `icicle-show-multi-completion-flag' are non-nil, then the text is
2338 prefixed by MARKER's buffer name."
2339   (with-current-buffer (marker-buffer marker)
2340     (save-excursion
2341       (goto-char marker)
2342       (let ((line  (let ((inhibit-field-text-motion  t)) ; Just to be sure, for `end-of-line'.
2343                      (buffer-substring-no-properties (save-excursion (beginning-of-line) (point))
2344                                                      (save-excursion (end-of-line) (point)))))
2345             (buff  (and globalp icicle-show-multi-completion-flag (buffer-name)))
2346             (help  (and (or (> icicle-help-in-mode-line-delay 0) ; Get it only if user will see it.
2347                             (and (boundp 'tooltip-mode) tooltip-mode))
2348                         (format "Line: %d, Char: %d" (line-number-at-pos) (point)))))
2349         (when (string= "" line) (setq line  "<EMPTY LINE>"))
2350         (when help
2351           (icicle-candidate-short-help help line)
2352           (when (and globalp icicle-show-multi-completion-flag)
2353             (icicle-candidate-short-help help buff)))
2354         (if (and globalp icicle-show-multi-completion-flag)
2355             (cons (list buff line) marker)
2356           (cons line marker))))))
2357
2358 (defun icicle-markers (ring)
2359   "Marks in mark RING that are in live buffers other than a minibuffer."
2360   (let ((markers  ()))
2361     (dolist (mkr  ring)
2362       (when (and (buffer-live-p (marker-buffer mkr))
2363                  (not (string-match "\\` \\*Minibuf-[0-9]+\\*\\'"
2364                                     (buffer-name (marker-buffer mkr)))))
2365         (push mkr markers)))
2366     markers))
2367
2368 ;;;###autoload
2369 (defun icicle-exchange-point-and-mark (&optional arg) ; Bound to `C-x C-x'.
2370   "`exchange-point-and-mark' or save a region or select a saved region.
2371 With no prefix arg, invoke `exchange-point-and-mark'.
2372 If you use library `Bookmark+', then you can use a prefix arg.
2373
2374  * Plain `C-u': select (activate) one or more bookmarked regions.
2375
2376  * Numeric prefix arg: bookmark (save) the active region using
2377    `icicle-bookmark-cmd'.
2378
2379    Arg < 0: Prompt for the bookmark name.
2380    Arg > 0: Do not prompt for the bookmark name.  Use the buffer name
2381             plus a prefix of the region text as the bookmark name.
2382    Arg = 0: Same as > 0, except do not overwrite any existing bookmark
2383             with the same name.
2384
2385 By default, Icicle mode remaps all key sequences that are normally
2386 bound to `exchange-point-and-mark' to
2387 `icicle-exchange-point-and-mark'.  If you do not want this remapping,
2388 then customize option `icicle-top-level-key-bindings'."
2389   (interactive "P")
2390   (let ((bplus  (featurep 'bookmark+)))
2391     (if (not arg)
2392         (call-interactively #'exchange-point-and-mark)
2393       (unless bplus (error "You must load library `Bookmark+' to use a prefix arg"))
2394       (cond ((atom arg)
2395              (unless (and transient-mark-mode mark-active (not (eq (mark) (point))))
2396                (error "Cannot bookmark inactive region: you must activate it first"))
2397              (icicle-bookmark-cmd (and (natnump (prefix-numeric-value arg)) 9)))
2398             (t
2399              (bookmark-maybe-load-default-file)
2400              (unless (consp (bmkp-region-alist-only)) (error "No bookmarked regions"))
2401              (call-interactively #'icicle-select-bookmarked-region))))))
2402
2403 ;;;###autoload
2404 (defun icicle-search-generic ()         ; Bound to `C-x `'.
2405   "Run `icicle-search-command'.  By default, this is `icicle-search'.
2406 In Compilation and Grep modes, this is `icicle-compilation-search'.
2407 In Comint, Shell, GUD, and Inferior Lisp modes, this is
2408    `icicle-comint-search'."
2409   (interactive)
2410   (call-interactively icicle-search-command))
2411
2412 ;;;###autoload
2413 (defun icicle-search (beg end scan-fn-or-regexp require-match ; Bound to `C-c `'.
2414                       &optional where &rest args)
2415   "Search for matches, with completion, cycling, and hit replacement.
2416 Search a set of contexts, which are defined interactively by
2417 specifying a regexp (followed by `RET').
2418
2419 After specifying the regexp that defines the search contexts, type
2420 input (e.g. regexp or other pattern) to match within the contexts.
2421 The contexts that match your input are available as completion
2422 candidates.  You can use `M-*' to further narrow the candidates,
2423 typing additional patterns to match.
2424
2425 By default, candidates are in order of buffer occurrence, but you can
2426 sort them in various ways using `C-,'.
2427
2428 You can replace individual matches with another string, as in
2429 `query-replace' or `query-replace-regexp'.  See the Icicles Search doc
2430 for more info.
2431
2432 Non-interactively, search can be for regexp matches or any other kind
2433 of matches.  Argument SCAN-FN-OR-REGEXP is the regexp to match, or it
2434 is a function that defines an alist of buffer zones to search.  You
2435 can navigate among the matching buffer zones (defined either as regexp
2436 matches or via function), called search \"contexts\", and you can
2437 match another regexp against the text in a search context.  See the
2438 end of this description for information about the other arguments.
2439
2440 If the search-context regexp contains regexp subgroups, that is,
2441 subexpressions of the form `\(...\)', then you are prompted for the
2442 subgroup to use to define the search contexts.  Subgroup 0 means the
2443 context is whatever matches the whole regexp.  Subgroup 1 means the
2444 context is whatever matches the first subgroup, and so on.  The
2445 subgroup number is the number of occurrences of `\(', starting at the
2446 beginning of the regexp.
2447
2448 Search respects `icicle-regexp-quote-flag' and
2449 `icicle-search-whole-word-flag'.  You can toggle these during search,
2450 by using `C-`' and `M-q', respectively.  If `icicle-regexp-quote-flag'
2451 is non-nil, then regexp special characters are quoted, so that they
2452 become non-special.  If `icicle-search-whole-word-flag' is non-nil,
2453 then whole-word searching is done.  (You can also use
2454 `\\[icicle-search-word]' to perform word search.)
2455
2456 For each of the predefined Icicles search commands, including for
2457 `icicle-search' itself, you can alternatively choose to search, not
2458 the search contexts as you define them, but the non-contexts, that is,
2459 the buffer text that is outside (in between) the search contexts as
2460 defined.  For example, if you use `icicle-search-thing' and you define
2461 sexps as the search contexts, then this feature lets you search the
2462 zones of text that are not within a sexp.
2463
2464 To do this, use `C-M-~' (`icicle-toggle-search-complementing-domain')
2465 during completion to turn on `icicle-search-complement-domain-p'.
2466 \(This is a toggle, and it affects only future search commands, not
2467 the current one.)
2468
2469
2470 Optional Behaviors: Prefix Argument
2471 -----------------------------------
2472
2473 By default, search only the current buffer.  Search the active region,
2474 or, if there is none, then search the entire buffer.
2475
2476 With a prefix argument, you can search multiple buffers, files, or
2477 bookmarks, as follows:
2478
2479 - With a plain prefix arg (`C-u'), search bookmarks.  This is the
2480 same as command `icicle-search-bookmarks-together'.  (To search
2481 bookmarks one at a time instead of together, use multi-command
2482 `icicle-search-bookmark'.)
2483
2484 - With a non-negative numeric prefix arg, search multiple buffers
2485 completely.  You are prompted for the buffers to search - all of each
2486 buffer is searched.  Any existing buffers can be chosen.  If the
2487 prefix arg is 99, then only buffers visiting files are candidates.
2488 This is the same as command `icicle-search-buffer'.
2489
2490 - With a negative numeric prefix arg, search multiple files
2491 completely.  You are prompted for the files to search - all of each
2492 file is searched.  Any existing files in the current directory can be
2493 chosen.  This is the same as command `icicle-search-file'.
2494
2495
2496 Navigation and Help
2497 -------------------
2498
2499 The use of completion for this command is special.  It is not unusual
2500 in this context to have multiple completion candidates that are
2501 identical - only the positions of their occurrences in the search
2502 buffer(s) differ.  In that case, you cannot choose one simply by
2503 completing it in the minibuffer, because the destination would be
2504 ambiguous.  That is, simply completing your input and entering the
2505 completion with `RET' will not take you to its occurrence in the
2506 search buffer, unless it is unique.
2507
2508 Instead, choose search hits to visit using any of the candidate-action
2509 keys: `C-RET', `C-mouse-2', `C-down', `C-up', `C-next', `C-prior',
2510 `C-end', and `C-home'.  All but the first two of these cycle among the
2511 search hits.  The current candidate in `*Completions*' corresponds to
2512 the current location visited (it is not off by one, as is usually the
2513 case in Icicles).
2514
2515 As always, the `C-M-' keys provide help on individual candidates:
2516 `C-M-RET', `C-M-mouse-2', `C-M-down', `C-M-up', `C-M-next',
2517 `C-M-prior', `C-M-end', and `C-M-home'.  For `icicle-search', they
2518 indicate the buffer and position of the search hit.
2519
2520 You can cycle among candidates without moving to their occurrences in
2521 the search buffer, using `down', `up', `next', `prior', `end', or
2522 `home' (no `C-' modifier).
2523
2524
2525 Highlighting
2526 ------------
2527
2528 In the search buffer (that is, where the hits are), `icicle-search'
2529 does the following:
2530
2531 - Highlights the current match (buffer zone) for the initial (context)
2532   regexp, using face `icicle-search-main-regexp-current'.
2533
2534 - Highlights the first `icicle-search-highlight-threshold' context
2535   matches, using face `icicle-search-main-regexp-others'.
2536
2537 - Highlights 1-8 context levels, within each search context.  This
2538   happens only if your initial (context) regexp has \\(...\\) groups
2539   and option `icicle-search-highlight-context-levels-flag' is non-nil.
2540
2541 - Highlights the match for your current input, using face
2542   `icicle-search-current-input'.  Highlights all such matches if
2543   option `icicle-search-highlight-all-current-flag' is non-nil;
2544   otherwise, highlights just the currently visited match.
2545   You can toggle this option using `C-^'.
2546
2547 If user option `icicle-search-cleanup-flag' is non-nil (the default),
2548 then all search highlighting is removed from the search buffer when
2549 you are finished searching.  If it is nil, then you can remove this
2550 highlighting later using command `icicle-search-highlight-cleanup'.
2551 You can toggle `icicle-search-cleanup-flag' during Icicles search
2552 using `C-.' in the minibuffer.
2553
2554
2555 `*Completions*' Display
2556 -----------------------
2557
2558 In buffer `*Completions*', in addition to eliding the common match
2559 \(option `icicle-hide-common-match-in-Completions-flag', toggled
2560 anytime using `C-x .' - no prefix arg), you can elide all lines of a
2561 multi-line candidate that do not match your current minibuffer input.
2562 This hiding is governed by option
2563 `icicle-hide-non-matching-lines-flag', which you can toggle anytime
2564 during completion using `C-u C-x .' (this is not specfic to Icicles
2565 search).  This can be useful when candidates are very long, as can be
2566 the case for instance for the `icicle-imenu-*-full' commands.
2567
2568
2569 Search and Replace
2570 ------------------
2571
2572 You can replace the current search match by using any of the
2573 alternative action keys: `C-S-RET', `C-S-mouse-2' (in
2574 `*Completions*'), `C-S-down', `C-S-up', `C-S-next', `C-S-prior',
2575 `C-S-end', and `C-S-home'.  You can use `M-|' to replace all matches
2576 at once.  (And remember that you can activate the region to limit the
2577 search-and-replace space.)
2578
2579
2580 At the first use of any of these, you are prompted for the replacement
2581 string; it is used thereafter, or until you use `M-,'
2582 \(`icicle-search-define-replacement') to change it (anytime).
2583
2584 Unlike `query-replace', you need not visit search matches successively
2585 or exhaustively.  You can visit and replace selected matches in any
2586 order.
2587
2588 What is meant here by a \"search match\"?  It can be either an entire
2589 search context or just a part of the context that your current
2590 minibuffer input matches.
2591
2592 `C-,' toggles option `icicle-search-replace-whole-candidate-flag'.  By
2593 default, the entire current search context is replaced, that is,
2594 whatever matches the context regexp that you entered initially using
2595 `RET'.  However, you can use `C-,' anytime during searching to toggle
2596 between this default behavior and replacement of whatever your current
2597 minibuffer input matches.
2598
2599 Remember this:
2600
2601  - If `icicle-search-replace-whole-candidate-flag' is non-nil, then
2602    the granularity of replacement is a complete search context.  In
2603    this case, replacement behaves similarly to `query-replace-regexp'.
2604    You can still use minibuffer input to filter the set of search
2605    contexts, but replacement is on a whole-context basis.
2606
2607  - If `icicle-search-replace-whole-candidate-flag' is nil, then you
2608    can replace multiple input matches separately within a search
2609    context (using `C-S-RET').  This behavior is unique to Icicles.
2610    You cannot, however skip over one input match and replace the next
2611    one in the same context - `C-S-RET' always replaces the first
2612    available match.
2613
2614 If `icicle-search-replace-whole-candidate-flag' is non-nil, then you
2615 can use the navigational alternative action keys, `C-S-down',
2616 `C-S-up', `C-S-next', `C-S-prior', `C-S-end', and `C-S-home',
2617 repeatedly to replace successive search contexts.  At the buffer
2618 limits, these commands wraps around to the other buffer limit (last
2619 search context to first, and vice versa).
2620
2621 Search traversal using these go-to-next-context-and-replace keys is
2622 always by search context, not by individual input match.  This means
2623 that you cannot use these keys to replace input matches within a
2624 search context (except for the first such match, if
2625 `icicle-search-replace-whole-candidate-flag' is nil).
2626
2627 If your input matches multiple parts of a search context, and you want
2628 to replace these in order, then use `C-S-RET' repeatedly.  You can
2629 traverse all matches of your input in the order they appear in the
2630 buffer by repeating `C-S-RET' (provided the replacement text does not
2631 also match your input - see below).  At the buffer limits, repeating
2632 `C-S-RET' wraps around too.
2633
2634 `C-S-RET' always replaces the first input match in the current search
2635 context or, if there are no matches, then the first input match in the
2636 next context.  This behavior has these important consequences:
2637
2638 * If you repeat `C-S-RET' and the previous replacement no longer
2639   matches your input, then `C-S-RET' moves on to the next input match
2640   (which is now the first one) and replaces that.  This is why you can
2641   usually just repeat `C-S-RET' to successively replaces matches of
2642   your input, including from one context to the next.
2643
2644 * If, on the other hand, after replacement the text still matches your
2645   input, then repeating `C-S-RET' will just replace that match.
2646   For example, if you replace the input match `ab' by `abcd', then
2647   repeating `C-S-RET' produces `abcd', then `abcdcd', then `abcdcd'...
2648
2649 * You cannot replace an input match, skip the next match, and then
2650   replace the following one, all in the same context.  You can,
2651   however, replace some matches and then skip (e.g. `C-next') to the
2652   next context.
2653
2654 What your input matches, hence what gets replaced if
2655 `icicle-search-replace-whole-candidate-flag' is nil, depends on a few
2656 Icicles options:
2657
2658  - `icicle-regexp-quote-flag' determines whether to use regexp
2659    matching or literal matching.
2660
2661  - `icicle-search-highlight-all-current-flag',
2662    `icicle-expand-input-to-common-match-flag' and
2663    `icicle-search-replace-common-match-flag' together determine
2664    whether to replace exactly what your input matches in the current
2665    search hit or the expanded common match (ECM) of your input among
2666    all search hits.  If any of these options is nil, then your exact
2667    input match is replaced; if they are all non-nil, then the ECM is
2668    replaced.
2669
2670 Finally, the replacement string can be nearly anything that is allowed
2671 as a replacement by `query-replace-regexp'.  In Emacs 22 or later,
2672 this includes Lisp sexp evaluation via `\,' and constructs such as
2673 `\#' and `\N' (back references).  You can also use `\?', but it is not
2674 very useful - you might as well use `M-,' instead, to change the
2675 replacement text.
2676
2677
2678 Using Regexps
2679 -------------
2680
2681 At any time, you can use `\\<minibuffer-local-completion-map>\
2682 \\[icicle-insert-string-from-variable]' (command
2683 `icicle-insert-string-from-variable') to insert text (e.g. a regexp)
2684 from a variable into the minibuffer.  For example, you can search for
2685 ends of sentences by using `C-u \\[icicle-insert-string-from-variable]' and choosing variable
2686 `sentence-end' as the variable.  And you can use
2687 `\\[icicle-save-string-to-variable]' to save a string to a variable
2688 for later use by `\\[icicle-insert-string-from-variable]'.
2689
2690 When employed with useful regexps, `C-=' can turn `icicle-search' into
2691 a general navigator or browser of code, mail messages, and many other
2692 types of buffer.  Imenu regexps work fine, for example - command
2693 `icicle-imenu' simply uses `icicle-search' this way.  See
2694 `icicle-insert-string-from-variable' for more tips on inserting
2695 regexps from variables.
2696
2697
2698 Additional Information
2699 ----------------------
2700
2701 If user option `icicle-show-multi-completion-flag' is non-nil, then
2702 each candidate is annotated with the name of the buffer where the
2703 search hit occurs, to facilitate orientation.  Note that even when the
2704 value is nil, you can use `C-M-mouse-2' and so on to see the buffer
2705 name, as well as the position of the hit in the buffer.
2706
2707 Completion is lax if `icicle-show-multi-completion-flag' is non-nil;
2708 otherwise, it is strict.
2709
2710 After you visit a completion candidate, the hooks in variable
2711 `icicle-search-hook' are run.
2712
2713 `icicle-search' overrides `icicle-ignore-space-prefix-flag', binding
2714 it to nil, so that candidates with initial spaces can be matched.
2715
2716 `icicle-search' sets `icicle-search-final-choice' to the final user
2717 choice, which might not be one of the search candidates if
2718 REQUIRE-MATCH is nil.
2719
2720
2721 Non-Interactive Use
2722 -------------------
2723
2724 Function `icicle-search' is not only a powerful command, it is also a
2725 building block for creating your own Icicles search-and-replace
2726 commands.  When called non-interactively, these are the
2727 `icicle-search' arguments:
2728
2729 BEG is the beginning of the region to search; END is the end.
2730 SCAN-FN-OR-REGEXP: Regexp or function that determines the set of
2731   initial candidates (match zones).  If a function, it is passed, as
2732   arguments, the buffer to search, the beginning and end of the search
2733   region in that buffer, and ARGS.
2734 REQUIRE-MATCH is passed to `completing-read'.
2735 Optional arg WHERE is a list of bookmarks, buffers, or files to be
2736   searched.  If nil, then search only the current buffer or region.
2737   (To search bookmarks you must also use library `Bookmark+').
2738 ARGS are arguments that are passed to function SCAN-FN-OR-REGEXP.
2739
2740 Note that if SCAN-FN-OR-REGEXP is a regexp string, then function
2741 `icicle-search-regexp-scan' is used to determine the set of match
2742 zones.  You can limit hits to regexp matches that also satisfy a
2743 predicate, by using `(PREDICATE)' as ARGS: PREDICATE is then passed to
2744 `icicle-search-regexp-scan' as its PREDICATE argument.
2745
2746 This command is intended for use only in Icicle mode."
2747   (interactive `(,@(icicle-region-or-buffer-limits)
2748                  ,(if icicle-search-whole-word-flag
2749                       (icicle-search-read-word)
2750                       (icicle-search-read-context-regexp))
2751                  ,(not icicle-show-multi-completion-flag)
2752                  ,(icicle-search-where-arg)))
2753   (setq icicle-search-context-regexp  (and (stringp scan-fn-or-regexp) scan-fn-or-regexp))
2754   (let ((icicle-candidate-action-fn                  (or icicle-candidate-action-fn
2755                                                          'icicle-search-action))
2756         (icicle-candidate-help-fn                    'icicle-search-help)
2757         (icicle-all-candidates-list-alt-action-fn
2758          (or icicle-all-candidates-list-alt-action-fn 'icicle-search-replace-all-search-hits))
2759         (icicle-candidate-alt-action-fn
2760          (or icicle-candidate-alt-action-fn 'icicle-search-replace-search-hit))
2761         (icicle-scan-fn-or-regexp           scan-fn-or-regexp) ; Used free in `M-,'.
2762         (icicle-update-input-hook           (list 'icicle-search-highlight-all-input-matches))
2763         (icicle-search-ecm                  nil)
2764         (icicle-searching-p                 t)
2765         (icicle-search-replacement          nil)
2766         (icicle-current-input               "")
2767         (icicle-list-nth-parts-join-string  "\t")
2768         (icicle-list-join-string            "\t")
2769         ;; $$$$$$ (icicle-list-end-string             "")
2770         (icicle-list-use-nth-parts          '(1))
2771         (icicle-sort-comparer               nil)
2772
2773         ;; Alternative: If we used `icicle-search-replace-cand-in-alist', then we would inhibit
2774         ;; sorting, because we would be depending on the alist order.
2775         ;;    (icicle-inhibit-sort-p          t)
2776
2777         (icicle-no-match-hook               icicle-no-match-hook)
2778         (completion-ignore-case             case-fold-search)
2779         (replace-count                      0)) ; Defined in `replace.el'.  Used for replacement.
2780     (add-hook 'icicle-no-match-hook (lambda () (when (overlayp icicle-search-current-overlay)
2781                                                  (delete-overlay icicle-search-current-overlay))))
2782     (setq icicle-search-final-choice
2783           (icicle-explore #'(lambda () (icicle-search-define-candidates beg end scan-fn-or-regexp
2784                                                                         require-match where args))
2785                           #'icicle-search-final-act #'icicle-search-quit-or-error
2786                           #'icicle-search-quit-or-error #'icicle-search-cleanup
2787                           "Choose an occurrence: " nil require-match nil 'icicle-search-history))))
2788
2789 ;; This is the same as `region-or-buffer-limits' in `misc-fns.el'.
2790 (defun icicle-region-or-buffer-limits ()
2791   "Return the start and end of the region as a list, smallest first.
2792 If the region is not active or is empty, then use bob and eob."
2793   (if (or (not mark-active) (null (mark)) (= (point) (mark)))
2794       (list (point-min) (point-max))
2795     (if (< (point) (mark)) (list (point) (mark)) (list (mark) (point)))))
2796
2797 (defun icicle-search-read-context-regexp (&optional prompt pred init hist def i-i-m)
2798   "Read context regexp and determine `icicle-search-context-level'.
2799 Read the regexp using completion against previous regexp input.
2800 The arguments are for use by `completing-read' to read the regexp.
2801  HIST (or `regexp-history' if HIST is nil) is used for the
2802  `completing-read' COLLECTION argument.
2803  The REQUIRE-MATCH arg to `completing-read' is nil.
2804  A default prompt is used if PROMPT is nil."
2805   (setq hist    (or hist 'regexp-history)
2806         prompt  (or prompt (format "Search %swithin contexts (regexp): "
2807                                    (if icicle-search-complement-domain-p "*NOT* " ""))))
2808   (let* ((icicle-candidate-action-fn  nil)
2809          (icicle-candidate-help-fn    nil)
2810          (regexp                      (icicle-completing-read-history
2811                                        prompt 'regexp-history pred init def i-i-m)))
2812     (while (string= "" regexp)
2813       (message "Regexp cannot be empty.  Try again...") (sit-for 2)
2814       (setq regexp  (icicle-completing-read-history prompt 'regexp-history pred init def i-i-m)))
2815     (setq prompt                       "Subgroup to use as search context [0, 1, 2,...]: "
2816           icicle-search-context-level  (if (string-match "\\\\(" regexp)
2817                                            (truncate (if (fboundp 'read-number)
2818                                                          (read-number prompt 0)
2819                                                        (read-from-minibuffer ; Hope for a number.
2820                                                         prompt nil nil nil nil 0)))
2821                                          0))
2822     regexp))
2823
2824 (defun icicle-search-where-arg ()
2825   "Return WHERE arg for `icicle-search*' commands, based on prefix arg."
2826   (cond ((consp current-prefix-arg)
2827          (unless (require 'bookmark+ nil t) (error "This requires library `Bookmark+'"))
2828          (message "Searching multiple bookmarks...") (sit-for 1)
2829          (let ((icicle-show-Completions-initially-flag  t)
2830                (icicle-bookmark-types                   '(all)))
2831            (save-selected-window (icicle-bookmark-list))))
2832         ((wholenump current-prefix-arg)
2833          (message "Searching multiple buffers...") (sit-for 1)
2834          (icicle-search-choose-buffers (= 99 (prefix-numeric-value current-prefix-arg))))
2835         (current-prefix-arg
2836          (message "Searching multiple files...") (sit-for 1)
2837          (let ((icicle-show-Completions-initially-flag  t))
2838            (save-selected-window (icicle-file-list))))
2839         (t nil)))
2840
2841 (defun icicle-search-choose-buffers (files-only-p)
2842   "Choose multiple buffers to search.
2843 FILES-ONLY-P non-nil means that only buffers visiting files are
2844 candidates."
2845   (let ((icicle-show-Completions-initially-flag  t))
2846     (mapcar #'get-buffer (let ((icicle-buffer-require-match-flag  'partial-match-ok)
2847                                (current-prefix-arg                files-only-p))
2848                            (save-selected-window (icicle-buffer-list))))))
2849
2850 ;;; $$$$$$ (defun icicle-search-read-word ()
2851 ;;;   "Read a word to search for (whole-word search).
2852 ;;; Regexp special characters within the word are escaped (quoted)."
2853 ;;;   (setq icicle-search-context-level  0)
2854 ;;;   (concat "\\b"
2855 ;;;           (regexp-quote (icicle-completing-read-history "Search for whole word: "
2856 ;;;                                                         'icicle-search-history))
2857 ;;;           "\\b"))
2858
2859 (defun icicle-search-read-word ()
2860   "Read a word to search for (whole-word search).
2861 The search string is regarded as a whole word, but a \"word\" here can
2862 contain embedded strings of non word-constituent chars (they are
2863 skipped over, when matching, included in the match), and any leading
2864 or trailing word-constituent chars in the search string are dropped
2865 \(ignored for matching, not included in the match): matches begin and
2866 end on a word boundary."
2867   (setq icicle-search-context-level  0)
2868   (concat "\\b" (replace-regexp-in-string
2869                  "\\W+" "\\W+" (replace-regexp-in-string
2870                                 "^\\W+\\|\\W+$" ""
2871                                 (icicle-completing-read-history "Search for whole word: "
2872                                                                 'icicle-search-history))
2873                  nil t)
2874           "\\b"))
2875
2876 (defun icicle-search-final-act ()
2877   "Go to the final search hit choice, then run `icicle-search-hook'.
2878 The hit's frame is raised and selected."
2879   (let* ((marker  (cdr icicle-explore-final-choice-full))
2880          (buf     (marker-buffer marker)))
2881     (unless (bufferp buf) (error "No such buffer: %s" buf))
2882     (pop-to-buffer buf)
2883     (raise-frame)
2884     (goto-char (marker-position marker))
2885     (unless (pos-visible-in-window-p) (recenter icicle-recenter))
2886     (select-frame-set-input-focus (selected-frame))
2887     (run-hooks 'icicle-search-hook)))
2888
2889 ;; Free vars here: `icicle-orig-pt-explore', `icicle-orig-win-explore' are bound in `icicle-explore'.
2890 (defun icicle-search-quit-or-error ()
2891   "Return to the starting point."
2892   (when (window-live-p icicle-orig-win-explore)
2893     (select-window icicle-orig-win-explore)
2894     (goto-char icicle-orig-pt-explore)))
2895
2896 ;; Free vars here: `icicle-orig-win-explore' is bound in `icicle-explore'.
2897 (defun icicle-search-cleanup ()
2898   "Clean up search highlighting, if `icicle-search-cleanup-flag'.
2899 Select original window."
2900   (when icicle-search-cleanup-flag (icicle-search-highlight-cleanup))
2901   (when (window-live-p icicle-orig-win-explore)
2902     (select-window icicle-orig-win-explore)
2903     (select-frame-set-input-focus (selected-frame))))
2904
2905 (defun icicle-search-define-candidates (beg end scan-fn-or-regexp require-match where args)
2906   "Define completion candidates for `icicle-search'.
2907 The arguments are the same as for `icicle-search'."
2908   (when (and icicle-regexp-quote-flag
2909              (not icicle-search-whole-word-flag)
2910              (stringp scan-fn-or-regexp))
2911     (setq scan-fn-or-regexp  (regexp-quote scan-fn-or-regexp)))
2912   (cond ((and (consp where) (bufferp (car where))) ; List of buffers - search buffers.
2913          (dolist (buf  where)
2914            (icicle-search-define-candidates-1 buf nil nil scan-fn-or-regexp args)))
2915         ((and (consp where) (stringp (car where)) ; List of files - search files.
2916               (file-exists-p (car where)))
2917          (dolist (file  where)
2918            (icicle-search-define-candidates-1 (find-file-noselect file 'nowarn) nil nil
2919                                               scan-fn-or-regexp args)))
2920         ((consp where)                  ; Search all bookmarked regions.
2921          (unless (require 'bookmark+ nil t) (error "This requires library `Bookmark+'"))
2922          (let ((non-existent-buffers  ())
2923                buf+beg buf beg end)
2924            (dolist (bmk  where)
2925              (setq buf+beg  (bookmark-jump-noselect bmk)
2926                    buf      (car buf+beg)
2927                    beg      (cdr buf+beg)
2928                    end      (bmkp-get-end-position bmk))
2929              (if (bufferp buf)
2930                  (icicle-search-define-candidates-1 buf beg end scan-fn-or-regexp args)
2931                (push buf non-existent-buffers)))
2932            (when non-existent-buffers
2933              (message "Skipping regions in non-existent buffers: `%s'"
2934                       (mapconcat #'identity (icicle-remove-duplicates non-existent-buffers)
2935                                  "', `"))
2936              (sit-for 3))))
2937         (t                              ; Search this buffer only.
2938          (icicle-search-define-candidates-1 nil beg end scan-fn-or-regexp args)))
2939   (when (and icicle-candidates-alist  (null (cdr icicle-candidates-alist)))
2940     (message "Moving to sole candidate") (sit-for 1.5))
2941   (unless icicle-candidates-alist  (if (functionp scan-fn-or-regexp)
2942                                        (error "No search hits")
2943                                      (error "No search hits for `%s'" scan-fn-or-regexp)))
2944   (setq mark-active  nil))              ; Remove any region highlighting, so we can see search hits.
2945
2946 (defun icicle-search-define-candidates-1 (buffer beg end scan-fn-or-regexp args)
2947   "Helper function for `icicle-search-define-candidates'.
2948 BUFFER is a buffer to scan for candidates.
2949 The other arguments are the same as for `icicle-search'."
2950   (if (functionp scan-fn-or-regexp)
2951       (apply scan-fn-or-regexp buffer beg end args)
2952     (apply 'icicle-search-regexp-scan buffer beg end scan-fn-or-regexp args)))
2953
2954 (defun icicle-search-regexp-scan (buffer beg end regexp &optional predicate action)
2955   "Scan BUFFER for REGEXP, pushing hits onto `icicle-candidates-alist'.
2956 If BUFFER is nil, scan the current buffer.
2957 If BEG and END are non-nil, scan only between positions BEG and END.
2958 If REGEXP has subgroups, then use what the Nth subgroup matches as the
2959  search context (hit), where N = `icicle-search-context-level'.
2960  If N=0, then use the overall match of REGEXP as the search context.
2961 PREDICATE is nil or a boolean function that takes these arguments:
2962   - the search-context string
2963   - a marker at the end of the search-context
2964 If PREDICATE is non-nil, then push only the hits for which it holds.
2965
2966 Highlight the matches in face `icicle-search-main-regexp-others'."
2967   (setq regexp  (or regexp (icicle-search-read-context-regexp)))
2968   (let ((add-bufname-p  (and buffer icicle-show-multi-completion-flag))
2969         (temp-list      ())
2970         (last-beg       nil))
2971     (unless buffer (setq buffer  (current-buffer)))
2972     (when (bufferp buffer)     ; Do nothing if BUFFER is not a buffer.
2973       (with-current-buffer buffer
2974         (unless (and beg end) (setq beg  (point-min)
2975                                     end  (point-max)))
2976         (icicle-condition-case-no-debug icicle-search-regexp-scan
2977             (save-excursion
2978               (goto-char (setq last-beg  beg))
2979               (while (and beg (< beg end) (not (eobp))
2980                           (progn
2981                             (while (and (setq beg  (re-search-forward regexp end t))
2982                                         (eq last-beg beg)
2983                                         (not (eobp)))
2984                               ;; Matched again, same place.  Advance 1 char.
2985                               (forward-char) (setq beg  (1+ beg)))
2986                             ;; Stop if no more match.  But if complementing then continue until eobp.
2987                             (or beg  icicle-search-complement-domain-p)))
2988                 (unless (or (not beg) (match-beginning icicle-search-context-level))
2989                   (error "Search context has no subgroup of level %d - try a lower number"
2990                          icicle-search-context-level))
2991                 (let* ((hit-beg     (if icicle-search-complement-domain-p
2992                                         last-beg
2993                                       (match-beginning icicle-search-context-level)))
2994                        (hit-end     (if icicle-search-complement-domain-p
2995                                         (if beg
2996                                             (match-beginning icicle-search-context-level)
2997                                           (point-max))
2998                                       (match-end icicle-search-context-level)))
2999                        (IGNORE      (when action
3000                                       (save-excursion
3001                                         (funcall action)
3002                                         (setq hit-end  (point)))))
3003                        (hit-string  (buffer-substring-no-properties hit-beg hit-end))
3004                        end-marker)
3005                   (when (and (not (string= "" hit-string)) ; Do nothing if empty hit.
3006                              (setq end-marker  (copy-marker hit-end))
3007                              (or (not predicate)
3008                                  (save-match-data (funcall predicate hit-string end-marker))))
3009                     (icicle-candidate-short-help
3010                      (concat (and add-bufname-p
3011                                   (format "Buffer: `%s', "
3012                                           (buffer-name (marker-buffer end-marker))))
3013                              (format "Position: %d, Length: %d"
3014                                      (marker-position end-marker) (length hit-string)))
3015                      hit-string)
3016                     ;; Add whole candidate to `temp-list'.  Whole candidate is
3017                     ;; (`hit-string' . `end-marker') or ((`hit-string' BUFNAME) . `end-marker').
3018                     (push (cons (if add-bufname-p
3019                                     (list hit-string
3020                                           (let ((string  (copy-sequence (buffer-name))))
3021                                             (put-text-property 0 (length string) 'face
3022                                                                'icicle-candidate-part string)
3023                                             string))
3024                                   hit-string)
3025                                 end-marker)
3026                           temp-list)
3027                     ;; Highlight search context in buffer.
3028                     (when (<= (+ (length temp-list) (length icicle-candidates-alist))
3029                               icicle-search-highlight-threshold)
3030                       (let ((ov  (make-overlay hit-beg hit-end)))
3031                         (push ov icicle-search-overlays)
3032                         (overlay-put ov 'priority 200) ; > ediff's 100+, < isearch-overlay's 1001.
3033                         (overlay-put ov 'face 'icicle-search-main-regexp-others)))))
3034                 (setq last-beg  beg))
3035               (setq icicle-candidates-alist  (append icicle-candidates-alist (nreverse temp-list))))
3036           (quit (when icicle-search-cleanup-flag (icicle-search-highlight-cleanup)))
3037           (error (when icicle-search-cleanup-flag (icicle-search-highlight-cleanup))
3038                  (error "%s" (error-message-string icicle-search-regexp-scan))))))))
3039
3040 ;; Free var here: `icicle-search-ecm' is bound in `icicle-search'.
3041 (defun icicle-search-highlight-all-input-matches (&optional input)
3042   "Highlight, inside each search context, what INPUT matches."
3043   (save-excursion
3044     ;; Update by deleting (if it exists) and then creating.
3045     ;; If a single overlay exists, it means that the user just changed
3046     ;; `icicle-search-highlight-threshold' to non-zero.
3047     ;; Otherwise, it's nil or a list of overlays.
3048     (when (overlayp icicle-search-refined-overlays)
3049       (delete-overlay icicle-search-refined-overlays)
3050       (setq icicle-search-refined-overlays  ()))
3051     (while icicle-search-refined-overlays
3052       (delete-overlay (car icicle-search-refined-overlays))
3053       (setq icicle-search-refined-overlays  (cdr icicle-search-refined-overlays))))
3054   (when icicle-search-highlight-all-current-flag
3055     (setq input  (or input icicle-current-input))
3056     (unless (or (string= "" input) (null icicle-search-overlays))
3057       (let ((hits  ())
3058             pos)
3059         (save-excursion
3060           (dolist (ov  icicle-search-overlays)
3061             (set-buffer (overlay-buffer ov))
3062             (unless (equal (overlay-start ov) (overlay-end ov))
3063               (save-restriction         ; Search within the current search context.
3064                 (narrow-to-region (overlay-start ov) (overlay-end ov))
3065                 (goto-char (point-min))
3066                 (when (condition-case nil (re-search-forward input nil 'move-to-end) (error nil))
3067                   (push (buffer-substring-no-properties (point-min) (point-max)) hits)))))
3068           (when (and icicle-expand-input-to-common-match-flag  hits)
3069             (setq icicle-search-ecm  (icicle-expanded-common-match input hits))
3070             (when (string= "" icicle-search-ecm) (setq icicle-search-ecm  nil)))
3071           (when (or icicle-search-ecm (and input (not (string= "" input))))
3072             (dolist (ov  icicle-search-overlays)
3073               (set-buffer (overlay-buffer ov))
3074               (unless (equal (overlay-start ov) (overlay-end ov))
3075                 (save-restriction       ; Search within the current search context.
3076                   (narrow-to-region (overlay-start ov) (overlay-end ov))
3077                   (when (member (buffer-substring-no-properties (point-min) (point-max)) hits)
3078                     (goto-char (setq pos  (point-min)))
3079                     (save-match-data
3080                       (while (and (not (eobp))
3081                                   (condition-case nil
3082                                       (re-search-forward (or icicle-search-ecm input)
3083                                                          nil 'move-to-end)
3084                                     (error nil)))
3085                         (if (or (and (equal (match-beginning 0) (match-end 0)) (not (eobp)))
3086                                 (equal (point) pos))
3087                             (forward-char)
3088                           (setq pos  (point))
3089                           (unless (equal (match-beginning 0) (match-end 0))
3090                             (setq ov  (make-overlay (match-beginning 0) (match-end 0)))
3091                             (push ov icicle-search-refined-overlays)
3092                             (overlay-put ov 'priority 220)
3093                             (overlay-put ov 'face 'icicle-search-current-input)))))))))))))))
3094
3095 (defun icicle-search-replace-search-hit (candidate) ; Bound to `C-S-RET' (`icicle-search').
3096   "Replace search hit CANDIDATE with `icicle-search-replacement'."
3097   ;; NOTE: We allow side effects during replacement.
3098   ;; In particular, `icicle-completion-candidates', `icicle-candidate-nb', and `icicle-last-input'
3099   ;; can change.
3100
3101   (let (;; (icicle-candidate-nb          icicle-candidate-nb)
3102         ;; (icicle-completion-candidates icicle-completion-candidates)
3103         ;; (icicle-last-input            icicle-last-input)
3104         (icicle-last-completion-command  icicle-last-completion-command)
3105         (compl-win                       (get-buffer-window "*Completions*" 0)))
3106     (unless (or icicle-candidate-nb icicle-all-candidates-action)
3107       (error "No current candidate.  Cycle or complete to get to a candidate"))
3108     (unless icicle-search-replacement
3109       (icicle-search-define-replacement)
3110       (when (and compl-win icicle-completion-candidates)
3111         (with-output-to-temp-buffer "*Completions*"
3112           (display-completion-list icicle-completion-candidates)))))
3113   (setq icicle-candidate-nb  (or icicle-candidate-nb 0)) ; Replace-all has nil, so use 0.
3114   (funcall icicle-candidate-action-fn candidate icicle-search-replacement)) ; Call with second arg.
3115
3116 (defun icicle-search-replace-all-search-hits (candidates) ; Bound to `M-|' (for `icicle-search').
3117   "Default alternative list action function for `icicle-search'.
3118 CANDIDATES is a list of search-hit strings.  They are all matched by
3119 the initial regexp (context regexp)."
3120   (let ((icicle-last-completion-command  icicle-last-completion-command)
3121         (compl-win                       (get-buffer-window "*Completions*" 0)))
3122 ;;; $$$$$$ These are now avoided always for all candidates, in `icicle-all-candidates-action-1'.
3123 ;;;     (icicle-minibuffer-message-ok-p  nil) ; Avoid delays from `icicle-msg-maybe-in-minibuffer'.
3124 ;;;     (icicle-help-in-mode-line-delay  0)) ; Avoid delays for individual candidate help.
3125     (unless icicle-search-replacement
3126       (icicle-search-define-replacement)
3127       (when (and compl-win icicle-completion-candidates)
3128         (with-output-to-temp-buffer "*Completions*"
3129           (display-completion-list icicle-completion-candidates))))
3130     (dolist (cand+mrker  (mapcar icicle-get-alist-candidate-function candidates))
3131       (icicle-search-action-1 cand+mrker icicle-search-replacement)))
3132   (select-window (minibuffer-window))
3133   (select-frame-set-input-focus (selected-frame)))
3134
3135 (defun icicle-search-action (string &optional replace-string) ; Bound to `C-RET' (`icicle-search').
3136   "Default completion action function for `icicle-search'.
3137 STRING is a search-hit string.  It is matched by the initial regexp
3138 \(context regexp).
3139
3140 1. Move to the STRING occurrence in original buffer.  Highlight it.
3141 2. If `icicle-search-highlight-threshold' is zero, highlight what the
3142    current input matches, inside the STRING occurrence.
3143 3. If REPLACE-STRING is non-nil, replace the current match with it.
3144    If `icicle-search-replace-whole-candidate-flag' is non-nil, replace
3145    the entire STRING occurrence.  Otherwise, replace only the part
3146    that matches the current input.
3147 4. Highlight the current candidate in `*Completions*'.
3148
3149    Note: The replacement can be nearly anything allowed as a
3150    replacement by `query-replace-regexp', including Lisp-evaluation
3151    constructs (`\,...')."
3152   (prog1
3153       (let* ((icicle-whole-candidate-as-text-prop-p  t)
3154              ;; Alternative: If we used `icicle-search-replace-cand-in-alist', then we would bind that
3155              ;; to nil to force using the alist, because we would be performing side effects on it.
3156              (cand+mrker  (funcall icicle-get-alist-candidate-function string)))
3157         (icicle-search-action-1 cand+mrker replace-string))
3158     (select-window (minibuffer-window))
3159     (select-frame-set-input-focus (selected-frame))))
3160
3161 ;; Free vars here: `icicle-orig-win-explore' is bound in `icicle-explore'.
3162 (defun icicle-search-action-1 (cand+mrker &optional replace-string)
3163   "Same as `icicle-search-action', but using full candidate, not string.
3164 CAND+MRKER is a full alist completion-candidate entry, not just a
3165 display string as in `icicle-search-action'."
3166   (when icicle-completion-candidates
3167     (icicle-condition-case-no-debug icicle-search-action-1
3168         (progn
3169           ;; Move cursor to the match in the original buffer and highlight it.
3170           (let* ((candidate                    (if (consp (car-safe cand+mrker))
3171                                                    (car-safe (car-safe cand+mrker))
3172                                                  (car-safe cand+mrker)))
3173                  (marker                       (cdr-safe cand+mrker))
3174                  (icicle-search-in-context-fn  (or icicle-search-in-context-fn
3175                                                    'icicle-search-in-context-default-fn)))
3176             (when (get-buffer-window (marker-buffer marker) 0)
3177               (setq icicle-other-window  (get-buffer-window (marker-buffer marker) 0)))
3178             (unless marker (error "No such occurrence"))
3179             (icicle-condition-case-no-debug icicle-search-action-1-save-window
3180                 (save-selected-window
3181                   (when (window-live-p icicle-orig-win-explore)
3182                     (select-window icicle-orig-win-explore))
3183                   (let ((completion-ignore-case  case-fold-search)
3184                         (buf                     (marker-buffer marker)))
3185                     (unless (bufferp buf) (error "No such buffer: %s" buf))
3186                     (pop-to-buffer buf)
3187                     (raise-frame)
3188                     (goto-char marker)
3189                     (unless (pos-visible-in-window-p) (recenter icicle-recenter))
3190                     ;; Highlight current search context using `icicle-search-main-regexp-current'.
3191                     (icicle-place-overlay (- marker (length candidate)) marker
3192                                           'icicle-search-current-overlay
3193                                           'icicle-search-main-regexp-current
3194                                           202 buf)
3195                     (funcall icicle-search-in-context-fn cand+mrker replace-string)
3196                     (icicle-highlight-candidate-in-Completions)
3197                     (run-hooks 'icicle-search-hook)))
3198               (error                    ; Ignore disappearance of `*Completions*'.
3199                (unless (string-match "Wrong type argument: window-live-p,"
3200                                      (error-message-string icicle-search-action-1-save-window))
3201                  (error "%s" (error-message-string icicle-search-action-1-save-window)))))
3202             nil))                       ; Return nil for success.
3203       (error (message "%s" (error-message-string icicle-search-action-1))
3204              (error-message-string icicle-search-action-1))))) ; Return the error string.
3205
3206 (defun icicle-search-in-context-default-fn (cand+mrker replace-string)
3207   "Default value of `icicle-search-in-context-fn'."
3208   (let ((candidate  (if (consp (car-safe cand+mrker))
3209                         (car-safe (car-safe cand+mrker))
3210                       (car-safe cand+mrker)))
3211         (marker     (cdr-safe cand+mrker)))
3212     ;; Highlight match and possibly replace.  If replacement tried, then update the dialog state.
3213     (when (save-excursion (save-restriction ; Search within the current search context.
3214                             (narrow-to-region (- marker (length candidate)) marker)
3215                             (icicle-search-highlight-and-maybe-replace cand+mrker replace-string)))
3216       ;; Update, since replacement might have changed the current candidate:
3217       ;; Rehighlight current context, update last candidate, update candidate in minibuffer.
3218       (if icicle-search-highlight-all-current-flag
3219           (let ((icicle-search-highlight-all-current-flag  nil))
3220             (icicle-search-highlight-input-matches-here))
3221         (let ((ov  icicle-search-current-overlay))
3222           (save-restriction (narrow-to-region (overlay-start ov) (overlay-end ov))
3223                             (icicle-search-highlight-input-matches-here))))
3224       (if (null icicle-completion-candidates) ; If have already replaced all, then no candidates.
3225           (when (overlayp icicle-search-current-overlay)
3226             (delete-overlay icicle-search-current-overlay))
3227         (let* ((cand+mrker  (funcall icicle-get-alist-candidate-function
3228                                      (setq icicle-last-completion-candidate
3229                                            (elt icicle-completion-candidates icicle-candidate-nb))))
3230                (marker      (cdr-safe cand+mrker)))
3231           (with-current-buffer (marker-buffer marker)
3232             (goto-char marker)
3233             ;; Highlight current search context using `icicle-search-main-regexp-current'.
3234             (icicle-place-overlay (- marker (if (consp (car cand+mrker))
3235                                                 (length (caar cand+mrker))
3236                                               (length (car cand+mrker))))
3237                                   marker 'icicle-search-current-overlay
3238                                   'icicle-search-main-regexp-current 202 (current-buffer))
3239             (unless icicle-search-highlight-all-current-flag
3240               (let ((ov  icicle-search-current-overlay))
3241                 (save-restriction (narrow-to-region (overlay-start ov) (overlay-end ov))
3242                                   (icicle-search-highlight-input-matches-here)))))
3243           (save-selected-window
3244             (select-window (minibuffer-window))
3245             (icicle-clear-minibuffer)
3246             (setq icicle-nb-of-other-cycle-candidates  (length icicle-completion-candidates))
3247             (icicle-insert-cand-in-minibuffer icicle-last-completion-candidate t)
3248             (icicle-show-help-in-mode-line icicle-last-completion-candidate))))))
3249   (let ((icicle-candidate-nb               icicle-candidate-nb)
3250         (icicle-last-completion-candidate  icicle-last-completion-candidate)
3251         (icicle-completion-candidates      icicle-completion-candidates))
3252     (icicle-complete-again-update)))
3253
3254 ;; Free var here: `icicle-search-ecm' is bound in `icicle-search'.
3255 (defun icicle-search-highlight-and-maybe-replace (cand+mrker replace-string)
3256   "Highlight within search context and replace using REPLACE-STRING.
3257 If REPLACE-STRING is nil, no replacement occurs.
3258 Arguments are the same as for `icicle-search-in-context-fn'.
3259 Return non-nil if replacement occurred, nil otherwise."
3260   (icicle-search-highlight-context-levels)
3261   (icicle-search-highlight-input-matches-here)
3262   (let ((replacement-p  nil))
3263     (when replace-string
3264       (setq replacement-p  t)
3265       (goto-char (point-min))
3266       (let ((candidate  (if (consp (car-safe cand+mrker))
3267                             (car-safe (car-safe cand+mrker))
3268                           (car-safe cand+mrker)))
3269             (ecm        (and icicle-search-replace-common-match-flag icicle-search-ecm)))
3270         (cond (icicle-search-replace-whole-candidate-flag
3271                (cond ((string= candidate replace-string) ; Sanity check only.
3272                       (save-restriction (widen) (message "Replacement = candidate, and \
3273 current input matches candidate") (sit-for 2))
3274                       (setq replacement-p  nil))
3275                      (t
3276                       (set-match-data (list (point-min) (point-max)))
3277                       (icicle-search-replace-match replace-string
3278                                                    (icicle-search-replace-fixed-case-p
3279                                                     icicle-search-context-regexp)))))
3280               ((not (save-excursion (re-search-forward (or ecm icicle-current-input) nil t)))
3281                (save-restriction (widen)
3282                                  (message "Text to be replaced not found in candidate") (sit-for 2))
3283                (setq replacement-p  nil))
3284               (t
3285                (save-match-data
3286                  (let ((first-p  t))
3287                    ;; The condition order is important.  Don't search unless first time (or all)
3288                    (while (and (or first-p icicle-all-candidates-action)
3289                                (re-search-forward (or ecm icicle-current-input) nil 'move-to-end))
3290                      (setq first-p  nil)
3291                      (icicle-search-replace-match replace-string
3292                                                   (icicle-search-replace-fixed-case-p
3293                                                    icicle-current-input)))))))
3294         (when replacement-p
3295           ;; Update the alist and `minibuffer-completion-table' with the new text.
3296
3297           ;; An ALTERNATIVE approach would be to use `icicle-search-replace-cand-in-alist'.
3298           ;; In that case we would:
3299           ;; 1. Bind `icicle-whole-candidate-as-text-prop-p' to nil (in `icicle-search-action'
3300           ;;    and `icicle-search-help').
3301           ;; 2. Use these two lines, instead of calling `icicle-search-replace-cand-in-mct'.
3302           ;;    (icicle-search-replace-cand-in-alist cand+mrker
3303           ;;                                         (buffer-substring (point-min) (point-max)))
3304           ;;    (setq minibuffer-completion-table
3305           ;;          (car (icicle-mctize-all icicle-candidates-alist nil)))
3306           ;;  If we used that method (as we used to), then users could not sort the search hits.
3307
3308           (icicle-search-replace-cand-in-mct cand+mrker (buffer-substring (point-min) (point-max)))
3309
3310           ;; If we are replacing input matches within a search context, and there are no more matches
3311           ;; in the current context, then this context is removed as a candidate. If the current
3312           ;; action command is one that moves to the next or previous candidate, then we might need
3313           ;; to adjust the current candidate number, to compensate for the removal.
3314           ;;
3315           ;; If the current action command is one (e.g. `C-S-next'), that moves to the next candidate
3316           ;; to do its action, then move back one.  If the current action acts on the previous
3317           ;; candidate (e.g. `C-S-prior'), and that previous candidate is the last one, then move
3318           ;; forward one candidate, to the first.
3319           (when (and icicle-acting-on-next/prev
3320                      (not (save-excursion (goto-char (point-min))
3321                                           (re-search-forward icicle-current-input nil t))))
3322             (let ((nb-cands  (1- (length icicle-completion-candidates)))) ; -1 for replaced one.
3323               (unless (wholenump nb-cands) (setq nb-cands  0))
3324               (setq icicle-candidate-nb  (cond ((not icicle-candidate-nb) 0)
3325                                                ((eq icicle-acting-on-next/prev 'forward)
3326                                                 (if (zerop icicle-candidate-nb)
3327                                                     (1- nb-cands)
3328                                                   (1- icicle-candidate-nb)))
3329                                                ((eq icicle-candidate-nb nb-cands)  0)
3330                                                (t icicle-candidate-nb)))
3331               (when (> icicle-candidate-nb nb-cands) (setq icicle-candidate-nb  0))
3332               (when (< icicle-candidate-nb 0) (setq icicle-candidate-nb  nb-cands))))
3333
3334           (let ((icicle-candidate-nb             icicle-candidate-nb)
3335                 (icicle-minibuffer-message-ok-p  nil)) ; Inhibit no-candidates message.
3336             (icicle-complete-again-update))
3337
3338           ;; If we are using `C-S-RET' and we are on the last candidate, then wrap to the first one.
3339           (when (and (not icicle-acting-on-next/prev)
3340                      (or (not icicle-candidate-nb)
3341                          (>= icicle-candidate-nb (length icicle-completion-candidates))))
3342             (setq icicle-candidate-nb  0))
3343           (icicle-highlight-candidate-in-Completions)
3344           (icicle-search-highlight-context-levels))))
3345     replacement-p))                     ; Return indication of whether we tried to replace something.
3346
3347 (defun icicle-search-replace-match (replace-string fixedcase)
3348   "Replace current match with REPLACE-STRING, interpreting escapes.
3349 Treat REPLACE-STRING as it would be treated by `query-replace-regexp'.
3350 FIXEDCASE is as for `replace-match'.  Non-nil means do not alter case."
3351   (if (fboundp 'query-replace-compile-replacement) ; Emacs 22.
3352       (let ((compiled
3353              (save-match-data
3354                (query-replace-compile-replacement replace-string
3355                                                   (not icicle-search-replace-literally-flag)))))
3356         (condition-case icicle-search-replace-match1
3357             (let ((enable-recursive-minibuffers    t) ; So we can read input from \?.
3358                   ;; Save and restore these, because we might read input from \?.
3359                   (icicle-last-completion-command  icicle-last-completion-command)
3360                   (icicle-last-input               icicle-last-input))
3361               (replace-match-maybe-edit
3362                (if (consp compiled)
3363                    ;; `replace-count' is free here, bound in `icicle-search'.
3364                    (funcall (car compiled) (cdr compiled) (setq replace-count  (1+ replace-count)))
3365                  compiled)
3366                fixedcase icicle-search-replace-literally-flag nil (match-data)))
3367           (buffer-read-only (ding) (error "Buffer is read-only"))
3368           (error (icicle-remove-Completions-window) (error "No match for `%s'" replace-string))))
3369     (condition-case icicle-search-replace-match2 ; Emacs < 22.  Try to interpret `\'.
3370         (replace-match replace-string fixedcase icicle-search-replace-literally-flag)
3371       (error (replace-match replace-string fixedcase t))))) ;   If error, replace literally.
3372
3373 (defun icicle-search-highlight-context-levels ()
3374   "Highlight context levels differently (up to 8 levels).
3375 No such highlighting is done if any of these conditions holds:
3376  * `icicle-search-context-level' is not 0 (search context < regexp).
3377  * `icicle-search-highlight-context-levels-flag' is nil.
3378  * `icicle-search-context-regexp' is nil (non-regexp searching)."
3379   (unless (or (/= icicle-search-context-level 0)
3380               (not icicle-search-highlight-context-levels-flag)
3381               (not icicle-search-context-regexp)) ; E.g. text-property searching
3382     (while icicle-search-level-overlays
3383       (delete-overlay (car icicle-search-level-overlays))
3384       (setq icicle-search-level-overlays  (cdr icicle-search-level-overlays)))
3385     (save-match-data
3386       (let ((level       1)
3387             (max-levels  (min (regexp-opt-depth icicle-search-context-regexp) 8)))
3388         (goto-char (point-min))
3389         (re-search-forward icicle-search-context-regexp nil t)
3390         (condition-case nil
3391             (while (<= level max-levels)
3392               (unless (equal (match-beginning level) (match-end level))
3393                 (let ((ov  (make-overlay (match-beginning level) (match-end level))))
3394                   (push ov icicle-search-level-overlays)
3395                   (overlay-put ov 'priority (+ 205 level)) ; > ediff's 100+, < isearch-overlay's 1001.
3396                   (overlay-put ov 'face (intern (concat "icicle-search-context-level-"
3397                                                         (number-to-string level))))))
3398               (setq level  (1+ level)))
3399           (error nil))))))
3400
3401 ;; Free var here: `icicle-search-ecm' is bound in `icicle-search'.
3402 (defun icicle-search-highlight-input-matches-here ()
3403   "Highlight all input matches in the current search context."
3404   (unless (or (> 0 icicle-search-highlight-threshold) (string= "" icicle-current-input))
3405     (goto-char (point-min))
3406     (when (and (not icicle-search-highlight-all-current-flag)
3407                (overlayp icicle-search-refined-overlays))
3408       (delete-overlay icicle-search-refined-overlays)
3409       (setq icicle-search-refined-overlays  nil))
3410     (unless icicle-search-highlight-all-current-flag
3411       (while icicle-search-refined-overlays
3412         (delete-overlay (car icicle-search-refined-overlays))
3413         (setq icicle-search-refined-overlays  (cdr icicle-search-refined-overlays))))
3414     (let ((ov  nil))
3415       (save-match-data
3416         (while (and (not (eobp)) (re-search-forward (or icicle-search-ecm icicle-current-input)
3417                                                     nil 'move-to-end))
3418           (if (equal (match-beginning 0) (match-end 0))
3419               (forward-char 1)
3420             (setq ov  (make-overlay (match-beginning 0) (match-end 0)))
3421             (push ov icicle-search-refined-overlays)
3422             (overlay-put ov 'priority 220) ; Greater than any possible context-level priority (213).
3423             (overlay-put ov 'face 'icicle-search-current-input)))))))
3424
3425 (defun icicle-search-replace-fixed-case-p (from)
3426   "Return non-nil if FROM should be replaced without transferring case.
3427 FROM is a string or nil.  If FROM is nil, then return nil.
3428 Retuns non-nil if FROM is a string and one of the following holds:
3429  * FROM is not all lowercase
3430  * `case-replace' or `case-fold-search' is nil"
3431   (and from (not (and case-fold-search case-replace (string= from (downcase from))))))
3432
3433 ;; Not used for now - this could replace using mct.  In that case, user must not be able to sort.
3434 (defun icicle-search-replace-cand-in-alist (cand+mrker new-cand)
3435   "In `icicle-candidates-alist', replace car of CAND+MRKER by NEW-CAND.
3436 Replace only the first occurrence of CAND+MRKER in
3437 `icicle-candidates-alist'.  (There should be only one.)"
3438   (let ((newlist  icicle-candidates-alist))
3439     (catch 'icicle-search-replace-cand-in-alist
3440       (while newlist
3441         (when (equal (car newlist) cand+mrker)
3442           (setcar newlist (cons new-cand (cdr-safe cand+mrker)))
3443           (throw 'icicle-search-replace-cand-in-alist nil))
3444         (setq newlist  (cdr newlist))))
3445     icicle-candidates-alist))
3446
3447 (defun icicle-search-replace-cand-in-mct (cand+mrker new-cand)
3448   "Replace candidate in `minibuffer-completion-table'.
3449 Update CAND+MRKER itself to use NEW-CAND (replacement string).
3450 Any text properties on CAND+MRKER's string are preserved.
3451 Use this only with a `minibuffer-completion-table' derived from an alist."
3452   (let ((newlist  minibuffer-completion-table))
3453     (catch 'icicle-search-replace-cand-in-mct
3454       ;; CAND+MRKER: ("aa" . c) or (("aa" "bb") . c)
3455       ;; `minibuffer-completion-table' entry: ("aa" "aa" . c) or ("aa^G^Jbb" . (("aa" "bb") . c))
3456       (while newlist
3457         (when (equal (cdr (car newlist)) cand+mrker)
3458           (let ((new-compl  (if (consp (car cand+mrker)) ; New completion: "QQ" or ("QQ" "bb")
3459                                 (cons new-cand (cdar cand+mrker))
3460                               new-cand))
3461                 (old-cand   (if (consp (car cand+mrker)) (caar cand+mrker) (car cand+mrker)))
3462                 rep-cand)
3463             (setcar newlist (icicle-mctized-full-candidate (cons new-compl (cdr-safe cand+mrker))))
3464             ;; NEWLIST is done.
3465             ;; Now update CAND+MRKER to reflect the replacement but with the text properties it had.
3466             ;; (cdar NEWLIST) is the new cand+mrker.  Its car or caar is the replaced candidate.
3467             ;; It is the first field of the multi-completion, in the latter case.
3468             (setq rep-cand  (if (consp (car cand+mrker)) (caar (cdar newlist)) (car (cdar newlist))))
3469             (let ((len-old  (length old-cand))
3470                   (len-rep  (length rep-cand))
3471                   (ii       0)
3472                   props)
3473               (while (< ii len-old)
3474                 (setq props  (text-properties-at ii old-cand))
3475                 (when (< ii len-rep) (add-text-properties ii (1+ ii) props rep-cand))
3476                 (setq ii  (1+ ii)))
3477               (let ((last-props  (text-properties-at (1- len-old) old-cand)))
3478                 (when (> len-rep len-old)
3479                   (add-text-properties len-old len-rep last-props rep-cand))))
3480             (if (consp (car cand+mrker))
3481                 (setcar (car cand+mrker) rep-cand)
3482               (setcar cand+mrker rep-cand)))
3483           (throw 'icicle-search-replace-cand-in-mct nil))
3484         (setq newlist  (cdr newlist))))
3485     minibuffer-completion-table))
3486
3487 (defun icicle-search-help (cand)
3488   "Use as `icicle-candidate-help-fn' for `icicle-search' commands."
3489   (icicle-msg-maybe-in-minibuffer
3490    (let* ((icicle-whole-candidate-as-text-prop-p  t)
3491           ;; Alternative: If we used `icicle-search-replace-cand-in-alist', then we would bind that
3492           ;; to nil to force using the alist, because we would be performing side effects on it.
3493           (marker  (cdr (funcall icicle-get-alist-candidate-function cand))))
3494      (concat "Buffer: `" (buffer-name (marker-buffer marker))
3495              (format "', Position: %d" (marker-position marker))))))
3496
3497 ;;;###autoload
3498 (defun icicle-search-keywords (beg end keywords require-match ; Bound to `C-c ^'.
3499                                &optional where &rest args)
3500   "Search with one or more keywords, which can each be a regexp.
3501 Text that matches *any* of the keywords is found.
3502
3503 You can use completion to choose one or more previously entered
3504 regexps (using `C-RET', `C-mouse-2', `C-next', and so on), or you can
3505 enter new keywords (using `C-RET').  Use `RET' or `mouse-2' to choose
3506 the last keyword.
3507
3508 Keywords are interpreted as regexps.  You can change to substring
3509 completion instead, matching regexp special characters literally, by
3510 using `C-`' during completion to toggle `icicle-regexp-quote-flag'.
3511
3512 You can alternatively choose to search, not the search contexts as
3513 defined by keyword matches, but the non-contexts, that is, the text in
3514 the buffer that does not match the keyword patterns.  To do this, use
3515 `C-M-~' during completion.  (This is a toggle, and it affects only
3516 future search commands, not the current one.)
3517
3518 This command is intended only for use in Icicle mode.  It is defined
3519 using `icicle-search'.  For more information, in particular for
3520 information about the arguments and the use of a prefix argument to
3521 search multiple regions, buffers, or files, see the `icicle-search'
3522 documentation."
3523   (interactive
3524    `(,@(icicle-region-or-buffer-limits)
3525        ,(icicle-group-regexp (mapconcat #'icicle-group-regexp (icicle-keyword-list) "\\|"))
3526        ,(not icicle-show-multi-completion-flag)
3527        ,(icicle-search-where-arg)))
3528   (icicle-search beg end keywords (not icicle-show-multi-completion-flag) where))
3529
3530 ;;;###autoload
3531 (defalias 'icicle-regexp-list 'icicle-keyword-list)
3532 ;;;###autoload (autoload 'icicle-keyword-list "icicles-cmd2.el")
3533 (icicle-define-command icicle-keyword-list ; Command name
3534   "Choose a list of keywords. The list of keywords (strings) is returned.
3535 You can choose from keywords entered previously or enter new keywords
3536 using `C-RET'.  Each keyword is a regexp.  The regexps are OR'd, and
3537 the resulting regexp is usable for `icicle-search'." ; Doc string
3538   (lambda (name)                        ; Action function
3539     (push name keywords)
3540     (message "Added keyword `%s'" name))
3541   "Choose keyword (regexp) (`RET' when done): " ; `completing-read' args
3542   (mapcar #'list (icicle-remove-duplicates regexp-history)) nil nil nil 'regexp-history nil nil
3543   ((keywords                              nil) ; Bindings
3544    (icicle-use-candidates-only-once-flag  t))
3545   nil nil                               ; First code, undo code
3546   (prog1 (setq keywords  (nreverse (delete "" keywords))) ; Last code - return the list of keywords.
3547     (when (interactive-p) (message "Keywords (regexps): %S" keywords))))
3548
3549 (defun icicle-group-regexp (regexp)
3550   "Wrap REGEXP between regexp parens, as a regexp group."
3551   (concat "\\(" regexp "\\)"))
3552
3553 ;;;###autoload (autoload 'icicle-search-bookmark "icicles-cmd2.el")
3554 (icicle-define-command icicle-search-bookmark ; Command name
3555   "Search bookmarked text.
3556 See also `icicle-search-bookmarks-together', which searches bookmarks
3557 together instead of one at a time.
3558
3559 1. Enter a context regexp (using `RET'), to define the possible
3560    search-hit contexts.
3561 2. Choose a bookmark using completion.  It is opened/visited/handled.
3562 3. (Optional) Type some text to be matched in the search contexts.
3563 4. Navigate to matches (search hits) using `C-next' etc.
3564 5. Finish with that bookmark using `RET' (stay) or `C-g' (skip).
3565 6. (Optional) Repeat steps 2-5 for other bookmarks.
3566
3567 If you use library `Bookmark+' then:
3568
3569 a. If a bookmark specifies a nonempty region, then search only the text
3570   in that region.
3571
3572 b. The candidate bookmarks are those in the current `*Bookmark List*'
3573   display (list `bmkp-sorted-alist', to be precise).  This means that
3574   you can limit the candidates to bookmarks of a certain type (e.g.,
3575   only autofiles, using `A S'), bookmarks with certain tags (e.g.,
3576   those with tags matching a regexp using `T m %' followed by `>'),
3577   and so on.
3578
3579 \(b) provides you with a great deal of flexibility.  However, for your
3580 convenience, if you use `Bookmark+' then Icicles also provides some
3581 special-purpose commands for searching the content of bookmarks of
3582 various types.  For example, `icicle-search-autofile-bookmark'
3583 searches autofiles.  And you can define your own such commands using
3584 macro `icicle-define-search-bookmark-command'.
3585
3586 You can alternatively choose to search, not the search contexts as
3587 defined by the context regexp, but the non-contexts, that is, the text
3588 in the bookmarked buffer that does not match the regexp.  To do this,
3589 use `C-M-~' during completion.  (This is a toggle, and it affects only
3590 future search commands, not the current one.)" ; Doc string
3591   icicle-search-bookmark-action         ; Action function
3592   prompt icicle-candidates-alist nil (not icicle-show-multi-completion-flag) ; `completing-read' args
3593   nil (if (boundp 'bookmark-history) 'bookmark-history 'icicle-bookmark-history)
3594   (and (boundp 'bookmark-current-bookmark) bookmark-current-bookmark) nil
3595   ((enable-recursive-minibuffers             t) ; In case we read input, e.g. File changed on disk...
3596    (completion-ignore-case                   bookmark-completion-ignore-case)
3597    (prompt                                   "Search bookmark: ")
3598    (regexp                                   (icicle-search-read-context-regexp))
3599    (icicle-list-use-nth-parts                '(1))
3600    (icicle-candidate-properties-alist        (if (not icicle-show-multi-completion-flag)
3601                                                  nil
3602                                                (if (facep 'file-name-shadow)
3603                                                    '((2 (face file-name-shadow))
3604                                                      (3 (face bookmark-menu-heading)))
3605                                                  '((3 (face bookmark-menu-heading))))))
3606    (icicle-transform-function                (if (interactive-p) nil icicle-transform-function))
3607    (icicle-whole-candidate-as-text-prop-p    t)
3608    (icicle-transform-before-sort-p           t)
3609    (icicle-delete-candidate-object           'icicle-bookmark-delete-action)
3610    (bookmark-automatically-show-annotations  nil) ; Do not show annotations
3611    (icicle-sort-orders-alist
3612     (append '(("in *Bookmark List* order") ; Renamed from "turned OFF'.
3613               ("by bookmark name" . icicle-alpha-p))
3614             (and (featurep 'bookmark+)
3615                  '(("by last bookmark access" (bmkp-bookmark-last-access-cp) icicle-alpha-p)
3616                    ("by bookmark visit frequency" (bmkp-visited-more-cp) icicle-alpha-p)
3617                    ("by last buffer or file access" (bmkp-buffer-last-access-cp
3618                                                      bmkp-local-file-accessed-more-recently-cp)
3619                     icicle-alpha-p)
3620                    ("marked before unmarked (in *Bookmark List*)" (bmkp-marked-cp)
3621                     icicle-alpha-p)
3622                    ("by local file type" (bmkp-local-file-type-cp) icicle-alpha-p)
3623                    ("by file name" (bmkp-file-alpha-cp) icicle-alpha-p)
3624                    ("by local file size" (bmkp-local-file-size-cp) icicle-alpha-p)
3625                    ("by last local file access" (bmkp-local-file-accessed-more-recently-cp)
3626                     icicle-alpha-p)
3627                    ("by last local file update" (bmkp-local-file-updated-more-recently-cp)
3628                     icicle-alpha-p)
3629                    ("by Info location" (bmkp-info-cp) icicle-alpha-p)
3630                    ("by Gnus thread" (bmkp-gnus-cp) icicle-alpha-p)
3631                    ("by URL" (bmkp-url-cp) icicle-alpha-p)
3632                    ("by bookmark type" (bmkp-info-cp bmkp-url-cp bmkp-gnus-cp
3633                                         bmkp-local-file-type-cp bmkp-handler-cp)
3634                     icicle-alpha-p)))
3635             '(("by previous use alphabetically" . icicle-historical-alphabetic-p)
3636               ("case insensitive" . icicle-case-insensitive-string-less-p))))
3637    (icicle-candidate-help-fn
3638     #'(lambda (cand)
3639         (when (and (featurep 'bookmark+) icicle-show-multi-completion-flag)
3640           (setq cand  (funcall icicle-get-alist-candidate-function cand))
3641           (setq cand  (cons (caar cand) (cdr cand))))
3642         (if (featurep 'bookmark+)
3643             (if current-prefix-arg
3644                 (bmkp-describe-bookmark-internals cand)
3645               (bmkp-describe-bookmark cand))
3646           (icicle-msg-maybe-in-minibuffer (icicle-bookmark-help-string cand)))))
3647    (icicle-candidates-alist
3648     (if (not (featurep 'bookmark+))
3649         (mapcar #'(lambda (cand)
3650                     (list (icicle-candidate-short-help (icicle-bookmark-help-string cand)
3651                                                        (icicle-bookmark-propertize-candidate cand))))
3652                 (bookmark-all-names))   ; Loads bookmarks file, defining `bookmark-alist'.
3653       (bookmark-maybe-load-default-file) ; Loads bookmarks file, defining `bookmark-alist'.
3654       (mapcar (if icicle-show-multi-completion-flag
3655                   #'(lambda (bmk)
3656                       ;; Ignore errors, e.g. from bad or stale bookmark records.
3657                       (icicle-condition-case-no-debug nil
3658                           (let* ((bname     (bookmark-name-from-full-record bmk))
3659                                  (guts      (bookmark-get-bookmark-record bmk))
3660                                  (file      (bookmark-get-filename bmk))
3661                                  (buf       (bmkp-get-buffer-name bmk))
3662                                  (file/buf  (if (and buf (equal file bmkp-non-file-filename))
3663                                                 buf
3664                                               file))
3665                                  (tags      (bmkp-get-tags bmk)))
3666                             (cons `(,(icicle-candidate-short-help
3667                                       (icicle-bookmark-help-string bname)
3668                                       (icicle-bookmark-propertize-candidate bname))
3669                                     ,file/buf
3670                                     ,@(and tags (list (format "%S" tags))))
3671                                   guts))
3672                         (error nil)))
3673                 #'(lambda (bmk)
3674                     ;; Ignore errors, e.g. from bad or stale bookmark records.
3675                     (icicle-condition-case-no-debug nil
3676                         (let ((bname  (bookmark-name-from-full-record bmk))
3677                               (guts   (bookmark-get-bookmark-record bmk)))
3678                           (cons (icicle-candidate-short-help
3679                                  (icicle-bookmark-help-string bname)
3680                                  (icicle-bookmark-propertize-candidate bname))
3681                                 guts))
3682                       (error nil))))
3683               (or (and (or (and (not icicle-bookmark-refresh-cache-flag)
3684                                 (not (consp current-prefix-arg)))
3685                            (and icicle-bookmark-refresh-cache-flag (consp current-prefix-arg)))
3686                        bmkp-sorted-alist)
3687                   (setq bmkp-sorted-alist  (bmkp-sort-omit bookmark-alist)))))))
3688   (progn                                ; First code
3689     (require 'bookmark)
3690     (when (featurep 'bookmark+)
3691       ;; Bind keys to narrow bookmark candidates by type.  Lax is for multi-completion case.
3692       (dolist (map  '(minibuffer-local-must-match-map minibuffer-local-completion-map))
3693         (define-key (symbol-value map) "\C-\M-b" 'icicle-bookmark-non-file-narrow)
3694         (define-key (symbol-value map) "\C-\M-d" 'icicle-bookmark-dired-narrow)
3695         (define-key (symbol-value map) "\C-\M-f" 'icicle-bookmark-file-narrow)
3696         (define-key (symbol-value map) "\C-\M-g" 'icicle-bookmark-gnus-narrow)
3697         (define-key (symbol-value map) "\C-\M-i" 'icicle-bookmark-info-narrow)
3698         (define-key (symbol-value map) "\C-\M-m" 'icicle-bookmark-man-narrow)
3699         (define-key (symbol-value map) "\C-\M-r" 'icicle-bookmark-region-narrow)
3700         (define-key (symbol-value map) "\C-\M-u" 'icicle-bookmark-url-narrow)
3701         (define-key (symbol-value map) "\C-\M-w" 'icicle-bookmark-w3m-narrow)
3702         (define-key (symbol-value map) "\C-\M-@" 'icicle-bookmark-remote-file-narrow)
3703         (define-key (symbol-value map) [(control meta ?B)]
3704           'icicle-bookmark-bookmark-list-narrow) ; `C-M-B'
3705         (define-key (symbol-value map) [(control meta ?F)]
3706           'icicle-bookmark-local-file-narrow) ; `C-M-F'
3707         (define-key (symbol-value map) [(control meta ?K)]
3708           'icicle-bookmark-desktop-narrow)))) ; `C-M-K'
3709   (icicle-bookmark-cleanup-on-quit)     ; Undo code
3710   (icicle-bookmark-cleanup))            ; Last code
3711
3712 (defun icicle-search-bookmark-action (bookmark-name)
3713   "Action function for `icicle-search-bookmark'."
3714   (setq bookmark-name  (icicle-transform-multi-completion bookmark-name))
3715   (bookmark-jump-other-window bookmark-name)
3716   (setq mark-active  nil)               ; Unhighlight region, so you can see search hits etc.
3717   (let ((icicle-show-Completions-initially-flag  t)
3718         (icicle-candidate-action-fn              'icicle-search-action)
3719         (enable-recursive-minibuffers            t)
3720         (beg
3721          (or (and (featurep 'bookmark+) (bmkp-region-bookmark-p bookmark-name)
3722                   (bookmark-get-position bookmark-name))
3723              (point-min)))
3724         (end
3725          (or (and (featurep 'bookmark+) (bmkp-region-bookmark-p bookmark-name)
3726                   (bmkp-get-end-position bookmark-name))
3727              (point-max))))
3728     (when (= beg end) (setq beg  (point-min)    end  (point-max)))
3729     (icicle-search beg end regexp t))
3730   (with-current-buffer (window-buffer (minibuffer-window)) (icicle-erase-minibuffer)))
3731
3732 ;; Similar to `icicle-define-bookmark-command-1' in `icicles-cmd1.el'.  Could combine them.
3733 (defmacro icicle-define-search-bookmark-command (type &optional prompt &rest args)
3734   "Define Icicles multi-command for searching bookmarks of type TYPE.
3735 TYPE is a string to be used for the doc string, default prompt, and in
3736  function names.  It should be lowercase and contain no spaces.
3737 Optional arg PROMPT is the completion prompt.
3738 ARGS is a list of any additional arguments to be passed to the
3739  appropriate `bmkp-TYPE-alist-only' function.
3740
3741 The command defined raises an error unless library `Bookmark+' can be
3742 loaded."
3743   `(icicle-define-command
3744     ,(intern (format "icicle-search-%s-bookmark" type)) ; Command name
3745     ,(format "Search %s bookmark text.
3746 Like `icicle-search-bookmark', but with %s bookmarks only.
3747 You need library `Bookmark+' for this command." type type) ; Doc string
3748     icicle-search-bookmark-action       ; Action function
3749     prompt1 icicle-candidates-alist nil ; `completing-read' args
3750     (not icicle-show-multi-completion-flag)
3751     nil (if (boundp 'bookmark-history) 'bookmark-history 'icicle-bookmark-history)
3752     nil nil
3753     ((IGNORED1                                 (unless (require 'bookmark+ nil t) ; Bindings
3754                                                  (error "You need library `Bookmark+' for this \
3755 command")))
3756      (IGNORED2                                 (bookmark-maybe-load-default-file)) ; `bookmark-alist'.
3757      (enable-recursive-minibuffers             t) ; In case we read input, e.g. File changed on...
3758      (completion-ignore-case                   bookmark-completion-ignore-case)
3759      (prompt1                                  ,(or prompt (format "Search %s bookmark: " type)))
3760      (icicle-list-use-nth-parts                '(1))
3761      (icicle-candidate-properties-alist        (if (not icicle-show-multi-completion-flag)
3762                                                    nil
3763                                                  (if (facep 'file-name-shadow)
3764                                                      '((2 (face file-name-shadow))
3765                                                        (3 (face bookmark-menu-heading)))
3766                                                    '((3 (face bookmark-menu-heading))))))
3767      (icicle-transform-function                (if (interactive-p) nil icicle-transform-function))
3768      (icicle-whole-candidate-as-text-prop-p    t)
3769      (icicle-transform-before-sort-p           t)
3770      (icicle-delete-candidate-object           'icicle-bookmark-delete-action)
3771      (regexp                                   (icicle-search-read-context-regexp))
3772      (bookmark-automatically-show-annotations  nil) ; Do not show annotations
3773      (icicle-sort-orders-alist
3774       (append
3775        '(("in *Bookmark List* order")   ; Renamed from "turned OFF'.
3776          ("by bookmark name" . icicle-alpha-p)
3777          ("by last bookmark access" (bmkp-bookmark-last-access-cp) icicle-alpha-p)
3778          ("by bookmark visit frequency" (bmkp-visited-more-cp) icicle-alpha-p))
3779        (and (member ,type '("info" "region"))
3780         '(("by Info location" (bmkp-info-cp) icicle-alpha-p)))
3781        (and (member ,type '("gnus" "region"))
3782         '(("by Gnus thread" (bmkp-gnus-cp) icicle-alpha-p)))
3783        (and (member ,type '("url" "region"))
3784         '(("by URL" (bmkp-url-cp) icicle-alpha-p)))
3785        (and (not (member ,type '("bookmark-list" "desktop" "gnus" "info" "man" "url")))
3786         '(("by bookmark type" (bmkp-info-cp bmkp-url-cp bmkp-gnus-cp
3787                                bmkp-local-file-type-cp bmkp-handler-cp)
3788            icicle-alpha-p)))
3789        (and (not (member ,type '("bookmark-list" "desktop" "dired" "non-file")))
3790         '(("by file name" (bmkp-file-alpha-cp) icicle-alpha-p)))
3791        (and (member ,type '("local-file" "file" "dired" "region"))
3792         '(("by local file type" (bmkp-local-file-type-cp) icicle-alpha-p)
3793           ("by local file size" (bmkp-local-file-size-cp) icicle-alpha-p)
3794           ("by last local file access" (bmkp-local-file-accessed-more-recently-cp)
3795            icicle-alpha-p)
3796           ("by last local file update" (bmkp-local-file-updated-more-recently-cp)
3797            icicle-alpha-p)))
3798        (and (not (string= ,type "desktop"))
3799         '(("by last buffer or file access" (bmkp-buffer-last-access-cp
3800                                             bmkp-local-file-accessed-more-recently-cp)
3801            icicle-alpha-p)))
3802        (and (get-buffer "*Bookmark List*")
3803         '(("marked before unmarked (in *Bookmark List*)" (bmkp-marked-cp)
3804            icicle-alpha-p)))
3805        '(("by previous use alphabetically" . icicle-historical-alphabetic-p)
3806          ("case insensitive" . icicle-case-insensitive-string-less-p))))
3807      (icicle-candidate-help-fn
3808       #'(lambda (cand)
3809           (when icicle-show-multi-completion-flag
3810             (setq cand  (funcall icicle-get-alist-candidate-function cand))
3811             (setq cand  (cons (caar cand) (cdr cand))))
3812           (if current-prefix-arg
3813               (bmkp-describe-bookmark-internals cand)
3814             (bmkp-describe-bookmark cand))))
3815      (icicle-candidates-alist
3816       (mapcar (if icicle-show-multi-completion-flag
3817                   #'(lambda (bmk)
3818                       ;; Ignore errors, e.g. from bad or stale bookmark records.
3819                       (icicle-condition-case-no-debug nil
3820                           (let* ((bname     (bookmark-name-from-full-record bmk))
3821                                  (guts      (bookmark-get-bookmark-record bmk))
3822                                  (file      (bookmark-get-filename bmk))
3823                                  (buf       (bmkp-get-buffer-name bmk))
3824                                  (file/buf  (if (and buf (equal file bmkp-non-file-filename))
3825                                                 buf
3826                                               file))
3827                                  (tags      (bmkp-get-tags bmk)))
3828                             ;; Emacs 20 byte-compiler bug prevents using backslash syntax here.
3829                             (cons (append (list (icicle-candidate-short-help
3830                                                  (icicle-bookmark-help-string bname)
3831                                                  (icicle-bookmark-propertize-candidate bname))
3832                                                 file/buf)
3833                                           (and tags (list (format "%S" tags))))
3834                                   guts))
3835                         (error nil)))
3836                 #'(lambda (bmk)
3837                     ;; Ignore errors, e.g. from bad or stale bookmark records.
3838                     (icicle-condition-case-no-debug nil
3839                         (let ((bname  (bookmark-name-from-full-record bmk))
3840                               (guts   (bookmark-get-bookmark-record bmk)))
3841                           (cons (icicle-candidate-short-help
3842                                  (icicle-bookmark-help-string bname)
3843                                  (icicle-bookmark-propertize-candidate bname))
3844                                 guts))
3845                       (error nil))))
3846        (bmkp-sort-omit (funcall ',(intern (format "bmkp-%s-alist-only" type)) ,@args)))))
3847     nil                                 ; First code
3848     (icicle-bookmark-cleanup-on-quit)   ; Undo code
3849     (icicle-bookmark-cleanup)))         ; Last code
3850
3851 ;; The following sexps macro-expand to define these commands:
3852 ;;  `icicle-search-all-tags-bookmark'
3853 ;;  `icicle-search-all-tags-regexp-bookmark'
3854 ;;  `icicle-search-autofile-bookmark'
3855 ;;  `icicle-search-bookmark-list-bookmark'
3856 ;;  `icicle-search-desktop-bookmark'
3857 ;;  `icicle-search-dired-bookmark'
3858 ;;  `icicle-search-file-bookmark'
3859 ;;  `icicle-search-gnus-bookmark'
3860 ;;  `icicle-search-info-bookmark'
3861 ;;  `icicle-search-local-file-bookmark'
3862 ;;  `icicle-search-man-bookmark'
3863 ;;  `icicle-search-non-file-bookmark'
3864 ;;  `icicle-search-region-bookmark'
3865 ;;  `icicle-search-remote-file-bookmark'
3866 ;;  `icicle-search-some-tags-bookmark'
3867 ;;  `icicle-search-some-tags-regexp-bookmark'
3868 ;;  `icicle-search-specific-buffers-bookmark'
3869 ;;  `icicle-search-specific-files-bookmark'
3870 ;;  `icicle-search-this-buffer-bookmark'
3871 ;;  `icicle-search-url-bookmark'
3872 ;;  `icicle-search-w3m-bookmark'
3873
3874 (icicle-define-search-bookmark-command "all-tags" nil (bmkp-read-tags-completing))
3875 (icicle-define-search-bookmark-command "all-tags-regexp" nil (bmkp-read-tags-completing))
3876 (icicle-define-search-bookmark-command "autofile")
3877 (icicle-define-search-bookmark-command "bookmark-list")
3878 (icicle-define-search-bookmark-command "desktop")
3879 (icicle-define-search-bookmark-command "dired")
3880 (icicle-define-search-bookmark-command "file")
3881 (icicle-define-search-bookmark-command "gnus")
3882 (icicle-define-search-bookmark-command "info")
3883 (icicle-define-search-bookmark-command "local-file")
3884 (icicle-define-search-bookmark-command "man")
3885 (icicle-define-search-bookmark-command "non-file")
3886 (icicle-define-search-bookmark-command "region" "Search region: ")
3887 (icicle-define-search-bookmark-command "remote-file")
3888 (icicle-define-search-bookmark-command "some-tags" nil (bmkp-read-tags-completing))
3889 (icicle-define-search-bookmark-command "some-tags-regexp" nil (bmkp-read-tags-completing))
3890 (icicle-define-search-bookmark-command "specific-buffers" nil (icicle-bookmarked-buffer-list))
3891 (icicle-define-search-bookmark-command "specific-files" nil (icicle-bookmarked-file-list))
3892 (icicle-define-search-bookmark-command "this-buffer")
3893 (icicle-define-search-bookmark-command "url")
3894 (icicle-define-search-bookmark-command "w3m")
3895
3896 ;;; Same as `thgcmd-last-thing-type' in `thing-cmds.el'.
3897 (defvar icicle-last-thing-type (if (boundp 'thgcmd-last-thing-type) thgcmd-last-thing-type 'sexp)
3898   "Type of thing last used by `icicle-next-visible-thing' (or previous).")
3899
3900 ;;;###autoload
3901 (defun icicle-search-xml-element (beg end require-match where element)
3902   "`icicle-search' with XML ELEMENTs as search contexts.
3903 ELEMENT is a regexp that is matched against actual element names.
3904
3905 The search contexts are the top-level matching elements within the
3906 search limits, BEG and END.  Those elements might or might not contain
3907 descendent elements that are themselves of type ELEMENT.
3908
3909 You can alternatively choose to search, not the search contexts as
3910 defined by the element-name regexp, but the non-contexts, that is, the
3911 buffer text that is outside such elements.  To do this, use `C-M-~'
3912 during completion.  (This is a toggle, and it affects only future
3913 search commands, not the current one.)
3914
3915 You probably need nXML for this command.  It is included in vanilla
3916 Emacs, starting with Emacs 23."
3917   (interactive
3918    (let* ((where    (icicle-search-where-arg))
3919           (beg+end  (icicle-region-or-buffer-limits))
3920           (beg1     (car beg+end))
3921           (end1     (cadr beg+end))
3922           (elt      (read-string "XML element (name regexp, no markup): " nil 'regexp-history)))
3923      `(,beg1 ,end1 ,(not icicle-show-multi-completion-flag) ,where ,elt)))
3924   (let ((nxml-sexp-element-flag  t))
3925     (icicle-search-thing
3926      'sexp beg end require-match where
3927      `(lambda (thg+bds)
3928        (and thg+bds
3929         (if (fboundp 'string-match-p)
3930             (string-match-p ,(format "\\`\\s-*<\\s-*%s\\s-*>" element) (car thg+bds))
3931           (string-match ,(format "\\`\\s-*<\\s-*%s\\s-*>" element) (car thg+bds))))))))
3932
3933 ;;;###autoload
3934 (defun icicle-search-xml-element-text-node (beg end require-match where element)
3935   "`icicle-search', with text() nodes of XML ELEMENTs as search contexts.
3936 ELEMENT is a regexp that is matched against actual XML element names.
3937
3938 The search contexts are the text() nodes of the top-level matching
3939 elements within the search limits, BEG and END.  (Those elements might
3940 or might not contain descendent elements that are themselves of type
3941 ELEMENT.)
3942
3943 You can alternatively choose to search, not the search contexts as
3944 defined by the element-name regexp, but the non-contexts, that is, the
3945 buffer text that is outside the text nodes of such elements.  To do
3946 this, use `C-M-~' during completion.  (This is a toggle, and it
3947 affects only future search commands, not the current one.)
3948
3949 You probably need nXML for this command.  It is included in vanilla
3950 Emacs, starting with Emacs 23."
3951   (interactive
3952    (let* ((where    (icicle-search-where-arg))
3953           (beg+end  (icicle-region-or-buffer-limits))
3954           (beg1     (car beg+end))
3955           (end1     (cadr beg+end))
3956           (elt      (read-string "XML element (name regexp, no markup): " nil 'regexp-history)))
3957      `(,beg1 ,end1 ,(not icicle-show-multi-completion-flag) ,where ,elt)))
3958   (let ((nxml-sexp-element-flag  t))
3959     (icicle-search-thing
3960      'sexp beg end require-match where
3961      `(lambda (thg+bds)
3962        (and thg+bds
3963         (if (fboundp 'string-match-p)
3964             (string-match-p ,(format "\\`\\s-*<\\s-*%s\\s-*>" element) (car thg+bds))
3965           (string-match ,(format "\\`\\s-*<\\s-*%s\\s-*>" element) (car thg+bds)))))
3966      `(lambda (thg+bds)
3967        (save-excursion
3968          (let* ((tag-end     (string-match ,(format "\\`\\s-*<\\s-*%s\\s-*>" element)
3969                                            (car thg+bds)))
3970                 (child       (icicle-next-visible-thing
3971                               'sexp (+ (match-end 0) (cadr thg+bds)) (cddr thg+bds)))
3972                 (tag-regexp  (concat "\\`\\s-*<\\s-*"
3973                                      (if (> emacs-major-version 20)
3974                                          (if (boundp 'xmltok-ncname-regexp)
3975                                              xmltok-ncname-regexp
3976                                            "\\(?:[_[:alpha:]][-._[:alnum:]]*\\)")
3977                                        "\\([_a-zA-Z][-._a-zA-Z0-9]\\)")
3978                                      "\\s-*>")))
3979            (and child
3980                 (not (if (fboundp 'string-match-p)
3981                          (string-match-p tag-regexp (car child))
3982                        (string-match tag-regexp (car child))))
3983                 child)))))))
3984
3985 ;;;###autoload
3986 (defun icicle-search-thing (thing &optional beg end require-match where predicate transform-fn)
3987   "`icicle-search' with THINGs as search contexts.
3988 Enter the type of THING to search: `sexp', `sentence', `list',
3989 `string', `comment', etc.
3990
3991 Possible THINGs are those for which `bounds-of-thing-at-point' returns
3992 non-nil (and for which the bounds are not equal: an empty thing).
3993 This does not include all THINGs for which `thing-at-point' returns
3994 non-nil.
3995
3996 You can search the region, buffer, multiple buffers, or multiple
3997 files.  See `icicle-search' for a full explanation.
3998
3999 If user option `icicle-ignore-comments-flag' is nil then include
4000 THINGs located within comments.  Non-nil means to ignore comments for
4001 searching.  You can toggle this option using `C-M-;' in the
4002 minibuffer, but depending on when you do so you might need to invoke
4003 this command again.
4004
4005 Non-interactively, if optional arg PREDICATE is non-nil then it is a
4006 predicate that acceptable things must satisfy.  It is passed the thing
4007 in the form of the cons returned by
4008 `icicle-next-visible-thing-and-bounds'.
4009
4010 Non-interactively, if optional arg TRANSFORM-FN is non-nil then it is
4011 a function to apply to each thing plus its bounds and which returns
4012 the actual search-target to push to `icicle-candidates-alist' in place
4013 of THING.  Its argument is the same as PREDICATE's.  It returns the
4014 replacement for the thing plus its bounds, in the same form: a
4015 cons (STRING START . END), where STRING is the search hit string and
4016 START and END are its bounds).
4017
4018 You can alternatively choose to search, not the THINGs as search
4019 contexts, but the non-THINGs (non-contexts), that is, the buffer text
4020 that is outside THINGs.  To do this, use `C-M-~' during completion.
4021 \(This is a toggle, and it affects only future search commands, not
4022 the current one.)
4023
4024 This command is intended only for use in Icicle mode.
4025
4026 NOTE:
4027
4028 1. For best results, use also library `thingatpt+.el'.
4029 2. In some cases it can take a while to gather the candidate THINGs.
4030    Use the command on an active region when you do not need to search
4031    THINGS throughout an entire buffer.
4032 3. In `nxml-mode', remember that option `nxml-sexp-element-flag'
4033    controls what a `sexp' means.  To use whole XML elements as search
4034    contexts, set it to t, not nil.  (This is already done for the
4035    predefined Icicles XML search commands.)
4036 4. Remember that if there is only one THING in the buffer or active
4037    region then no search is done.  Icicles search does nothing when
4038    there is only one possible search hit.
4039 5. The scan candidate things moves forward a THING at a time.  In
4040    particular, if either PREDICATE or TRANSFORM-FN disqualifies the
4041    thing being scanned currently, then scanning skips forward to the
4042    next thing.  The scan does not dig inside the current thing to look
4043    for a qualified THING.
4044 6. In some Emacs releases, especially prior to Emacs 23, the
4045    thing-at-point functions can sometimes behave incorrectly.  Thus,
4046    `icicle-search-thing' also behaves incorrectly in such cases.
4047 7. Prior to Emacs 21 there is no possibility of ignoring comments."
4048   (interactive (icicle-search-thing-args))
4049   (setq icicle-search-context-level  0)
4050   (icicle-search beg end 'icicle-search-thing-scan require-match where thing predicate transform-fn))
4051
4052 (defun icicle-search-thing-args ()
4053   "Read and return interactive arguments for `icicle-search-thing'."
4054   (let* ((where    (icicle-search-where-arg))
4055          (beg+end  (icicle-region-or-buffer-limits))
4056          (beg1     (car beg+end))
4057          (end1     (cadr beg+end))
4058          (thing    (intern
4059                     (completing-read
4060                      (format "%shing (type): " (if icicle-search-complement-domain-p "*NOT* t" "T"))
4061                      (icicle-things-alist) nil nil nil nil (symbol-name icicle-last-thing-type)))))
4062     (when (and (eq thing 'comment)  icicle-ignore-comments-flag)
4063       (message "Use `C-M-;' if you do not want to ignore comments") (sit-for 2))
4064     `(,thing ,beg1 ,end1 ,(not icicle-show-multi-completion-flag) ,where)))
4065
4066 ;;; Same as `thgcmd-things-alist' in `thing-cmds.el'.
4067 (defun icicle-things-alist ()
4068   "Alist of most thing types currently defined.
4069 Each is a cons (STRING), where STRING names a type of text entity for
4070 which there is a either a corresponding `forward-'thing operation, or
4071 corresponding `beginning-of-'thing and `end-of-'thing operations.  The
4072 list includes the names of the symbols that satisfy
4073 `icicle-defined-thing-p', but with these excluded: `thing', `buffer',
4074 `point'."
4075   (let ((types  ()))
4076     (mapatoms
4077      (lambda (tt)
4078        (when (icicle-defined-thing-p tt) (push (symbol-name tt) types))))
4079     (dolist (typ  '("thing" "buffer" "point")) ; Remove types that do not make sense.
4080       (setq types (delete typ types)))
4081     (setq types  (sort types #'string-lessp))
4082     (mapcar #'list types)))
4083
4084 ;;; Same as `thgcmd-defined-thing-p' in `thing-cmds.el'.
4085 (defun icicle-defined-thing-p (thing)
4086   "Return non-nil if THING (type) is defined for `thing-at-point'."
4087   (let ((forward-op    (or (get thing 'forward-op)  (intern-soft (format "forward-%s" thing))))
4088         (beginning-op  (get thing 'beginning-op))
4089         (end-op        (get thing 'end-op))
4090         (bounds-fn     (get thing 'bounds-of-thing-at-point))
4091         (thing-fn      (get thing 'thing-at-point)))
4092     (or (functionp forward-op)
4093         (and (functionp beginning-op) (functionp end-op))
4094         (functionp bounds-fn)
4095         (functionp thing-fn))))
4096
4097 ;;; Same as `hide/show-comments' in `hide-comnt.el'.
4098 ;;;###autoload
4099 (defun icicle-hide/show-comments (&optional hide/show start end)
4100   "Hide or show comments from START to END.
4101 Interactively, hide comments, or show them if you use a prefix arg.
4102 Interactively, START and END default to the region limits, if active.
4103 Otherwise, including non-interactively, they default to `point-min'
4104 and `point-max'.
4105
4106 Uses `save-excursion', restoring point.
4107
4108 Be aware that using this command to show invisible text shows *all*
4109 such text, regardless of how it was hidden.  IOW, it does not just
4110 show invisible text that you previously hid using this command.
4111
4112 From Lisp, a HIDE/SHOW value of `hide' hides comments.  Other values
4113 show them.
4114
4115 This function does nothing in Emacs versions prior to Emacs 21,
4116 because it needs `comment-search-forward'."
4117   (interactive `(,(if current-prefix-arg 'show 'hide) ,@(icicle-region-or-buffer-limits)))
4118   (when (require 'newcomment nil t)     ; `comment-search-forward'
4119     (unless start (setq start  (point-min)))
4120     (unless end   (setq end    (point-max)))
4121     (unless (<= start end) (setq start  (prog1 end (setq end  start))))
4122     (let ((bufmodp           (buffer-modified-p))
4123           (buffer-read-only  nil)
4124           cbeg cend)
4125       (unwind-protect
4126            (save-excursion
4127              (goto-char start)
4128              (while (and (< start end) (setq cbeg  (comment-search-forward end 'NOERROR)))
4129                (setq cend  (if (string= "" comment-end)
4130                                (min (1+ (line-end-position)) (point-max))
4131                              (search-forward comment-end end 'NOERROR)))
4132                (when (and cbeg cend)
4133                  (if (eq 'hide hide/show)
4134                      (put-text-property cbeg cend 'invisible t)
4135                    (put-text-property cbeg cend 'invisible nil)))))
4136         (set-buffer-modified-p bufmodp)))))
4137
4138 ;;; Same as `with-comments-hidden' in `hide-comnt.el', except doc here mentions `C-M-;'.
4139 (defmacro icicle-with-comments-hidden (start end &rest body)
4140   "Evaluate the forms in BODY while comments are hidden from START to END.
4141 But if `icicle-ignore-comments-flag' is nil, just evaluate BODY,
4142 without hiding comments.  Show comments again when BODY is finished.
4143 You can toggle `icicle-ignore-comments-flag' using `C-M-;' in the
4144 minibuffer, but depending on when you do so you might need to invoke
4145 the current command again.
4146
4147 See `icicle-hide/show-comments', which is used to hide and show the
4148 comments.  Note that prior to Emacs 21, this never hides comments."
4149   (let ((result  (make-symbol "result"))
4150         (ostart  (make-symbol "ostart"))
4151         (oend    (make-symbol "oend")))
4152     `(let ((,ostart  ,start)
4153            (,oend    ,end)
4154            ,result)
4155       (unwind-protect
4156            (setq ,result  (progn (when icicle-ignore-comments-flag
4157                                    (icicle-hide/show-comments 'hide ,ostart ,oend))
4158                                  ,@body))
4159         (when icicle-ignore-comments-flag (icicle-hide/show-comments 'show ,ostart ,oend))
4160         ,result))))
4161
4162 (defun icicle-search-thing-scan (buffer beg end thing &optional predicate transform-fn)
4163   "Scan BUFFER from BEG to END for things of type THING.
4164 Push the things found onto `icicle-candidates-alist'.
4165 If BUFFER is nil, scan the current buffer.
4166 Highlight the matches using face `icicle-search-main-regexp-others'.
4167 If BEG and END are nil, scan entire BUFFER.
4168
4169 If PREDICATE is non-nil then it is a predicate that acceptable things
4170 must satisfy.  It is passed the thing plus its bounds, in the form of
4171 the cons returned by `icicle-next-visible-thing-and-bounds'.
4172
4173 If TRANSFORM-FN is non-nil then it is a function to apply to each
4174 thing plus its bounds.  Its argument is the same as PREDICATE's.  It
4175 returns the actual search-target to push to `icicle-candidates-alist'
4176 in place of THING.  That is, it returns the replacement for the thing
4177 plus its bounds, in the same form: a cons (STRING START . END), where
4178 STRING is the search hit string and START and END are its bounds).  It
4179 can also return nil, in which case it acts as another predicate: the
4180 thing is not included as a candidate.
4181
4182 NOTE: The scan moves forward a THING at a time.  In particular, if
4183 either PREDICATE or TRANSFORM-FN disqualifies the thing being scanned
4184 currently, then scanning skips forward to the next thing.  The scan
4185 does not dig inside the current thing to look for a qualified THING.
4186
4187 This function respects both `icicle-search-complement-domain-p' and
4188 `icicle-ignore-comments-flag'."
4189   (let ((add-bufname-p  (and buffer icicle-show-multi-completion-flag))
4190         (temp-list      ())
4191         (last-beg       nil))
4192     (unless buffer (setq buffer  (current-buffer)))
4193     (when (bufferp buffer)              ; Do nothing if BUFFER is not a buffer.
4194       (with-current-buffer buffer
4195         (unless beg (setq beg  (point-min)))
4196         (unless end (setq end  (point-max)))
4197         (unless (< beg end) (setq beg  (prog1 end (setq end  beg)))) ; Ensure BEG is before END.
4198         (icicle-with-comments-hidden
4199          beg end
4200          (icicle-condition-case-no-debug icicle-search-thing-scan
4201              (save-excursion
4202                (goto-char (setq last-beg  beg)) ; `icicle-next-visible-thing-and-bounds' uses point.
4203                (while (and last-beg  (< last-beg end))
4204                  (while (and (< beg end) (icicle-invisible-p beg)) ; Skip invisible, overlay or text.
4205                    (when (get-char-property beg 'invisible)
4206                      (setq beg  (icicle-next-single-char-property-change beg 'invisible nil end))))
4207                  (let ((thg+bnds  (icicle-next-visible-thing-and-bounds thing beg end)))
4208                    (if (and (not thg+bnds) (not icicle-search-complement-domain-p))
4209                        (setq beg  end)
4210                      (let* ((thg-beg       (cadr thg+bnds))
4211                             (thg-end       (cddr thg+bnds))
4212                             (tr-thg-beg    thg-beg)
4213                             (tr-thg-end    thg-end)
4214                             (hit-beg       (if icicle-search-complement-domain-p
4215                                                last-beg
4216                                              tr-thg-beg))
4217                             (hit-end       (if icicle-search-complement-domain-p
4218                                                (or tr-thg-beg end)
4219                                              tr-thg-end))
4220                             (hit-string    (buffer-substring hit-beg hit-end))
4221                             (end-marker    (copy-marker hit-end))
4222                             (filteredp     (or (not predicate)
4223                                                (not thg+bnds)
4224                                                (funcall predicate thg+bnds)))
4225                             (new-thg+bnds  (if icicle-search-complement-domain-p
4226                                                thg+bnds
4227                                              (and filteredp
4228                                                   thg+bnds
4229                                                   (if transform-fn
4230                                                       (funcall transform-fn thg+bnds)
4231                                                     thg+bnds)))))
4232                        (when (and (not (string= "" hit-string)) ; No-op if empty hit.
4233                                   (or new-thg+bnds  icicle-search-complement-domain-p))
4234                          (when (and  transform-fn  (not icicle-search-complement-domain-p))
4235                            (setq hit-string  (car  new-thg+bnds)
4236                                  tr-thg-beg  (cadr new-thg+bnds)
4237                                  tr-thg-end  (cddr new-thg+bnds)
4238                                  end-marker  (copy-marker tr-thg-end)))
4239
4240                          (when (and icicle-ignore-comments-flag  icicle-search-complement-domain-p)
4241                            (put-text-property 0 (length hit-string) 'invisible nil hit-string))
4242                          
4243                          (icicle-candidate-short-help
4244                           (concat (and add-bufname-p
4245                                        (format "Buffer: `%s', "
4246                                                (buffer-name (marker-buffer end-marker))))
4247                                   (format "Bounds: (%d, %d), Length: %d"
4248                                           hit-beg hit-end (length hit-string)))
4249                           hit-string)
4250                          (push (cons (if add-bufname-p
4251                                          (list hit-string
4252                                                (let ((string  (copy-sequence (buffer-name))))
4253                                                  (put-text-property
4254                                                   0 (length string)
4255                                                   'face 'icicle-candidate-part string)
4256                                                  string))
4257                                        hit-string)
4258                                      end-marker)
4259                                temp-list)
4260                          ;; Highlight search context in buffer.
4261                          (when (and (not (equal hit-beg hit-end))
4262                                     (<= (+ (length temp-list) (length icicle-candidates-alist))
4263                                         icicle-search-highlight-threshold))
4264                            (let ((ov  (make-overlay hit-beg hit-end)))
4265                              (push ov icicle-search-overlays)
4266                              (overlay-put ov 'priority 200) ; > ediff's 100+, but < isearch overlays
4267                              (overlay-put ov 'face 'icicle-search-main-regexp-others))))
4268                        (if thg-end
4269                            ;; $$$$$$
4270                            ;; The correct code here is (setq beg end).  However, unless you use my
4271                            ;; library `thingatpt+.el' or unless Emacs bug #9300 is fixed (hopefully
4272                            ;; in Emacs 24), that will loop forever.  In that case we move forward a
4273                            ;; char to prevent looping, but that means that the position just after
4274                            ;; a THING is considered to be covered by the THING (which is incorrect).
4275                            (setq beg  (if (or (featurep 'thingatpt+) (> emacs-major-version 23))
4276                                           thg-end
4277                                         (1+ thg-end)))
4278                          ;; If visible then no more things - skip to END.
4279                          (unless (icicle-invisible-p beg) (setq beg  end)))))
4280                    (setq last-beg  beg)))
4281                (setq icicle-candidates-alist  (append icicle-candidates-alist (nreverse temp-list))))
4282            (quit (when icicle-search-cleanup-flag (icicle-search-highlight-cleanup)))
4283            (error (when icicle-search-cleanup-flag (icicle-search-highlight-cleanup))
4284                   (error "%s" (error-message-string icicle-search-thing-scan)))))))))
4285
4286 ;; Same as `thgcmd-invisible-p' in `thing-cmds.el'.
4287 (defun icicle-invisible-p (position)
4288   "Return non-nil if the character at POSITION is invisible."
4289   (if (fboundp 'invisible-p)            ; Emacs 22+
4290       (invisible-p position)
4291     (let ((prop  (get-char-property position 'invisible))) ; Overlay or text property.
4292       (if (eq buffer-invisibility-spec t)
4293           prop
4294         (or (memq prop buffer-invisibility-spec) (assq prop buffer-invisibility-spec))))))
4295
4296 (defun icicle-invisible-face-p (face)
4297   "Return non-nil if FACE is currently invisibile."
4298   (and (consp buffer-invisibility-spec)
4299        (or (memq face buffer-invisibility-spec) (assq face buffer-invisibility-spec))))
4300
4301 (defun icicle-next-visible-thing-and-bounds (thing start end)
4302   "Return the next visible THING and its bounds.
4303 Start at BEG and end at END, when searching for THING.
4304 Return (THING THING-START . THING-END), with THING-START and THING-END
4305  the bounds of THING.  Return nil if no such THING is found.
4306
4307 The \"visible\" in the name refers to ignoring things that are within
4308 invisible text, such as hidden comments.
4309
4310 You can toggle hiding of comments using `C-M-;' in the minibuffer, but
4311 depending on when you do so you might need to invoke the current
4312 command again."
4313   (save-excursion (icicle-next-visible-thing thing start end)))
4314
4315 ;;; Simple version of `previous-visible-thing' from `thing-cmds.el'.
4316 ;;;###autoload
4317 (defun icicle-previous-visible-thing (thing start &optional end)
4318   "Same as `icicle-next-visible-thing', except it moves backward."
4319   (interactive
4320    (list (or (and (memq last-command '(icicle-next-visible-thing icicle-previous-visible-thing))
4321                   icicle-last-thing-type)
4322              (prog1 (intern (completing-read "Thing (type): " (icicle-things-alist) nil nil nil nil
4323                                              (symbol-name icicle-last-thing-type)))))
4324          (point)
4325          (if mark-active (min (region-beginning) (region-end)) (point-min))))
4326   (if (interactive-p)
4327       (icicle-with-comments-hidden start end (icicle-next-visible-thing thing start end 'BACKWARD))
4328     (icicle-next-visible-thing thing start end 'BACKWARD)))
4329
4330 ;;; Simple version of `next-visible-thing' from `thing-cmds.el'.
4331 ;;;###autoload
4332 (defun icicle-next-visible-thing (thing &optional start end backward)
4333   "Go to the next visible THING.
4334 Start at START.  If END is non-nil then look no farther than END.
4335 Interactively:
4336  - START is point.
4337  - If the region is not active, END is the buffer end.  If the region
4338    is active, END is the region end: the greater of point and mark.
4339
4340 Ignores (skips) comments if `icicle-ignore-comments-flag' is non-nil.
4341 You can toggle this ignoring of comments using `C-M-;' in the
4342 minibuffer, but depending on when you do so you might need to invoke
4343 the current command again.
4344
4345 If you use this command or `icicle-previous-visible-thing'
4346 successively, even mixing the two, you are prompted for the type of
4347 THING only the first time.  You can thus bind these two commands to
4348 simple, repeatable keys (e.g. `f11', `f12'), to navigate among things
4349 quickly.
4350
4351 Non-interactively, THING is a symbol, and optional arg BACKWARD means
4352 go to the previous thing.
4353
4354 Return (THING THING-START . THING-END), with THING-START and THING-END
4355 the bounds of THING.  Return nil if no such THING is found."
4356   (interactive
4357    (list (or (and (memq last-command '(icicle-next-visible-thing icicle-previous-visible-thing))
4358                   icicle-last-thing-type)
4359              (prog1 (intern (completing-read "Thing (type): " (icicle-things-alist) nil nil nil nil
4360                                              (symbol-name icicle-last-thing-type)))))
4361          (point)
4362          (if mark-active (max (region-beginning) (region-end)) (point-max))))
4363   (setq icicle-last-thing-type  thing)
4364   (unless start (setq start  (point)))
4365   (unless end   (setq end    (if backward (point-min) (point-max))))
4366   (cond ((< start end) (when backward (setq start  (prog1 end (setq end  start)))))
4367         ((> start end) (unless backward (setq start  (prog1 end (setq end  start))))))
4368   (if (interactive-p)
4369       (icicle-with-comments-hidden start end (icicle-next-visible-thing-1 thing start end backward))
4370     (icicle-next-visible-thing-1 thing start end backward)))
4371
4372 ;;; Same as `next-visible-thing-1' in `thing-cmds.el'.
4373 (if (fboundp 'next-visible-thing-1)
4374     (defalias 'icicle-next-visible-thing-1 'next-visible-thing-1)
4375   (defun icicle-next-visible-thing-1 (thing start end backward)
4376     "Helper for `icicle-next-visible-thing'.  Get thing past point."
4377     (let ((thg+bds  (icicle-next-visible-thing-2 thing start end backward)))
4378       (if (not thg+bds)
4379           nil
4380         ;; $$$$$$ Which is better, > or >=, < or <=, for the comparisons?
4381         ;; $$$$$$ (while (and thg+bds
4382         ;;                    (if backward  (> (cddr thg+bds) (point)) (<= (cadr thg+bds) (point))))
4383         (while (and thg+bds  (if backward  (> (cddr thg+bds) (point))  (< (cadr thg+bds) (point))))
4384           (if backward
4385               (setq start  (max end (1- (cadr thg+bds))))
4386             (setq start  (min end (1+ (cddr thg+bds)))))
4387           (setq thg+bds  (icicle-next-visible-thing-2 thing start end backward)))
4388         (when thg+bds (goto-char (cadr thg+bds)))
4389         thg+bds))))
4390
4391 ;;; Same as `next-visible-thing-2' in `thing-cmds.el'.
4392 (if (fboundp 'next-visible-thing-2)
4393     (defalias 'icicle-next-visible-thing-2 'next-visible-thing-2)
4394   (defun icicle-next-visible-thing-2 (thing start end &optional backward)
4395     "Helper for `icicle-next-visible-thing-1'.  Thing might not be past START."
4396     (and (not (= start end))
4397          (save-excursion
4398            (let ((bounds  nil))
4399              ;; If BACKWARD, swap START and END.
4400              (cond ((< start end) (when   backward (setq start  (prog1 end (setq end  start)))))
4401                    ((> start end) (unless backward (setq start  (prog1 end (setq end  start))))))
4402              (catch 'icicle-next-visible-thing-2
4403                (while (if backward (> start end) (< start end))
4404                  (goto-char start)
4405                  ;; Skip invisible text.
4406                  (when (and (if backward (> start end) (< start end)) (icicle-invisible-p start))
4407                    (setq start  (if (get-text-property start 'invisible) ; Text prop.
4408                                     (if backward
4409                                         (previous-single-property-change start 'invisible nil end)
4410                                       (next-single-property-change start 'invisible nil end))
4411                                   (if backward ; Overlay prop.
4412                                       (previous-overlay-change start)
4413                                     (next-overlay-change start))))
4414                    (goto-char start))
4415                  (when (and (setq bounds  (bounds-of-thing-at-point thing))
4416                             (not (equal (car bounds) (cdr bounds)))) ; Not an empty thing, "".
4417                    (throw 'icicle-next-visible-thing-2
4418                      (cons (buffer-substring (car bounds) (cdr bounds)) bounds)))
4419                  (setq start  (if backward (1- start) (1+ start))))
4420                nil))))))
4421
4422 ;;;###autoload
4423 (defun icicle-search-char-property (beg end require-match
4424                                     &optional where prop values predicate)
4425   "Search for text that has a character property with a certain value.
4426 If the property is `face' or `font-lock-face', then you can pick
4427 multiple faces, using completion.  Text is then searched that has a
4428 face property that includes any of the selected faces.  If you choose
4429 no face (empty input), then text with any face is found.
4430
4431 By \"character property\" is meant either an overlay property or a
4432 text property.  If you want to search for only an overlay property or
4433 only a text property, then use `icicle-search-overlay-property' or
4434 `icicle-search-text-property' instead.
4435
4436 Non-interactively, arguments BEG, END, REQUIRE-MATCH, and WHERE are as
4437 for `icicle-search'.  Arguments PROP, VALUES, and PREDICATE are passed
4438 to `icicle-search-char-property-scan' to define the search contexts.
4439
4440 You can alternatively choose to search, not the search contexts as
4441 defined, but the zones of buffer text that do NOT have the given
4442 character property value.  To do this, use `C-M-~' during completion.
4443 \(This is a toggle, and it affects only future search commands, not
4444 the current one.)
4445
4446 This command is intended only for use in Icicle mode.  It is defined
4447 using `icicle-search'.  For more information, in particular for
4448 information about the arguments and the use of a prefix argument to
4449 search multiple regions, buffers, or files, see the doc for command
4450 `icicle-search'."
4451   (interactive (icicle-search-property-args))
4452   (icicle-search beg end 'icicle-search-char-property-scan require-match where prop values nil
4453                  predicate))
4454
4455 ;;;###autoload
4456 (defun icicle-search-overlay-property (beg end require-match &optional where prop values predicate)
4457   "Same as `icicle-search-char-property', except only overlay property.
4458 That is, do not also search a text property."
4459   (interactive (icicle-search-property-args))
4460   (icicle-search beg end 'icicle-search-char-property-scan require-match where prop values 'overlay
4461                  predicate))
4462
4463 ;;;###autoload
4464 (defun icicle-search-text-property (beg end require-match ; Bound to `C-c "'.
4465                                     &optional where prop values predicate)
4466   "Same as `icicle-search-char-property', except only text property.
4467 That is, do not also search an overlay property."
4468   (interactive (icicle-search-property-args))
4469   (icicle-search beg end 'icicle-search-char-property-scan require-match where prop values 'text
4470                  predicate))
4471
4472 (defun icicle-search-property-args ()
4473   "Read and return interactive arguments for `icicle-search-*-property'."
4474   (let* ((where    (icicle-search-where-arg))
4475          (beg+end  (icicle-region-or-buffer-limits))
4476          (beg1     (car beg+end))
4477          (end1     (cadr beg+end))
4478          (props    (mapcar #'(lambda (prop) (list (symbol-name prop)))
4479                            (icicle-char-properties-in-buffers where beg1 end1)))
4480          (prop     (intern (completing-read
4481                             (format "Property %sto search: "
4482                                     (if icicle-search-complement-domain-p "*NOT* " ""))
4483                             props nil nil nil nil "face")))
4484          (values   (if (memq prop '(face font-lock-face))
4485                        (let ((faces  (icicle-face-list)))
4486                          (if faces (mapcar #'intern faces) (face-list))) ; Default: all faces.
4487                      (list (intern (icicle-completing-read-history
4488                                     "Property value: " 'icicle-char-property-value-history))))))
4489     `(,beg1 ,end1 ,(not icicle-show-multi-completion-flag) ,where ,prop ,values)))
4490
4491 (defun icicle-char-properties-in-buffers (where beg end &optional type)
4492   "List of all character properties in WHERE.
4493 The other arguments are passed to `icicle-char-properties-in-buffer'.
4494 Only the character properties are included, not their values.
4495 WHERE is a list of buffers, a list of files, or a list of region
4496   bookmarks (in which case you must also use library `Bookmark+').
4497   If nil, then only the current buffer is used.
4498 TYPE can be `overlay', `text', or nil, meaning overlay properties,
4499 text properties, or both, respectively."
4500   (cond ((and (consp where) (bufferp (car where))) ; List of buffers - search buffers.
4501          (dolist (buf  where) (icicle-char-properties-in-buffer buf nil nil type)))
4502         ((and (consp where)             ; List of files - search files.
4503               (stringp (car where))
4504               (file-exists-p (car where)))
4505          (dolist (file  where)
4506            (icicle-char-properties-in-buffer (find-file-noselect file) nil nil type)))
4507         ((consp where)                  ; Search bookmarked regions.
4508          (unless (require 'bookmark+ nil t) (error "This requires library `Bookmark+'"))
4509          (let (buf+beg buf beg end)
4510            (dolist (bmk  where)
4511              (setq buf+beg  (bookmark-jump-noselect bmk)
4512                    buf      (car buf+beg)
4513                    beg      (cdr buf+beg)
4514                    end      (bmkp-get-end-position bmk))
4515              (when (bufferp buf) (icicle-char-properties-in-buffer (get-buffer buf) beg end type)))))
4516         (t                              ; Search this buffer only.
4517          (icicle-char-properties-in-buffer (current-buffer) beg end type))))
4518
4519 (defun icicle-char-properties-in-buffer (&optional buffer beg end type)
4520   "List of all character properties in BUFFER between BEG and END.
4521 Only the character properties are included, not their values.
4522 TYPE can be `overlay', `text', or nil, meaning overlay properties,
4523 text properties, or both, respectively."
4524   (unless buffer (setq buffer  (current-buffer)))
4525   (let ((props  ())
4526         ovrlays curr-props)
4527     (when (bufferp buffer)              ; Do nothing if BUFFER is not a buffer.
4528       (with-current-buffer buffer
4529         (unless (and beg end)
4530           (setq beg  (point-min)
4531                 end  (point-max)))
4532         (when (or (not type) (eq type 'overlay)) ; Get overlay properties.
4533           (setq ovrlays  (overlays-in beg end))
4534           (dolist (ovrly  ovrlays)
4535             (setq curr-props  (overlay-properties ovrly))
4536             (while curr-props
4537               (unless (memq (car curr-props) props) (push (car curr-props) props))
4538               (setq curr-props  (cddr curr-props)))))
4539         (when (or (not type) (eq type 'text)) ; Get text properties.
4540           (while (< beg end)
4541             (setq beg         (or (next-property-change beg nil end) end)
4542                   curr-props  (text-properties-at beg))
4543             (while curr-props
4544               (unless (memq (car curr-props) props) (push (car curr-props) props))
4545               (setq curr-props  (cddr curr-props)))))))
4546     props))
4547
4548 (defun icicle-search-char-property-scan (buffer beg end prop values type predicate)
4549   "Scan BUFFER from BEG to END for character property PROP with VALUES.
4550 Push hits onto `icicle-candidates-alist'.
4551 If BUFFER is nil, scan the current buffer.
4552 Highlight the matches in face `icicle-search-main-regexp-others'.
4553 If BEG and END are nil, scan entire BUFFER.
4554
4555 Find text with a PROP value that overlaps with VALUES.  That is, if
4556 the value of PROP is an atom, then it must be a member of VALUES; if
4557 it is a list, then at least one list element must be a member of
4558 VALUES.
4559
4560 TYPE is `overlay', `text', or nil, and specifies the type of character
4561 property - nil means look for both overlay and text properties.
4562
4563 If PREDICATE is non-nil, then push only the hits for which it holds.
4564 PREDICATE is nil or a Boolean function that takes these arguments:
4565   - the search-context string
4566   - a marker at the end of the search-context"
4567   (let ((add-bufname-p  (and buffer icicle-show-multi-completion-flag))
4568         (temp-list      ())
4569         (last-beg       nil)
4570         (zone-end       nil))
4571     (unless buffer (setq buffer  (current-buffer)))
4572     (when (bufferp buffer)              ; Do nothing if BUFFER is not a buffer.
4573       (with-current-buffer buffer
4574         (unless (and beg end) (setq beg  (point-min)
4575                                     end  (point-max)))
4576         (icicle-condition-case-no-debug icicle-search-char-property-scan
4577             (save-excursion
4578               (setq last-beg  beg)
4579               (while (and (< beg end)
4580                           (let* ((charval  (and (or (not type) (eq type 'overlay))
4581                                                 (get-char-property beg prop)))
4582                                  (textval  (and (or (not type) (eq type 'text))
4583                                                 (get-text-property beg prop)))
4584                                  (currval  (icicle-flat-list charval textval)))
4585                             (not (icicle-set-intersection values currval))))
4586                 (setq beg  (icicle-next-single-char-property-change beg prop nil end)))
4587               (while (and beg  (< last-beg end))
4588                 (setq zone-end  (or (icicle-next-single-char-property-change beg prop nil end) end))
4589                 (let* ((hit-beg     (if icicle-search-complement-domain-p
4590                                         last-beg
4591                                       beg))
4592                        (hit-end     (if icicle-search-complement-domain-p
4593                                           beg
4594                                         zone-end))
4595                        (hit-string  (buffer-substring-no-properties hit-beg hit-end))
4596                        end-marker)
4597                   (when (and (not (string= "" hit-string)) ; Do nothing if empty hit.
4598                              (setq end-marker  (copy-marker hit-end))
4599                              (or (not predicate)
4600                                  (save-match-data (funcall predicate hit-string end-marker))))
4601                     (icicle-candidate-short-help
4602                      (concat (and add-bufname-p
4603                                   (format "Buffer: `%s', " (buffer-name (marker-buffer end-marker))))
4604                              (format "Position: %d, Length: %d"
4605                                      (marker-position end-marker) (length hit-string)))
4606                      hit-string)
4607                     (push (cons (if add-bufname-p
4608                                     (list hit-string
4609                                           (let ((string  (copy-sequence (buffer-name))))
4610                                             (put-text-property 0 (length string)
4611                                                                'face 'icicle-candidate-part string)
4612                                             string))
4613                                   hit-string)
4614                                 end-marker)
4615                           temp-list)
4616                     ;; Highlight search context in buffer.
4617                     (when (and (<= (+ (length temp-list) (length icicle-candidates-alist))
4618                                    icicle-search-highlight-threshold))
4619                       (let ((ov  (make-overlay hit-beg hit-end)))
4620                         (push ov icicle-search-overlays)
4621                         (overlay-put ov 'priority 200) ; > ediff's 100+, but < isearch overlays
4622                         (overlay-put ov 'face 'icicle-search-main-regexp-others)))))
4623                 (setq beg       zone-end
4624                       last-beg  zone-end)
4625                 (while (and (< beg end)
4626                             (let* ((charval  (and (or (not type) (eq type 'overlay))
4627                                                   (get-char-property beg prop)))
4628                                    (textval  (and (or (not type) (eq type 'text))
4629                                                   (get-text-property beg prop)))
4630                                    (currval  (icicle-flat-list charval textval)))
4631                               (not (icicle-set-intersection values currval))))
4632                   (setq beg  (icicle-next-single-char-property-change beg prop nil end))))
4633               (setq icicle-candidates-alist  (append icicle-candidates-alist (nreverse temp-list))))
4634           (quit (when icicle-search-cleanup-flag (icicle-search-highlight-cleanup)))
4635           (error (when icicle-search-cleanup-flag (icicle-search-highlight-cleanup))
4636                  (error "%s" (error-message-string icicle-search-char-property-scan))))))))
4637
4638 (defun icicle-flat-list (val1 val2)
4639   "Return a flat list with all values in VAL1 and VAL2."
4640   (let ((result  nil))
4641     (unless (listp val1) (setq val1  (list val1)))
4642     (unless (listp val2) (setq val2  (list val2)))
4643     (while val1 (add-to-list 'result (pop val1)))
4644     (while val2 (add-to-list 'result (pop val2)))
4645     result))
4646
4647 ;; Same as `thgcmd-next-single-char-property-change' in `thing-cmds.el'.
4648 (if (fboundp 'next-single-char-property-change)
4649     (defalias 'icicle-next-single-char-property-change 'next-single-char-property-change)
4650   (defun icicle-next-single-char-property-change (position prop &optional object limit)
4651     "Position of next change of PROP for text property or overlay change.
4652 Scans characters forward from buffer position POSITION until property
4653 PROP changes.  Returns the position of that change.
4654
4655 POSITION is a buffer position (integer or marker).
4656
4657 Optional third arg OBJECT is ignored.  It is present for compatibility
4658  with Emacs 22+.
4659
4660 If optional fourth arg LIMIT is non-nil, search stops at position
4661 LIMIT.  LIMIT is returned if nothing is found before reaching LIMIT.
4662
4663 The property values are compared with `eq'.  If the property is
4664 constant all the way to the end of the buffer, then return the last
4665 valid buffer position."
4666     (save-excursion
4667       (goto-char position)
4668       (let ((propval  (get-char-property (point) prop))
4669             (end      (min limit (point-max))))
4670         (while (and (< (point) end) (eq (get-char-property (point) prop) propval))
4671           (goto-char (min (next-overlay-change (point))
4672                           (next-single-property-change (point) prop nil end)))))
4673       (point))))
4674
4675 ;; Same as `thgcmd-previous-single-char-property-change' in `thing-cmds.el'.
4676 (if (fboundp 'previous-single-char-property-change)
4677     (defalias 'icicle-previous-single-char-property-change 'previous-single-char-property-change)
4678   (defun icicle-previous-single-char-property-change (position prop &optional object limit)
4679     "Position of previous change of PROP for text property or overlay change.
4680 Scans characters backward from buffer position POSITION until property
4681 PROP changes.  Returns the position of that change.
4682
4683 POSITION is a buffer position (integer or marker).
4684
4685 Optional third arg OBJECT is ignored.  It is present for compatibility
4686  with Emacs 22+.
4687
4688 If optional fourth arg LIMIT is non-nil, search stops at position
4689 LIMIT.  LIMIT is returned if nothing is found before reaching LIMIT.
4690
4691 The property values are compared with `eq'.  If the property is
4692 constant all the way to the start of the buffer, then return the first
4693 valid buffer position."
4694     (save-excursion
4695       (goto-char position)
4696       (let ((propval  (get-char-property (point) prop))
4697             (end      (max limit (point-min))))
4698         (while (and (> (point) end) (eq (get-char-property (point) prop) propval))
4699           (goto-char (max (next-overlay-change (point))
4700                           (next-single-property-change (point) prop nil end)))))
4701       (point))))
4702
4703 ;;;###autoload
4704 (defun icicle-search-highlight-cleanup ()
4705   "Remove all highlighting from the last use of `icicle-search'."
4706   (interactive)
4707   (let ((inhibit-quit  t))
4708     (message "Removing search highlighting...")
4709     (while icicle-search-overlays
4710       (delete-overlay (car icicle-search-overlays))
4711       (setq icicle-search-overlays  (cdr icicle-search-overlays)))
4712     (while icicle-search-level-overlays
4713       (delete-overlay (car icicle-search-level-overlays))
4714       (setq icicle-search-level-overlays  (cdr icicle-search-level-overlays)))
4715     (when (overlayp icicle-search-current-overlay)
4716       (delete-overlay icicle-search-current-overlay))
4717     (when (overlayp icicle-search-refined-overlays)
4718       (delete-overlay icicle-search-refined-overlays)
4719       (setq icicle-search-refined-overlays  ()))
4720     (while icicle-search-refined-overlays
4721       (delete-overlay (car icicle-search-refined-overlays))
4722       (setq icicle-search-refined-overlays  (cdr icicle-search-refined-overlays)))
4723     (message "Removing search highlighting...done")))
4724
4725 ;;;###autoload
4726 (defun icicle-search-word (beg end word-regexp require-match ; Bound to `C-c $'.
4727                            &optional where &rest args)
4728   "Search for a whole word.
4729 The search string is regarded as a whole word, but a \"word\" here can
4730 contain embedded strings of non word-constituent chars (they are
4731 skipped over, when matching, included in the match), and any leading
4732 or trailing word-constituent chars in the search string are dropped
4733 \(ignored for matching, not included in the match): matches begin and
4734 end on a word boundary.
4735
4736 At the prompt for a word, you can use completion against previous
4737 Icicles search inputs to choose the word, or you can enter a new word.
4738
4739 Non-interactively, WORD-REGEXP should be a regexp that matches a word.
4740 The other arguments are the same as for `icicle-search'.
4741
4742 You can alternatively choose to search, not the word search contexts
4743 you define, but the buffer text that is outside these contexts: the
4744 non-word text.  To do this, use `C-M-~' during completion.  \(This is
4745 a toggle, and it affects only future search commands, not the current
4746 one.)
4747
4748 This command is intended only for use in Icicle mode.  It is defined
4749 using `icicle-search'.  For more information, in particular for
4750 information about the arguments and the use of a prefix argument to
4751 search multiple regions, buffers, or files, see the doc for command
4752 `icicle-search'."
4753   (interactive `(,@(icicle-region-or-buffer-limits)
4754                  ,(icicle-search-read-word)
4755                  ,(not icicle-show-multi-completion-flag)
4756                  ,(icicle-search-where-arg)))
4757   (icicle-search beg end word-regexp (not icicle-show-multi-completion-flag) where))
4758
4759 ;;;###autoload
4760 (defun icicle-search-bookmarks-together (scan-fn-or-regexp require-match &rest args)
4761   "Search bookmarked regions (together).
4762 The arguments are the same as for `icicle-search', but without
4763 arguments BEG, END, and WHERE.
4764
4765 This is the same as using a plain prefix arg, `C-u', with
4766 `icicle-search'.
4767
4768 You first choose all of the bookmarked buffers/regions to search.
4769 Then your input is matched against a multi-completion composed of (a)
4770 the region text that matches the context regexp and (b) the region's
4771 buffer name.
4772
4773 You can alternatively choose to search, not the search contexts as
4774 defined by the context regexp, but the non-contexts, that is, the text
4775 in the bookmarked buffer that does not match the regexp.  To do this,
4776 use `C-M-~' during completion.  (This is a toggle, and it affects only
4777 future search commands, not the current one.)
4778
4779 An alternative is multi-command `icicle-search-bookmark', which
4780 searches the bookmarked regions/buffers you choose one at a time."
4781   (interactive `(,(if icicle-search-whole-word-flag
4782                       (icicle-search-read-word)
4783                       (icicle-search-read-context-regexp))
4784                  ,(not icicle-show-multi-completion-flag)))
4785   (apply #'icicle-search nil nil scan-fn-or-regexp require-match
4786          (let ((current-prefix-arg  '(4))) (icicle-search-where-arg))
4787          args))
4788
4789 ;;;###autoload
4790 (defun icicle-search-buffer (scan-fn-or-regexp require-match &rest args)
4791   "Search multiple buffers completely.
4792 Same as using a non-negative numeric prefix arg, such as `C-9', with
4793 `icicle-search'.  You are prompted for the buffers to search.  All of
4794 each buffer is searched.  Any existing buffers can be chosen.
4795 Arguments are the same as for `icicle-search', but without arguments
4796 BEG, END, and WHERE.
4797
4798 You can alternatively choose to search, not the search contexts as
4799 defined by the context regexp you provide, but the non-contexts, that
4800 is, the text in the buffers that does not match the regexp.  To do
4801 this, use `C-M-~' during completion.  (This is a toggle, and it
4802 affects only future search commands, not the current one.)"
4803   (interactive `(,(if icicle-search-whole-word-flag
4804                       (icicle-search-read-word)
4805                       (icicle-search-read-context-regexp))
4806                  ,(not icicle-show-multi-completion-flag)))
4807   (apply #'icicle-search nil nil scan-fn-or-regexp require-match
4808          (let ((icicle-show-Completions-initially-flag  t))
4809            (mapcar #'get-buffer (let ((icicle-buffer-require-match-flag  'partial-match-ok))
4810                                   (icicle-buffer-list))))
4811          args))
4812
4813 ;;;###autoload
4814 (defun icicle-search-file (scan-fn-or-regexp require-match &rest args)
4815   "Search multiple files completely.
4816 Same as using a negative numeric prefix arg, such as `C--', with
4817 `icicle-search'.  You are prompted for the files to search.  All of
4818 each file is searched.  Any existing files in the current directory
4819 can be chosen.  Arguments are the same as for `icicle-search', but
4820 without arguments BEG, END, and WHERE.
4821
4822 You can alternatively choose to search, not the search contexts as
4823 defined by the context regexp you provide, but the non-contexts, that
4824 is, the text in the files that does not match the regexp.  To do this,
4825 use `C-M-~' during completion.  (This is a toggle, and it affects only
4826 future search commands, not the current one.)"
4827   (interactive `(,(if icicle-search-whole-word-flag
4828                       (icicle-search-read-word)
4829                       (icicle-search-read-context-regexp))
4830                  ,(not icicle-show-multi-completion-flag)))
4831   (apply #'icicle-search nil nil scan-fn-or-regexp require-match
4832          (let ((icicle-show-Completions-initially-flag  t)) (icicle-file-list))
4833          args))
4834
4835 ;;;###autoload
4836 (defun icicle-search-bookmark-list-marked (scan-fn-or-regexp require-match &rest args)
4837   "Search the files of the marked bookmarks in `*Bookmark List*'.
4838 Arguments are the same as for `icicle-search', but without arguments
4839 BEG, END, and WHERE."
4840   (interactive `(,(if icicle-search-whole-word-flag
4841                       (icicle-search-read-word)
4842                       (icicle-search-read-context-regexp))
4843                  ,(not icicle-show-multi-completion-flag)))
4844   (unless (fboundp 'bmkp-bmenu-get-marked-files)
4845     (error "Command `icicle-bookmark-save-marked-files' requires library Bookmark+"))
4846   (bmkp-bmenu-barf-if-not-in-menu-list)
4847   (apply #'icicle-search nil nil scan-fn-or-regexp require-match (bmkp-bmenu-get-marked-files) args))
4848
4849 ;;;###autoload
4850 (defun icicle-search-dired-marked (scan-fn-or-regexp require-match &rest args)
4851   "Search the marked files in Dired.
4852 Arguments are the same as for `icicle-search', but without arguments
4853 BEG, END, and WHERE."
4854   (interactive `(,(if icicle-search-whole-word-flag
4855                       (icicle-search-read-word)
4856                       (icicle-search-read-context-regexp))
4857                  ,(not icicle-show-multi-completion-flag)))
4858   (unless (eq major-mode 'dired-mode)
4859     (error "Command `icicle-search-dired-marked' must be called from a Dired buffer"))
4860   (apply #'icicle-search nil nil scan-fn-or-regexp require-match (dired-get-marked-files) args))
4861
4862 ;;;###autoload
4863 (defun icicle-search-ibuffer-marked (scan-fn-or-regexp require-match &rest args)
4864   "Search the marked buffers in Ibuffer, in order.
4865 Arguments are the same as for `icicle-search', but without arguments
4866 BEG, END, and WHERE."
4867   (interactive `(,(if icicle-search-whole-word-flag
4868                       (icicle-search-read-word)
4869                       (icicle-search-read-context-regexp))
4870                  ,(not icicle-show-multi-completion-flag)))
4871   (unless (eq major-mode 'ibuffer-mode)
4872     (error "Command `icicle-search-ibuffer-marked' must be called from an Ibuffer buffer"))
4873   (let ((marked-bufs (nreverse (ibuffer-get-marked-buffers))))
4874     (unless marked-bufs (setq marked-bufs  (list (ibuffer-current-buffer t))))
4875     (apply #'icicle-search nil nil scan-fn-or-regexp require-match marked-bufs args)))
4876
4877 ;;;###autoload
4878 (defun icicle-search-buff-menu-marked (scan-fn-or-regexp require-match &rest args)
4879   "Search the marked buffers in Buffer Menu, in order.
4880 Arguments are the same as for `icicle-search', but without arguments
4881 BEG, END, and WHERE."
4882   (interactive `(,(if icicle-search-whole-word-flag
4883                       (icicle-search-read-word)
4884                       (icicle-search-read-context-regexp))
4885                  ,(not icicle-show-multi-completion-flag)))
4886   (unless (eq major-mode 'Buffer-menu-mode)
4887     (error "Command `icicle-search-buff-menu-marked' must be called from a Buffer Menu buffer"))
4888   (let ((marked-bufs  ()))
4889     (save-excursion
4890       (Buffer-menu-beginning)
4891       (while (re-search-forward "^>" nil t) (push (Buffer-menu-buffer t) marked-bufs)))
4892     (setq marked-bufs  (nreverse marked-bufs))
4893     (unless marked-bufs (setq marked-bufs  (list (Buffer-menu-buffer t))))
4894     (apply #'icicle-search nil nil scan-fn-or-regexp require-match marked-bufs args)))
4895
4896 ;;;###autoload
4897 (defalias 'icicle-search-lines 'icicle-occur)
4898 ;;;###autoload
4899 (defun icicle-occur (beg end &optional buffers) ; Bound to `C-c ''.
4900   "`icicle-search' with a regexp of \".*\".  An `occur' with icompletion.
4901 Type a regexp to match within each line of one or more buffers.  Use
4902 `S-TAB' to show matching lines.  Use `C-RET' or `C-mouse-2' to go to
4903 the line of the current candidate.  Use `C-down', `C-up', `C-next',
4904 `C-prior', `C-end', or `C-home', to cycle among the matching lines.
4905
4906 By default, search only the current buffer.  Search the active region,
4907 or, if none, the entire buffer.  With a prefix argument, you are
4908 prompted for the buffers to search.  You can choose buffers using
4909 completion (`C-RET' and so on).  If the prefix argument is 99, then
4910 only buffers visiting files are candidates.
4911
4912 You can use `M-*' to further narrow the match candidates, typing
4913 additional regexps to match.
4914
4915 This command is intended only for use in Icicle mode.  It is defined
4916 using `icicle-search'.  For more information, see the doc for command
4917 `icicle-search'."
4918   (interactive `(,@(icicle-region-or-buffer-limits)
4919                  ,(and current-prefix-arg
4920                        (icicle-search-choose-buffers (= 99 (prefix-numeric-value
4921                                                             current-prefix-arg))))))
4922   (let ((fg (face-foreground        'icicle-search-main-regexp-others))
4923         (bg (face-background        'icicle-search-main-regexp-others))
4924         (icicle-transform-function  (if (interactive-p) nil icicle-transform-function)))
4925     (unwind-protect
4926          (progn (set-face-foreground 'icicle-search-main-regexp-others nil)
4927                 (set-face-background 'icicle-search-main-regexp-others nil)
4928                 (icicle-search beg end ".*" (not icicle-show-multi-completion-flag) buffers))
4929       (when icicle-search-cleanup-flag (icicle-search-highlight-cleanup))
4930       (set-face-foreground 'icicle-search-main-regexp-others fg)
4931       (set-face-background 'icicle-search-main-regexp-others bg))))
4932
4933 ;;;###autoload
4934 (defun icicle-search-sentences (beg end &optional buffers)
4935   "`icicle-search' with sentences as contexts.
4936 Type a regexp to match within each sentence of one or more buffers.
4937 Use `S-TAB' to show matching sentences.  Use `C-RET' or `C-mouse-2' to
4938 go to the line of the current candidate.  Use `C-down', `C-up',
4939 `C-next', `C-prior', `C-end', or `C-home' to cycle among the matching
4940 sentences.
4941
4942 By default, search only the current buffer.  Search the active region,
4943 or, if none, the entire buffer.  With a prefix argument, you are
4944 prompted for the buffers to search.  You can choose buffers using
4945 completion (`C-RET' and so on).  If the prefix argument is 99, then
4946 only buffers visiting files are candidates.
4947
4948 You can use `M-*' to further narrow the match candidates, typing
4949 additional regexps to match.
4950
4951 You can alternatively choose to search, not the search contexts
4952 \(sentences), but the non-sentences, that is, the text in the buffer
4953 that is outside sentences.  To do this, use `C-M-~' during completion.
4954 \(This is a toggle, and it affects only future search commands, not
4955 the current one.)
4956
4957 This command is intended only for use in Icicle mode.  It is defined
4958 using `icicle-search'.  For more information, see the doc for command
4959 `icicle-search'."
4960   (interactive `(,@(icicle-region-or-buffer-limits)
4961                  ,(and current-prefix-arg
4962                        (icicle-search-choose-buffers (= 99 (prefix-numeric-value
4963                                                             current-prefix-arg))))))
4964   (let ((fg (face-foreground        'icicle-search-main-regexp-others))
4965         (bg (face-background        'icicle-search-main-regexp-others))
4966         (icicle-transform-function  (if (interactive-p) nil icicle-transform-function)))
4967     (unwind-protect
4968          (progn (set-face-foreground 'icicle-search-main-regexp-others nil)
4969                 (set-face-background 'icicle-search-main-regexp-others nil)
4970                 (icicle-search beg end (concat "[A-Z][^.?!]+[.?!]")
4971                                (not icicle-show-multi-completion-flag) buffers))
4972       (when icicle-search-cleanup-flag (icicle-search-highlight-cleanup))
4973       (set-face-foreground 'icicle-search-main-regexp-others fg)
4974       (set-face-background 'icicle-search-main-regexp-others bg))))
4975
4976 ;;;###autoload
4977 (defun icicle-search-paragraphs (beg end &optional buffers)
4978   "`icicle-search' with paragraphs as contexts.
4979 Type a regexp to match within each paragraph of one or more buffers.
4980 Use `S-TAB' to show matching paragraphs.  Use `C-RET' or `C-mouse-2'
4981 to go to the line of the current candidate.  Use `C-down', `C-up',
4982 `C-next', `C-prior', `C-end', or `C-home' to cycle among the matching
4983 paragraphs.
4984
4985 By default, search only the current buffer.  Search the active region,
4986 or, if none, the entire buffer.  With a prefix argument, you are
4987 prompted for the buffers to search.  You can choose buffers using
4988 completion (`C-RET' and so on).  If the prefix argument is 99, then
4989 only buffers visiting files are candidates.
4990
4991 You can use `M-*' to further narrow the match candidates, typing
4992 additional regexps to match.
4993
4994 This command is intended only for use in Icicle mode.  It is defined
4995 using `icicle-search'.  For more information, see the doc for command
4996 `icicle-search'."
4997   (interactive `(,@(icicle-region-or-buffer-limits)
4998                  ,(and current-prefix-arg
4999                        (icicle-search-choose-buffers (= 99 (prefix-numeric-value
5000                                                             current-prefix-arg))))))
5001   (let ((fg (face-foreground        'icicle-search-main-regexp-others))
5002         (bg (face-background        'icicle-search-main-regexp-others))
5003         (icicle-transform-function  (if (interactive-p) nil icicle-transform-function)))
5004     (unwind-protect
5005          (progn (set-face-foreground 'icicle-search-main-regexp-others nil)
5006                 (set-face-background 'icicle-search-main-regexp-others nil)
5007                 (icicle-search beg end "\\(.+\n\\)+"
5008                                (not icicle-show-multi-completion-flag) buffers))
5009       (when icicle-search-cleanup-flag (icicle-search-highlight-cleanup))
5010       (set-face-foreground 'icicle-search-main-regexp-others fg)
5011       (set-face-background 'icicle-search-main-regexp-others bg))))
5012
5013 ;;;###autoload
5014 (defun icicle-search-pages (beg end &optional buffers)
5015   "`icicle-search' with pages as contexts.
5016 Type a regexp to match within each page of one or more buffers.  Use
5017 `S-TAB' to show matching page.  Use `C-RET' or `C-mouse-2' to go to
5018 the line of the current candidate.  Use `C-down', `C-up', `C-next',
5019 `C-prior', `C-end', or `C-home', to cycle among the matching pages.
5020
5021 By default, search only the current buffer.  Search the active region,
5022 or, if none, the entire buffer.  With a prefix argument, you are
5023 prompted for the buffers to search.  You can choose buffers using
5024 completion (`C-RET' and so on).  If the prefix argument is 99, then
5025 only buffers visiting files are candidates.
5026
5027 You can use `M-*' to further narrow the match candidates, typing
5028 additional regexps to match.
5029
5030 This command is intended only for use in Icicle mode.  It is defined
5031 using `icicle-search'.  For more information, see the doc for command
5032 `icicle-search'."
5033   (interactive `(,@(icicle-region-or-buffer-limits)
5034                  ,(and current-prefix-arg
5035                        (icicle-search-choose-buffers (= 99 (prefix-numeric-value
5036                                                             current-prefix-arg))))))
5037   (let ((fg (face-foreground        'icicle-search-main-regexp-others))
5038         (bg (face-background        'icicle-search-main-regexp-others))
5039         (icicle-transform-function  (if (interactive-p) nil icicle-transform-function)))
5040     (unwind-protect
5041          (progn (set-face-foreground 'icicle-search-main-regexp-others nil)
5042                 (set-face-background 'icicle-search-main-regexp-others nil)
5043                 (icicle-search beg end "\\([^\f]*[\f]\\|[^\f]+$\\)"
5044                                (not icicle-show-multi-completion-flag) buffers))
5045       (when icicle-search-cleanup-flag (icicle-search-highlight-cleanup))
5046       (set-face-foreground 'icicle-search-main-regexp-others fg)
5047       (set-face-background 'icicle-search-main-regexp-others bg))))
5048
5049 ;;;###autoload
5050 (defun icicle-comint-search (beg end)   ; Bound to `C-x `' in `comint-mode'.
5051   "Use `icicle-search' to pick up a previous input for reuse.
5052 Use this in a `comint-mode' buffer, such as *shell* or
5053 *inferior-lisp*.  This searches your interactive history in the buffer
5054 for a match to your current input, which you can change dynamically.
5055 When you choose a previous input, it is copied to the current prompt,
5056 for reuse.  If the region is active, then only it is searched;
5057 otherwise, the entire buffer is searched.
5058
5059 Use `C-RET' or `C-mouse-2' to choose a previous input for reuse.  Use
5060 `down', `up', `next', `prior', `end', or `home' to cycle among your
5061 previous inputs.  (You probably do NOT want to use `C-next' etc.,
5062 since such keys will not only cycle to another candidate but also
5063 reuse it immediately.)
5064
5065 As for other Icicles search commands, your current input narrows the
5066 set of possible candidates.  See `icicle-search' for more
5067 information.
5068
5069 You can use `M-*' to further narrow the match candidates, typing
5070 additional regexps to match.
5071
5072 Note that previous commands are identified by looking through the
5073 shell buffer for a shell prompt.  This is not foolproof.  If, for
5074 instance you use command `ls', the output includes an auto-save file
5075 such as #foo.el#, and `#' in the first column represents a shell
5076 prompt, then #foo.el# will be misinterpreted as a previous command.
5077
5078 Also, depending on your shell, you might want to customize variables
5079 such as the following:
5080
5081 `shell-prompt-pattern',`telnet-prompt-pattern'.
5082
5083 Being a search command, `icicle-comint-search' cannot give you access
5084 to previous shell commands that are not visible in the current buffer.
5085 See also \\<comint-mode-map>\\[icicle-comint-command] for another way to reuse commands,
5086 including those from previous sessions.
5087
5088 This command is intended only for use in Icicle mode.  It is defined
5089 using `icicle-search'.  For more information, in particular for
5090 information about the arguments, see the doc for command
5091 `icicle-search'."
5092   ;; $$$$$$ It would be good to somehow rebind C-next etc. to just what next etc. does.
5093   (interactive (icicle-region-or-buffer-limits))
5094   ;; Is there a better test we can use, to make sure the current mode inherits from `comint-mode'?
5095   (unless (where-is-internal 'comint-send-input (keymap-parent (current-local-map)))
5096     (error "Current mode must be derived from comint mode"))
5097   (let ((orig-search-hook           icicle-search-hook)
5098         (icicle-transform-function  'icicle-remove-duplicates))
5099     (add-hook 'icicle-search-hook 'icicle-comint-search-send-input)
5100     (unwind-protect
5101          (icicle-search beg end
5102                         (concat comint-prompt-regexp "\\S-.*") nil) ; Match not required (edit).
5103       (remove-hook 'icicle-search-hook 'icicle-comint-search-send-input)))
5104   (goto-char (point-max))
5105   (unless (pos-visible-in-window-p) (recenter icicle-recenter)))
5106
5107 (defun icicle-comint-search-send-input ()
5108   "Grab current completion input and use that for comint input."
5109   (unless (comint-check-proc (current-buffer))
5110     (error "No live process associated with this buffer"))
5111   (let ((comint-get-old-input
5112          (if (minibuffer-window-active-p (minibuffer-window))
5113              'icicle-comint-search-get-minibuffer-input ; Use minibuffer input (e.g. for action fn).
5114            'icicle-comint-search-get-final-choice))) ; Use final choice.
5115     (comint-copy-old-input))
5116   (comint-send-input))
5117
5118 (defun icicle-comint-search-get-minibuffer-input ()
5119   "Return the minibuffer input, beyond the prompt."
5120   (let* ((cand         (icicle-minibuf-input))
5121          (input-start  (and (string-match comint-prompt-regexp cand) (match-end 0))))
5122     (if input-start (substring cand input-start) cand)))
5123
5124 (defun icicle-comint-search-get-final-choice ()
5125   "Return the final choice, beyond the prompt."
5126   (let ((input-start  (and (string-match comint-prompt-regexp icicle-explore-final-choice)
5127                            (match-end 0))))
5128     (if input-start
5129         (substring icicle-explore-final-choice input-start)
5130       icicle-explore-final-choice)))
5131
5132 ;;;###autoload (autoload 'icicle-comint-command "icicles-cmd2.el")
5133 (icicle-define-command icicle-comint-command ; Bound to `C-c TAB' in `comint-mode'.
5134   "Retrieve a previously used command.
5135 Use this in a `comint-mode' buffer such as `*shell*' or
5136 `*inferior-lisp*'.
5137
5138 Note, depending on your shell, you might want to customize variables
5139 such as the following:
5140
5141 `shell-prompt-pattern',`telnet-prompt-pattern'.
5142
5143 See also \\<comint-mode-map>\\[icicle-comint-search] for another way to reuse commands." ; Doc string
5144   insert                                ; Action function
5145   "Choose a previous command: "         ; `completing-read' args
5146   (mapcar #'list (cddr comint-input-ring)) nil nil nil 'shell-command-history
5147   (aref (cddr comint-input-ring) 0) nil
5148   ((icicle-transform-function  'icicle-remove-duplicates))) ; Bindings
5149
5150 (defun icicle-comint-hook-fn ()
5151   "Hook to set up Comint mode for Icicles."
5152   (set (make-local-variable 'icicle-search-command) 'icicle-comint-search))
5153
5154 ;;;###autoload
5155 (defun icicle-compilation-search (beg end) ; Bound to `C-c `' in `compilation(-minor)-mode'.
5156   "Like `icicle-search', but show the matching compilation-buffer hit.
5157 Use this in a compilation buffer, such as `*grep*', searching for a
5158 regexp as with `icicle-search'.  Use `C-RET' or `C-mouse-2' to show
5159 the target-buffer hit corresponding to the current completion
5160 candidate.  Use `C-down', `C-up', `C-next', `C-prior', `C-end', or
5161 `C-home' to cycle among the target-buffer hits.
5162
5163 As for `icicle-search', you can further narrow the match candidates by
5164 typing a second regexp to search for among the first matches.  See
5165 `icicle-search' for more information.
5166
5167 Altogether, using this with `grep' gives you two or three levels of
5168 regexp searching: 1) the `grep' regexp, 2) the major `icicle-search'
5169 regexp, and optionally 3) the refining `icicle-search' regexp.
5170
5171 In Emacs 22 and later, you can replace search-hit text, as in
5172 `icicle-search'.  In earlier Emacs versions, you cannot replace text.
5173
5174 This command is intended only for use in Icicle mode.  It is defined
5175 using `icicle-search'.  For more information, in particular for
5176 information about the arguments, see the doc for command
5177 `icicle-search'."
5178   (interactive (icicle-region-or-buffer-limits))
5179   (unless (condition-case nil (eq (current-buffer) (compilation-find-buffer)) (error nil))
5180     (error "Current buffer must be a compilation buffer"))
5181   (save-excursion (goto-char (point-min))
5182                   (compilation-next-error 1)
5183                   (setq beg  (if beg (max beg (point)) (point))))
5184   (let ((icicle-transform-function    (if (interactive-p) nil icicle-transform-function))
5185         (icicle-candidate-alt-action-fn
5186          (if (boundp 'compilation-highlight-overlay) ; Emacs 22 test.
5187              icicle-candidate-alt-action-fn
5188            #'(lambda (cand)
5189                (message "Cannot replace matching text in Emacs before version 22"))))
5190         (next-error-highlight
5191          ;; Highlight indefinitely.  `until-move' should be part of Emacs (patch sent), but it's not.
5192          (if (and (featurep 'compile+) (featurep 'simple+)) 'until-move 1000000))
5193         (icicle-search-in-context-fn  'icicle-compilation-search-in-context-fn)
5194         (fg (face-foreground          'icicle-search-main-regexp-others))
5195         (bg (face-background          'icicle-search-main-regexp-others)))
5196     (unwind-protect
5197          (progn
5198            (set-face-foreground 'icicle-search-main-regexp-others nil)
5199            (set-face-background 'icicle-search-main-regexp-others nil)
5200            (icicle-search beg end ".*" t))
5201       (set-face-foreground 'icicle-search-main-regexp-others fg)
5202       (set-face-background 'icicle-search-main-regexp-others bg))))
5203
5204 (defun icicle-compilation-search-in-context-fn (cand+mrker replace-string)
5205   "`icicle-search-in-context-fn' used for `icicle-compilation-search'.
5206 If `crosshairs.el' is loaded, then the target position is highlighted."
5207   (if (not (fboundp 'compilation-next-error-function))
5208       (compile-goto-error)              ; Emacs 20, 21.
5209     (setq compilation-current-error  (point)) ; Emacs 22+.
5210     (compilation-next-error-function 0 nil))
5211   (save-excursion
5212     (save-restriction
5213       (let ((inhibit-field-text-motion  t)) ; Just to be sure, for `end-of-line'.
5214         (narrow-to-region (progn (beginning-of-line) (point)) (progn (end-of-line) (point))))
5215       (icicle-search-highlight-and-maybe-replace cand+mrker replace-string)))
5216   (when (fboundp 'crosshairs-highlight) (crosshairs-highlight 'line-only 'nomsg))
5217   (let ((icicle-candidate-nb  icicle-candidate-nb)) (icicle-complete-again-update)))
5218
5219 (defun icicle-compilation-hook-fn ()
5220   "Hook setting `icicle-search-command' for compilation modes.
5221 Used on `compilation-mode-hook' and `compilation-minor-mode-hook'."
5222   (set (make-local-variable 'icicle-search-command) 'icicle-compilation-search))
5223
5224 ;;;###autoload
5225 (defun icicle-search-w-isearch-string (&optional use-context-p) ; Bound to `S-TAB' in Isearch.
5226   "Icicles-search the buffer using an Isearch string chosen by completion.
5227 The Isearch string you choose is used as the Icicles search context.
5228 You can navigate among its occurrences or search within those
5229 occurrences for a subpattern.
5230
5231 For Emacs 22 and later, if option `isearch-allow-scroll' is non-nil
5232 then a prefix argument changes the behavior, as follows:
5233
5234 1. You are prompted for an Icicles search-context regexp.
5235 2. You choose an Isearch string using completion.  It is copied to the
5236    `kill-ring'.
5237 3. You can yank that string anytime during Icicles search, to search
5238    for it within the search contexts defined by the regexp matches."
5239   (interactive "P")
5240   (isearch-done)
5241   (if (or (not use-context-p) (not (boundp 'isearch-allow-scroll)))
5242       (icicle-search (point-min) (point-max) (icicle-isearch-complete-past-string) t)
5243     (let ((regexp  (icicle-search-read-context-regexp)))
5244       (kill-new (icicle-isearch-complete-past-string))
5245       (icicle-search (point-min) (point-max) regexp t))))
5246
5247 ;;;###autoload
5248 (defalias 'icicle-search-defs 'icicle-imenu)
5249 ;;;###autoload
5250 (defun icicle-imenu (beg end require-match &optional where) ; Bound to `C-c ='.
5251   "Search/go to an Imenu entry using `icicle-search'.
5252 Recommended: Use library `imenu+.el' also.
5253 In Emacs-Lisp mode, `imenu+.el' classifies definitions using these
5254 submenus:
5255
5256  1. Keys         - keys in the global keymap
5257  2. Keys in Maps - keys in keymaps other than global keymap
5258  3. Functions    - functions, whether interactive or not
5259  4. Macros       - macros defined with `defmacro'
5260  5. User Options - user variables, from `defcustom'
5261  6. Variables    - other variables (non-options), from `defvar'
5262  7. Faces        - faces, from `defface'
5263  8. Other        - other definitions
5264
5265 If you use this command with a prefix argument then multiple buffers,
5266 files, or bookmarks are used (see `icicle-search' for information
5267 about prefix arg behavior).  When this is the case, the Imenu mode
5268 \(and `imenu-generic-expression') of the current buffer at time of
5269 command invocation determines what kinds of definitions are found.
5270 So, if you want to search for definitions in a certain language, then
5271 invoke this command from a buffer in that language.
5272
5273 This command is intended only for use in Icicle mode.  It is defined
5274 using `icicle-search'.  For more information, in particular for
5275 information about the arguments and the use of a prefix argument to
5276 search multiple regions, buffers, or files, see the doc for command
5277 `icicle-search'.
5278
5279 See also these type-specific Icicles Imenu multi-commands:
5280
5281 * `icicle-imenu-command' - search/go to Emacs command definitions
5282 * `icicle-imenu-non-interactive-function' - non-command Lisp fn defs
5283 * `icicle-imenu-macro' - search/go to Lisp macro definitions
5284 * `icicle-imenu-user-option' - search/go to user option definitions
5285 * `icicle-imenu-variable' - search/go to Lisp variable definitions
5286 * `icicle-imenu-face' - search/go to Emacs face definitions
5287 * `icicle-imenu-key-explicit-map', `icicle-imenu-key-implicit-map'
5288   - search/go to Emacs key definitions
5289
5290 In addition, there are commands like each of the Imenu commands
5291 mentioned above, but with the suffix `-full'.  These commands use
5292 \"full\" definitions as completion candidates, rather than using only
5293 whatever the buffer's Imenu regexps matches.
5294
5295 A \"full\" candidate is obtained by first matching the Imenu regexp,
5296 then moving forward one sexp from the match beginning.  For a Lisp
5297 function, for instance, the regexp match starts at the `defun' sexp's
5298 opening parenthesis, and the full candidate is the entire `defun'
5299 sexp.
5300
5301 Outside of Lisp, \"full\" does not always mean that the candidate is
5302 larger.  Example: a C-language procedure/function definition.  The
5303 text between the regexp match beginning and `forward-sexp' is just the
5304 procedure name."
5305   (interactive `(,@(icicle-region-or-buffer-limits)
5306                  ,(not icicle-show-multi-completion-flag)
5307                  ,(icicle-search-where-arg)))
5308   (icicle-imenu-1 nil beg end require-match where))
5309
5310 ;;;###autoload
5311 (defalias 'icicle-search-defs-full 'icicle-imenu-full)
5312 ;;;###autoload
5313 (defun icicle-imenu-full (beg end require-match &optional where)
5314   "Search/go to an Imenu entry using `icicle-search'.
5315 Same as `icicle-imenu', except candidates are full definitions.
5316 This really means that a candidate is the text between the beginning
5317 of the Imenu regexp match and `forward-sexp' from there.
5318
5319 Remember that non-nil option
5320 `icicle-hide-common-match-in-Completions-flag' hides, in
5321 `*Completions*', all lines of multi-line candidates that do not match
5322 your current minibuffer input.  You can toggle this at anytime during
5323 completion using `C-u C-x .'"
5324   ;; Note: For this command, the candidate does not correspond to the regexp match.
5325   ;; Instead, it corresponds to that match plus text at the end to complete the definition.
5326   (interactive `(,@(icicle-region-or-buffer-limits)
5327                  ,(not icicle-show-multi-completion-flag)
5328                  ,(icicle-search-where-arg)))
5329   (icicle-imenu-1 'FULL beg end require-match where))
5330
5331 ;;;###autoload
5332 (defun icicle-imenu-command (beg end require-match &optional where)
5333   "Search/go to an Emacs command definition using `icicle-search'.
5334 This uses `commandp', so it finds only currently defined commands.
5335 That is, if the buffer has not been evaluated, then its function
5336 definitions are NOT considered commands by `icicle-imenu-command'.
5337
5338 This command is intended only for use in Icicle mode.  It is defined
5339 using `icicle-search'.  For more information, in particular for
5340 information about the arguments and the use of a prefix argument to
5341 search multiple regions, buffers, or files, see the doc for command
5342 `icicle-search'."
5343   (interactive `(,@(icicle-region-or-buffer-limits)
5344                  ,(not icicle-show-multi-completion-flag)
5345                  ,(icicle-search-where-arg)))
5346   (unless (or where (eq major-mode 'emacs-lisp-mode))
5347     (error "This command is only for Emacs-Lisp mode"))
5348   (icicle-imenu-1 nil beg end require-match where 'icicle-imenu-command-p
5349                   (lambda (menus)
5350                     (or (car (assoc "Functions" menus)) (car (assoc "Other" menus))
5351                         (error "No command definitions in buffer")))))
5352
5353 ;;;###autoload
5354 (defun icicle-imenu-command-full (beg end require-match &optional where)
5355   "Search/go to an Emacs command definition using `icicle-search'.
5356 Same as `icicle-imenu-command', except candidates are complete command
5357 definitions.
5358
5359 Remember that non-nil option
5360 `icicle-hide-common-match-in-Completions-flag' hides, in
5361 `*Completions*', all lines of multi-line candidates that do not match
5362 your current minibuffer input.  You can toggle this at anytime during
5363 completion using `C-u C-x .'"
5364   ;; Note: For this command, the candidate does not correspond to the regexp match.
5365   ;; Instead, it corresponds to that match plus text at the end to complete the definition.
5366   (interactive `(,@(icicle-region-or-buffer-limits)
5367                  ,(not icicle-show-multi-completion-flag)
5368                  ,(icicle-search-where-arg)))
5369   (unless (or where (eq major-mode 'emacs-lisp-mode))
5370     (error "This command is only for Emacs-Lisp mode"))
5371   (icicle-imenu-1 (eq major-mode 'emacs-lisp-mode) beg end require-match where
5372                   'icicle-imenu-command-p
5373                   (lambda (menus)
5374                     (or (car (assoc "Functions" menus)) (car (assoc "Other" menus))
5375                         (error "No command definitions in buffer")))))
5376
5377 (defun icicle-imenu-command-p (ignored-hit-string ignored-marker)
5378   "Return non-nil for a command definition.
5379 Predicate for `icicle-search'.
5380 Both arguments are ignored here."
5381   (let ((indx  (if (< emacs-major-version 21) 6 2)))
5382     (commandp (intern-soft
5383                (buffer-substring-no-properties (match-beginning indx) (match-end indx))))))
5384
5385 ;;;###autoload
5386 (defun icicle-imenu-non-interactive-function (beg end require-match &optional where)
5387   "Search/go to an Emacs non-command function definition with `icicle-search'.
5388 This uses `commandp' to distinguish currently defined commands from
5389 other functions.  This means that if the buffer has not yet been
5390 evaluated, then ALL of its function definitions are considered
5391 non-interactive by `icicle-imenu-non-interactive-function'.
5392
5393 This command is intended only for use in Icicle mode.  It is defined
5394 using `icicle-search'.  For more information, in particular for
5395 information about the arguments and the use of a prefix argument to
5396 search multiple regions, buffers, or files, see the doc for command
5397 `icicle-search'."
5398   (interactive `(,@(icicle-region-or-buffer-limits)
5399                  ,(not icicle-show-multi-completion-flag)
5400                  ,(icicle-search-where-arg)))
5401   (unless (or where (memq major-mode '(emacs-lisp-mode lisp-mode)))
5402     (error "This command is only for Emacs-Lisp mode"))
5403   (icicle-imenu-1 nil beg end require-match where 'icicle-imenu-non-interactive-function-p
5404                   (lambda (menus)
5405                     (or (car (assoc "Functions" menus)) (car (assoc "Other" menus))
5406                         (error "No non-command function definitions in buffer")))))
5407
5408 ;;;###autoload
5409 (defun icicle-imenu-non-interactive-function-full (beg end require-match &optional where)
5410   "Search/go to an Emacs non-command function definition with `icicle-search'.
5411 Same as `icicle-imenu-non-interactive-function', except candidates are
5412 complete function definitions.
5413
5414 Remember that non-nil option
5415 `icicle-hide-common-match-in-Completions-flag' hides, in
5416 `*Completions*', all lines of multi-line candidates that do not match
5417 your current minibuffer input.  You can toggle this at anytime during
5418 completion using `C-u C-x .'"
5419   ;; Note: For this command, the candidate does not correspond to the regexp match.
5420   ;; Instead, it corresponds to that match plus text at the end to complete the definition.
5421   (interactive `(,@(icicle-region-or-buffer-limits)
5422                  ,(not icicle-show-multi-completion-flag)
5423                  ,(icicle-search-where-arg)))
5424   (unless (or where (memq major-mode '(emacs-lisp-mode lisp-mode)))
5425     (error "This command is only for Emacs-Lisp mode"))
5426   (icicle-imenu-1 (memq major-mode '(emacs-lisp-mode lisp-mode)) beg end require-match where
5427                   'icicle-imenu-non-interactive-function-p
5428                   (lambda (menus)
5429                     (or (car (assoc "Functions" menus)) (car (assoc "Other" menus))
5430                         (error "No non-command function definitions in buffer")))))
5431
5432 (defun icicle-imenu-non-interactive-function-p (ignored-hit-string ignored-marker)
5433   "Return non-nil for a non-interactive function definition.
5434 Predicate for `icicle-search'.  Both arguments are ignored."
5435   (let* ((indx  (if (< emacs-major-version 21) 6 2))
5436          (fn    (intern-soft
5437                  (buffer-substring-no-properties (match-beginning indx) (match-end indx)))))
5438     (and (fboundp fn) (not (commandp fn)))))
5439
5440 ;;;###autoload
5441 (defun icicle-imenu-macro (beg end require-match &optional where)
5442   "Search/go to an Emacs macro definition using `icicle-search'.
5443 This command is intended only for use in Icicle mode.  It is defined
5444 using `icicle-search'.  For more information, in particular for
5445 information about the arguments and the use of a prefix argument to
5446 search multiple regions, buffers, or files, see the doc for command
5447 `icicle-search'."
5448   (interactive `(,@(icicle-region-or-buffer-limits)
5449                  ,(not icicle-show-multi-completion-flag)
5450                  ,(icicle-search-where-arg)))
5451   (unless (or where (memq major-mode '(emacs-lisp-mode lisp-mode)))
5452     (error "This command is only for Emacs-Lisp mode or Lisp mode"))
5453   (icicle-imenu-1 nil beg end require-match where 'icicle-imenu-macro-p
5454                   (lambda (menus)
5455                     (or (car (assoc "Macros" menus)) (car (assoc "Other" menus))
5456                         (error "No macro definitions in buffer")))))
5457
5458 ;;;###autoload
5459 (defun icicle-imenu-macro-full (beg end require-match &optional where)
5460   "Search/go to an Emacs macro definition using `icicle-search'.
5461 Same as `icicle-imenu-non-interactive-function', except candidates are
5462 complete function definitions.
5463
5464 Remember that non-nil option
5465 `icicle-hide-common-match-in-Completions-flag' hides, in
5466 `*Completions*', all lines of multi-line candidates that do not match
5467 your current minibuffer input.  You can toggle this at anytime during
5468 completion using `C-u C-x .'"
5469   ;; Note: For this command, the candidate does not correspond to the regexp match.
5470   ;; Instead, it corresponds to that match plus text at the end to complete the definition.
5471   (interactive `(,@(icicle-region-or-buffer-limits)
5472                  ,(not icicle-show-multi-completion-flag)
5473                  ,(icicle-search-where-arg)))
5474   (unless (or where (memq major-mode '(emacs-lisp-mode lisp-mode)))
5475     (error "This command is only for Emacs-Lisp mode"))
5476   (icicle-imenu-1 (memq major-mode '(emacs-lisp-mode lisp-mode)) beg end require-match where
5477                   'icicle-imenu-macro-p
5478                   (lambda (menus)
5479                     (or (car (assoc "Macro" menus)) (car (assoc "Other" menus))
5480                         (error "No macro definitions in buffer")))))
5481
5482 ;;;###autoload
5483 (defun icicle-imenu-variable (beg end require-match &optional where)
5484   "Search/go to an Emacs non-option variable definition using `icicle-search'.
5485 This command is intended only for use in Icicle mode.  It is defined
5486 using `icicle-search'.  For more information, in particular for
5487 information about the arguments and the use of a prefix argument to
5488 search multiple regions, buffers, or files, see the doc for command
5489 `icicle-search'."
5490   (interactive `(,@(icicle-region-or-buffer-limits)
5491                  ,(not icicle-show-multi-completion-flag)
5492                  ,(icicle-search-where-arg)))
5493   (unless (or where (memq major-mode '(emacs-lisp-mode lisp-mode)))
5494     (error "This command is only for Emacs-Lisp mode or Lisp mode"))
5495   (icicle-imenu-1 nil beg end require-match where nil
5496                   (lambda (menus)
5497                     (or (car (assoc "Variables" menus)) (car (assoc "Other" menus))
5498                         (error "No non-option variable definitions in buffer")))))
5499
5500 ;;;###autoload
5501 (defun icicle-imenu-variable-full (beg end require-match &optional where)
5502   "Search/go to an Emacs non-option variable definition using `icicle-search'.
5503 Same as `icicle-imenu-variable', except candidates are complete
5504 variable definitions.
5505
5506 Remember that non-nil option
5507 `icicle-hide-common-match-in-Completions-flag' hides, in
5508 `*Completions*', all lines of multi-line candidates that do not match
5509 your current minibuffer input.  You can toggle this at anytime during
5510 completion using `C-u C-x .'"
5511   ;; Note: For this command, the candidate does not correspond to the regexp match.
5512   ;; Instead, it corresponds to that match plus text at the end to complete the definition.
5513   (interactive `(,@(icicle-region-or-buffer-limits)
5514                  ,(not icicle-show-multi-completion-flag)
5515                  ,(icicle-search-where-arg)))
5516   (unless (or where (memq major-mode '(emacs-lisp-mode lisp-mode)))
5517     (error "This command is only for Emacs-Lisp mode or Lisp mode"))
5518   (icicle-imenu-1 (memq major-mode '(emacs-lisp-mode lisp-mode)) beg end require-match where nil
5519                   (lambda (menus)
5520                     (or (car (assoc "Variables" menus)) (car (assoc "Other" menus))
5521                         (error "No non-option variable definitions in buffer")))))
5522
5523 ;;;###autoload
5524 (defun icicle-imenu-user-option (beg end require-match &optional where)
5525   "Search/go to an Emacs user option definition using `icicle-search'.
5526 This command is intended only for use in Icicle mode.  It is defined
5527 using `icicle-search'.  For more information, in particular for
5528 information about the arguments and the use of a prefix argument to
5529 search multiple regions, buffers, or files, see the doc for command
5530 `icicle-search'."
5531   (interactive `(,@(icicle-region-or-buffer-limits)
5532                  ,(not icicle-show-multi-completion-flag)
5533                  ,(icicle-search-where-arg)))
5534   (unless (or where (eq major-mode 'emacs-lisp-mode))
5535     (error "This command is only for Emacs-Lisp mode"))
5536   (icicle-imenu-1 nil beg end require-match where nil
5537                   (lambda (menus)
5538                     (or (car (assoc "User Options" menus)) (car (assoc "Other" menus))
5539                         (error "No user option definitions in buffer")))))
5540
5541 ;;;###autoload
5542 (defun icicle-imenu-user-option-full (beg end require-match &optional where)
5543   "Search/go to an Emacs user option definition using `icicle-search'.
5544 Same as `icicle-imenu-user-option', except candidates are complete
5545 option definitions.
5546
5547 Remember that non-nil option
5548 `icicle-hide-common-match-in-Completions-flag' hides, in
5549 `*Completions*', all lines of multi-line candidates that do not match
5550 your current minibuffer input.  You can toggle this at anytime during
5551 completion using `C-u C-x .'"
5552   ;; Note: For this command, the candidate does not correspond to the regexp match.
5553   ;; Instead, it corresponds to that match plus text at the end to complete the definition.
5554   (interactive `(,@(icicle-region-or-buffer-limits)
5555                  ,(not icicle-show-multi-completion-flag)
5556                  ,(icicle-search-where-arg)))
5557   (unless (or where (eq major-mode 'emacs-lisp-mode))
5558     (error "This command is only for Emacs-Lisp mode"))
5559   (icicle-imenu-1 (eq major-mode 'emacs-lisp-mode) beg end require-match where nil
5560                   (lambda (menus)
5561                     (or (car (assoc "User Options" menus)) (car (assoc "Other" menus))
5562                         (error "No user option definitions in buffer")))))
5563
5564 ;;;###autoload
5565 (defun icicle-imenu-key-implicit-map (beg end require-match &optional where)
5566   "Search/go to a global/local Emacs key definition using `icicle-search'.
5567 This means a definition where no key map is specified explicitly -
5568 e.g., `global-set-key'.
5569
5570 This command is intended only for use in Icicle mode.  It is defined
5571 using `icicle-search'.  For more information, in particular for
5572 information about the arguments and the use of a prefix argument to
5573 search multiple regions, buffers, or files, see the doc for command
5574 `icicle-search'."
5575   (interactive `(,@(icicle-region-or-buffer-limits)
5576                  ,(not icicle-show-multi-completion-flag)
5577                  ,(icicle-search-where-arg)))
5578   (unless (or where (eq major-mode 'emacs-lisp-mode))
5579     (error "This command is only for Emacs-Lisp mode"))
5580   (icicle-imenu-1 nil beg end require-match where nil
5581                   (lambda (menus)
5582                     (or (car (assoc "Keys" menus)) (car (assoc "Other" menus))
5583                         (error "No implicit-map key definitions in buffer")))))
5584
5585 ;;;###autoload
5586 (defun icicle-imenu-key-implicit-map-full (beg end require-match &optional where)
5587   "Search/go to a global/local Emacs key definition using `icicle-search'.
5588 Same as `icicle-imenu-key-implicit-map', except candidates are complete key
5589 definitions."
5590   ;; Note: For this command, the candidate does not correspond to the regexp match.
5591   ;; Instead, it corresponds to that match plus text at the end to complete the definition.
5592   (interactive `(,@(icicle-region-or-buffer-limits)
5593                  ,(not icicle-show-multi-completion-flag)
5594                  ,(icicle-search-where-arg)))
5595   (unless (or where (eq major-mode 'emacs-lisp-mode))
5596     (error "This command is only for Emacs-Lisp mode"))
5597   (icicle-imenu-1 (eq major-mode 'emacs-lisp-mode) beg end require-match where nil
5598                   (lambda (menus)
5599                     (or (car (assoc "Keys" menus)) (car (assoc "Other" menus))
5600                         (error "No implicit-map key definitions in buffer")))))
5601
5602 ;;;###autoload
5603 (defun icicle-imenu-key-explicit-map (beg end require-match &optional where)
5604   "Search/go to an Emacs key definition for a named map using `icicle-search'.
5605 This command is intended only for use in Icicle mode.  It is defined
5606 using `icicle-search'.  For more information, in particular for
5607 information about the arguments and the use of a prefix argument to
5608 search multiple regions, buffers, or files, see the doc for command
5609 `icicle-search'."
5610   (interactive `(,@(icicle-region-or-buffer-limits)
5611                  ,(not icicle-show-multi-completion-flag)
5612                  ,(icicle-search-where-arg)))
5613   (unless (or where (eq major-mode 'emacs-lisp-mode))
5614     (error "This command is only for Emacs-Lisp mode"))
5615   (icicle-imenu-1 nil beg end require-match where nil
5616                   (lambda (menus)
5617                     (or (car (assoc "Keys in Maps" menus)) (car (assoc "Other" menus))
5618                         (error "No explicit-map key definitions in buffer")))))
5619
5620 ;;;###autoload
5621 (defun icicle-imenu-key-explicit-map-full (beg end require-match &optional where)
5622   "Search/go to an Emacs key definition for a named map using `icicle-search'.
5623 Same as `icicle-imenu-key-explicit-map', except candidates are
5624 complete key definitions."
5625   ;; Note: For this command, the candidate does not correspond to the regexp match.
5626   ;; Instead, it corresponds to that match plus text at the end to complete the definition.
5627   (interactive `(,@(icicle-region-or-buffer-limits)
5628                  ,(not icicle-show-multi-completion-flag)
5629                  ,(icicle-search-where-arg)))
5630   (unless (or where (eq major-mode 'emacs-lisp-mode))
5631     (error "This command is only for Emacs-Lisp mode"))
5632   (icicle-imenu-1 (eq major-mode 'emacs-lisp-mode) beg end require-match where nil
5633                   (lambda (menus)
5634                     (or (car (assoc "Keys in Maps" menus)) (car (assoc "Other" menus))
5635                         (error "No explicit-map key definitions in buffer")))))
5636
5637 ;;;###autoload
5638 (defun icicle-imenu-face (beg end require-match &optional where)
5639   "Search/go to an Emacs face definition using `icicle-search'.
5640 This command is intended only for use in Icicle mode.  It is defined
5641 using `icicle-search'.  For more information, in particular for
5642 information about the arguments and the use of a prefix argument to
5643 search multiple regions, buffers, or files, see the doc for command
5644 `icicle-search'."
5645   (interactive `(,@(icicle-region-or-buffer-limits)
5646                  ,(not icicle-show-multi-completion-flag)
5647                  ,(icicle-search-where-arg)))
5648   (unless (or where (eq major-mode 'emacs-lisp-mode))
5649     (error "This command is only for Emacs-Lisp mode"))
5650   (icicle-imenu-1 nil beg end require-match where nil
5651                   (lambda (menus)
5652                     (or (car (assoc "Faces" menus)) (car (assoc "Other" menus))
5653                         (error "No face definitions in buffer")))))
5654
5655 ;;;###autoload
5656 (defun icicle-imenu-face-full (beg end require-match &optional where)
5657   "Search/go to an Emacs face definition using `icicle-search'.
5658 Same as `icicle-imenu-face', except candidates are complete face
5659 definitions."
5660   ;; Note: For this command, the candidate does not correspond to the regexp match.
5661   ;; Instead, it corresponds to that match plus text at the end to complete the definition.
5662   (interactive `(,@(icicle-region-or-buffer-limits)
5663                  ,(not icicle-show-multi-completion-flag)
5664                  ,(icicle-search-where-arg)))
5665   (unless (or where (eq major-mode 'emacs-lisp-mode))
5666     (error "This command is only for Emacs-Lisp mode"))
5667   (icicle-imenu-1 (eq major-mode 'emacs-lisp-mode) beg end require-match where nil
5668                   (lambda (menus)
5669                     (or (car (assoc "Faces" menus)) (car (assoc "Other" menus))
5670                         (error "No face definitions in buffer")))))
5671
5672 (defun icicle-imenu-1 (fullp beg end require-match &optional where predicate submenu-fn)
5673   "Helper for `icicle-imenu*' commands.
5674 Non-nil FULLP means candidate is from the regexp match beginning
5675  through `forward-sexp' from there.
5676 Optional arg SUBMENU-FN is a function to apply to the list of Imenu
5677  submenus to choose one.  If nil then the user chooses one using
5678  completion.
5679 The other args are as for `icicle-search'."
5680   (unless imenu-generic-expression (error "No Imenu pattern for this buffer"))
5681   (let ((case-fold-search  (if (or (local-variable-p 'imenu-case-fold-search)
5682                                    (not (local-variable-p 'font-lock-defaults)))
5683                                imenu-case-fold-search
5684                              (nth 2 font-lock-defaults)))
5685         (old-table         (syntax-table))
5686         (table             (copy-syntax-table (syntax-table)))
5687         (slist             imenu-syntax-alist))
5688     (dolist (syn  slist)                ; Modify the syntax table used while matching regexps.
5689       (if (numberp (car syn))
5690           (modify-syntax-entry (car syn) (cdr syn) table) ; Single character.
5691         (dolist (char  (car syn))  (modify-syntax-entry char (cdr syn) table)))) ; String.
5692     (unwind-protect
5693          (save-match-data
5694            (set-syntax-table table)
5695            (let* ((others   0)
5696                   (menus    (mapcar #'(lambda (menu)
5697                                         (when (equal (car menu) "Other")
5698                                           (setq others  (1+ others))
5699                                           (when (> others 1)
5700                                             (setcar menu (format "Other<%d>" others))))
5701                                         menu)
5702                                     (icicle-remove-if-not
5703                                      #'icicle-imenu-in-buffer-p ; Use only menus that match buffer.
5704                                      (mapcar #'(lambda (menu) ; Name unlabeled menu(s) `Other[<N>]'.
5705                                                  (if (stringp (car menu))
5706                                                      menu
5707                                                    (cons "Other" (cdr menu))))
5708                                              imenu-generic-expression))))
5709                   (submenu  (if submenu-fn
5710                                 (funcall submenu-fn menus)
5711                               (if (cadr menus)
5712                                   (let ((icicle-show-Completions-initially-flag  t)
5713                                         (completion-ignore-case                  t))
5714                                     (completing-read "Choose: " menus nil t))
5715                                 (caar menus)))) ; Only one submenu, so use it.
5716                   (regexp   (cadr (assoc submenu menus)))
5717                   (icicle-transform-function
5718                    (if (interactive-p) nil icicle-transform-function)))
5719              (unless (stringp regexp) (error "No match"))
5720              (icicle-search
5721               beg end regexp require-match where predicate
5722               ;; We rely on the match data having been preserved.
5723               ;; $$$$$$ An alternative fn for Lisp only: #'(lambda () (up-list -1) (forward-sexp))))))
5724               (and fullp #'(lambda ()
5725                              (goto-char (match-beginning 0))
5726                              (condition-case icicle-imenu-1
5727                                  (forward-sexp)
5728                                (error (goto-char (match-end 0))))))))) ; Punt: just use regexp match.
5729       (set-syntax-table old-table))))
5730
5731 (defun icicle-imenu-in-buffer-p (menu)
5732   "Return non-nil if the regexp in MENU has a match in the buffer."
5733   (save-excursion (goto-char (point-min)) (re-search-forward (cadr menu) nil t)))
5734
5735 ;;;###autoload
5736 (defun icicle-tags-search (regexp &optional arg)
5737   "Search all source files listed in tags tables for matches for REGEXP.
5738 You are prompted for the REGEXP to match.  Enter REGEXP with `RET'.
5739 You do not need `M-,' - you see all matches as search hits to visit.
5740
5741 All tags in a tags file are used, including duplicate tags from the
5742 same or different source files.
5743
5744 By default, all tags files are used, but if you provide a prefix
5745 argument then only the current tag table is used.
5746
5747 If your TAGS file references source files that no longer exist, those
5748 files are listed.  In that case, you might want to update your TAGS
5749 file.
5750
5751
5752 You can alternatively choose to search, not the search contexts as
5753 defined by the context regexp you provide, but the non-contexts, that
5754 is, the text in the files that does not match the regexp.  To do this,
5755 use `C-M-~' during completion.  (This is a toggle, and it affects only
5756 future search commands, not the current one.)"
5757   (interactive
5758    (let ((completion-ignore-case  (if (and (boundp 'tags-case-fold-search)
5759                                            (memq tags-case-fold-search '(t nil)))
5760                                       tags-case-fold-search
5761                                     case-fold-search)))
5762      (require 'etags)
5763      (list (icicle-search-read-context-regexp (format
5764                                                "Search files with tags %smatching regexp: "
5765                                                (if icicle-search-complement-domain-p "*NOT* " "")))
5766            current-prefix-arg)))
5767   (let ((files  ()))
5768     (save-excursion
5769       (let ((first-time  t)
5770             (morep       t))
5771         (while (and morep (visit-tags-table-buffer (not first-time)))
5772           (when arg (setq morep  nil))
5773           (setq first-time  nil)
5774           (let ((tail  (last files)))
5775             (if tail
5776                 (setcdr tail (mapcar 'expand-file-name (tags-table-files)))
5777               (setq files  (mapcar 'expand-file-name (tags-table-files))))))))
5778     (let ((tail              files)     ; Remove names of non-existent or unreadable files.
5779           (unreadable-files  ()))
5780       (while tail
5781         (if (file-readable-p (car tail))
5782             (setq tail  (cdr tail))
5783           (push (car tail) unreadable-files)
5784           (setcar tail (cadr tail))
5785           (setcdr tail (cddr tail))))
5786       (when unreadable-files
5787         (with-output-to-temp-buffer "*Unreadable Files*"
5788           (princ "These missing or unreadable files were ignored:") (terpri) (terpri)
5789           (dolist (file  unreadable-files) (princ file) (terpri)))))
5790     (select-window (minibuffer-window))
5791     (select-frame-set-input-focus (selected-frame))
5792     (icicle-search nil nil regexp nil files)))
5793
5794 ;;;###autoload
5795 (defun icicle-save-string-to-variable (askp)
5796   "Save a string (text) to a variable.
5797 You are prompted for the string to save.  Typically, you store a
5798 regexp or part of a regexp in the variable.
5799
5800 By default, the variable is user option `icicle-input-string'.
5801 To save to a different variable, use a prefix argument; you are then
5802 prompted for the variable to use.
5803
5804 You can use `\\<minibuffer-local-completion-map>\
5805 \\[icicle-insert-string-from-variable]' to insert a string from a
5806 variable."
5807   (interactive "P")
5808   (let* ((enable-recursive-minibuffers  t)
5809          (icicle-must-pass-after-match-predicate  #'(lambda (s) (boundp (intern s))))
5810          (var
5811           (if askp
5812               (let ((icicle-candidate-alt-action-fn
5813                      (or icicle-candidate-alt-action-fn
5814                          (icicle-alt-act-fn-for-type "variable")))
5815                     (icicle-all-candidates-list-alt-action-fn
5816                      (or icicle-all-candidates-list-alt-action-fn
5817                          (icicle-alt-act-fn-for-type "variable"))))
5818                 (intern (completing-read "Variable: " obarray nil nil nil
5819                                          (if (boundp 'variable-name-history)
5820                                              'variable-name-history
5821                                            'icicle-variable-name-history)
5822                                          (symbol-name 'icicle-input-string))))
5823             'icicle-input-string))
5824          (text                          (icicle-completing-read-history
5825                                          (format "Text to save in `%s': " var))))
5826     (set var text)))
5827
5828 (when (> emacs-major-version 21)
5829
5830   (when (and icicle-define-alias-commands-flag (not (fboundp 'any)))
5831     (defalias 'any 'icicle-anything))
5832
5833   (defun icicle-anything (type)
5834     "Act on an object of type TYPE.
5835 You are prompted for the type, then for an object of that type.  The
5836 type is either the declared `type' of an Anything source, or its
5837 `name' if it has no `type'.
5838
5839 This command is available only if you use library `anything.el'.
5840
5841 This is an Icicles multi-command: You can act on multiple objects in
5842 multiple ways during a single command invocation.  When you choose an
5843 object using `RET' or `mouse-2', the default action is applied to it.
5844 The default action is also applied to the current completion candidate
5845 when you use `C-RET', `C-mouse-2', and so on.
5846
5847 You can apply a different action by using an alternative action key:
5848 `C-S-RET', `C-S-mouse-2', and so on.  This lets you choose the action
5849 to apply using completion. You can use `C-RET', `C-mouse-2', and so
5850 on, to perform multiple actions.
5851
5852 This command is intended for use only in Icicle mode."
5853     (interactive
5854      (let ((icicle-show-Completions-initially-flag  t)
5855            (icicle-whole-candidate-as-text-prop-p   icicle-anything-transform-candidates-flag))
5856        (unless (require 'anything nil t) (error "You must load library `anything.el' first"))
5857        (list (intern (completing-read "What (type): " (icicle-remove-duplicates
5858                                                        (mapcar #'list (icicle-get-anything-types)))
5859                                       nil t)))))
5860     (icicle-object-action type)))
5861
5862 (when (and icicle-define-alias-commands-flag (not (fboundp 'file)))
5863   (defun file ()
5864     "Act on a file.  You are prompted for the file and the action.
5865 During file-name completion, you can delete the file named by the
5866 current candidate, using `S-delete'.
5867
5868 This is just `icicle-object-action' with type `file'."
5869     (interactive) (icicle-object-action 'file)))
5870
5871 (when (and icicle-define-alias-commands-flag (not (fboundp 'buffer)))
5872   (defun buffer ()
5873     "Act on a buffer.  You are prompted for the buffer and the action.
5874 During buffer-name completion, you can kill the buffer named by the
5875 current candidate, using `S-delete'.
5876
5877 This is just `icicle-object-action' with type `buffer'."
5878     (interactive) (icicle-object-action 'buffer)))
5879
5880 (when (and icicle-define-alias-commands-flag (not (fboundp 'a)))
5881   (defalias 'a 'icicle-object-action))
5882 (when (and icicle-define-alias-commands-flag (not (fboundp 'what-which-how)))
5883   (defalias 'what-which-how 'icicle-object-action))
5884 ;;;###autoload
5885 (defun icicle-object-action (&optional type)
5886   "Act on an object of type TYPE (a symbol).
5887 You are prompted for the type (\"What\"), then for an object of that
5888 type (\"Which\"), then for the action function to apply to the
5889 object (\"How\").  For Anything types (see below), you are not
5890 prompted for the action function.
5891
5892 The \"type\" of an object is one of these:
5893
5894 a. A type defining an entry `icicle-predicate-types-alist'.
5895    These are type predicates, such as `bufferp', `keywordp', or `atom'.
5896
5897 b. The `type' of an Anything source, or its `name' if it has no
5898    `type'.  This is available only if you use library `anything.el'
5899    and option `icicle-use-anything-candidates-flag' is non-nil.
5900
5901 c. A type defining an entry in user option
5902    `icicle-type-actions-alist'.
5903
5904 In the case of Anything types (only), this is a multi-command:
5905 * `C-RET', `C-mouse-2', and so on perform the default action.
5906 * `C-S-RET', `C-S-mouse-2', and so on let you choose the action using
5907   completion.
5908
5909 Though this is not a multi-command for non-Anything types, for types
5910 `buffer' and `file' you can use `S-delete' during completion to delete
5911 the object (buffer or file) named by the current completion candidate.
5912
5913 Objects of types (b) and (c) are easily associated with names.  Their
5914 names are the completion candidates.  So, for instance, if you choose
5915 type `buffer', then you can act on a buffer by choosing its name.
5916
5917 Objects of predicate type (type a) are not necessarily named.  The
5918 completion candidates for these objects are variables (symbols) whose
5919 values are the objects acted upon.  So, for instance, if you choose
5920 type `bufferp', then you can choose a variable whose value is a
5921 buffer, in order to act on that buffer.  Whereas a buffer is always
5922 named, an object of type `stringp' is not.  The value of variable
5923 `emacs-version' is one such string that you can act on.
5924
5925 Anything types and Anything actions are highlighted when used as
5926 candidates in `*Completions*', using face `icicle-special-candidate'.
5927
5928 Be aware that the action function you choose must accommodate the
5929 object you choose as its only an argument.  Also, completion of the
5930 function candidate itself is not strict, so you can enter a lambda
5931 form.
5932
5933 With a prefix argument, the result of applying the function to the
5934 object is pretty-printed using `icicle-pp-eval-expression'.
5935 Otherwise, the function is called for its effect only, and its value
5936 is not displayed.
5937
5938 You can use a prefix argument similarly when you act on an individual
5939 function (\"How\") candidate to apply it to the object, without ending
5940 completion.  That is, `C-u C-RET', `C-u C-mouse-2', and so on, will
5941 pretty-print the result of the individual action.
5942
5943 This command is intended for use only in Icicle mode."
5944   (interactive)
5945   (let* ((anything-loaded-p         (and (> emacs-major-version 21)
5946                                          icicle-use-anything-candidates-flag
5947                                          (require 'anything nil t)))
5948          (anything-types            (and (not type) anything-loaded-p (icicle-get-anything-types)))
5949          (typ
5950           (or type
5951               (let ((icicle-show-Completions-initially-flag  t))
5952                 (intern
5953                  (completing-read "What (type): "
5954                                   (icicle-remove-duplicates (append (mapcar #'list anything-types)
5955                                                                     icicle-type-actions-alist
5956                                                                     icicle-predicate-types-alist))
5957                                   nil t)))))
5958          (predicate-type-p          (and (assoc (symbol-name typ) icicle-predicate-types-alist)
5959                                          (not (memq (symbol-name typ) anything-types))))
5960          (anything-candidates       (and anything-loaded-p (not predicate-type-p)
5961                                          (icicle-get-anything-candidates-of-type typ)))
5962          (anything-default-actions  (and anything-candidates
5963                                          (icicle-get-anything-default-actions-for-type typ)))
5964          (anything-actions          (and anything-candidates
5965                                          (icicle-get-anything-actions-for-type typ)))
5966          (icicle-saved-completion-candidate
5967           (cond (predicate-type-p (icicle-read-var-value-satisfying typ))
5968                 (anything-candidates
5969                  (icicle-choose-anything-candidate typ anything-candidates
5970                                                    anything-default-actions anything-actions))
5971                 ((member (symbol-name typ) (and anything-loaded-p (icicle-get-anything-types)))
5972                  (error "No candidates for type `%s'" (symbol-name typ)))
5973                 (t (icicle-choose-candidate-of-type typ))))
5974          (icicle-candidate-action-fn    ; For "how".
5975           #'(lambda (fn) (icicle-apply-to-saved-candidate fn anything-candidates typ)))
5976          (icicle-candidate-alt-action-fn ; For "how".
5977           (and anything-candidates #'(lambda (fn) (icicle-apply-to-saved-candidate fn t typ)))))
5978     (funcall (icicle-alt-act-fn-for-type
5979               (if predicate-type-p
5980                   (or (cdr (assoc (symbol-name typ) icicle-predicate-types-alist)) (symbol-name typ))
5981                 (symbol-name typ)))
5982              icicle-saved-completion-candidate)))
5983
5984 (when (> emacs-major-version 21)
5985   (defun icicle-get-anything-types ()
5986     "Return list of types defined in `anything-sources'.  See `anything.el'."
5987     (and (boundp 'anything-sources) (consp anything-sources)
5988          (let ((types  ())
5989                type)
5990            (dolist (source  (anything-get-sources))
5991              (if (setq type  (assoc-default 'type source))
5992                  (push (symbol-name type) types)
5993                (when (setq type  (assoc-default 'name source)) (push type types))))
5994            (setq types
5995                  (mapcar #'(lambda (typ)
5996                              (setq typ  (copy-sequence typ))
5997                              (put-text-property 0 (length typ) 'face 'icicle-special-candidate typ)
5998                              typ)
5999                          (icicle-remove-duplicates types)))))))
6000
6001 (when (> emacs-major-version 21)
6002   (defun icicle-get-anything-candidates-of-type (type)
6003     "Return list of Anything candidates for type TYPE.
6004 Used only when `anything-sources' is non-nil - see `anything.el'."
6005     (and (boundp 'anything-sources) (consp anything-sources)
6006          (let ((anything-candidate-cache  ())
6007                (candidates                nil))
6008            (dolist (source  (anything-get-sources))
6009              (let ((init-fn  (assoc-default 'init source))) (when init-fn (funcall init-fn)))
6010              (when (or (eq type (assoc-default 'type source))
6011                        (string= (symbol-name type) (assoc-default 'name source)))
6012                (setq candidates  (icicle-get-anything-cached-candidates source))))
6013            (when (and (not (functionp candidates)) (consp candidates))
6014              (mapcar #'(lambda (cand) (if (consp cand) cand (list cand))) candidates))
6015            candidates))))
6016
6017 ;; Similar to `anything-get-cached-candidates' in `anything.el', but ignores processes.
6018 ;; Free var here: `anything-candidate-cache'.
6019 (when (> emacs-major-version 21)
6020   (defun icicle-get-anything-cached-candidates (source)
6021     "Return cached value of candidates for Anything SOURCE.
6022 Cache the candidates if there is not yet a cached value."
6023     (let* ((source-name      (assoc-default 'name source))
6024            (candidate-cache  (assoc source-name anything-candidate-cache))
6025            candidates)
6026       (if candidate-cache
6027           (setq candidates  (cdr candidate-cache))
6028         (setq candidates  (icicle-get-anything-candidates source))
6029         (when (processp candidates) (setq candidates  ()))
6030         (setq candidate-cache  (cons source-name candidates))
6031         (push candidate-cache anything-candidate-cache))
6032       candidates)))
6033
6034 (when (> emacs-major-version 21)
6035   (defun icicle-get-anything-candidates (source)
6036     "Return the list of candidates from Anything SOURCE."
6037     (let* ((candidate-source  (assoc-default 'candidates source))
6038            (candidates
6039             (cond ((functionp candidate-source)
6040                    `(lambda (string pred mode)
6041                      (let ((anything-pattern  icicle-current-input))
6042                        (setq string  anything-pattern)
6043                        (let ((all-cands  (funcall ,candidate-source)))
6044                          (setq all-cands
6045                                (icicle-remove-if-not
6046                                 #'(lambda (cand)
6047                                     (string-match (if (eq 'prefix icicle-current-completion-mode)
6048                                                       (concat "^" (regexp-quote string))
6049                                                     string)
6050                                                   cand))
6051                                 all-cands))
6052                          (cond ((eq mode t) all-cands)
6053                                ((eq mode nil)
6054                                 (icicle-expanded-common-match icicle-current-input all-cands))
6055                                ((eq mode 'lambda) t))))))
6056                   ((listp candidate-source) candidate-source)
6057                   ((and (symbolp candidate-source) (boundp candidate-source))
6058                    (symbol-value candidate-source))
6059                   (t
6060                    (error
6061                     (concat "Source `candidates' value is not a function, variable or list: %s")
6062                     candidate-source)))))
6063       (if (or (not icicle-anything-transform-candidates-flag) (processp candidates))
6064           candidates
6065         (anything-transform-candidates candidates source)))))
6066
6067 (when (> emacs-major-version 21)
6068   (defun icicle-get-anything-actions-for-type (type)
6069     "Set and return `icicle-candidates-alist' of actions for type TYPE.
6070 The display string for each action is highlighted using face
6071 `icicle-special-candidate'."
6072     (setq icicle-candidates-alist  ())
6073     (let ((all-sources-actions  ())
6074           this-source-actions  faced-act)
6075       (dolist (source  (anything-get-sources))
6076         (when (or (eq type (assoc-default 'type source))
6077                   (string= (symbol-name type) (assoc-default 'name source)))
6078           (setq this-source-actions  (assoc-default 'action source))
6079           (dolist (action  this-source-actions)
6080             (unless (member action all-sources-actions)
6081               (setq faced-act  (copy-sequence (car action))) ; Highlight Anything action.
6082               (put-text-property 0 (length faced-act) 'face 'icicle-special-candidate faced-act)
6083               (push (cons faced-act (cdr action)) all-sources-actions)))))
6084       (setq icicle-candidates-alist  (sort all-sources-actions
6085                                            #'(lambda (a1 a2)
6086                                                (funcall icicle-sort-comparer (car a1) (car a2))))))))
6087 (when (> emacs-major-version 21)
6088   (defun icicle-choose-anything-candidate (type candidates default-actions actions)
6089     "Read an Anything object of type TYPE with completion, and return it.
6090 During completion, you can act on selected completion candidates, in
6091 turn, using the action keys (`C-RET', `C-mouse-2', `C-down', etc.).
6092 CANDIDATES is the list of candidates of type TYPE.
6093 DEFAULT-ACTIONS is the list of default actions for type TYPE.
6094 ACTIONS is the list of all actions for type TYPE."
6095     (let* ((win                                         (selected-window))
6096            (icicle-sort-comparer                        nil)
6097            (icicle-transform-function                   nil)
6098            (icicle-Completions-display-min-input-chars  (icicle-get-anything-req-pat-chars type))
6099            (icicle-incremental-completion-delay         (icicle-get-anything-input-delay type))
6100            (icicle-whole-candidate-as-text-prop-p       icicle-anything-transform-candidates-flag)
6101            (icicle-candidates-alist
6102             (if (or (functionp candidates) icicle-whole-candidate-as-text-prop-p)
6103                 candidates
6104               icicle-candidates-alist))
6105            (icicle-candidate-action-fn
6106             #'(lambda (obj)
6107                 (when icicle-whole-candidate-as-text-prop-p
6108                   (setq obj  (icicle-anything-candidate-value obj)))
6109                 (let ((enable-recursive-minibuffers  t))
6110                   (with-selected-window win
6111                     (if (null (cdr default-actions))
6112                         (funcall (cdar default-actions) obj)
6113                       (funcall (completing-read "How (action): " default-actions nil t) obj))))
6114                 (select-window (minibuffer-window))
6115                 (select-frame-set-input-focus (selected-frame))
6116                 (icicle-raise-Completions-frame)))
6117            (icicle-candidate-alt-action-fn
6118             `(lambda (obj)
6119               (when icicle-whole-candidate-as-text-prop-p
6120                 (setq obj  (icicle-anything-candidate-value obj)))
6121               (let ((icicle-show-Completions-initially-flag  t)
6122                     (icicle-saved-completion-candidate       obj)
6123                     (icicle-candidates-alist                 actions)
6124                     (enable-recursive-minibuffers            t))
6125                 (with-selected-window win
6126                   (icicle-apply-to-saved-candidate
6127                    (let ((enable-recursive-minibuffers      t)
6128                          (icicle-last-completion-candidate  icicle-last-completion-candidate)
6129                          (icicle-candidate-alt-action-fn    nil)
6130                          (icicle-candidate-action-fn
6131                           `(lambda (actn) (with-selected-window win
6132                                             (let ((enable-recursive-minibuffers  t)
6133                                                   (icicle-candidates-alist       actions))
6134                                               (icicle-apply-to-saved-candidate actn t ,type))))))
6135                      (completing-read "How (action): " actions nil t))
6136                    t
6137                    ,type)))))
6138            (orig-action-fn  icicle-candidate-action-fn)
6139            (icicle-candidate-help-fn
6140             (if icicle-whole-candidate-as-text-prop-p
6141                 #'(lambda (obj)
6142                     (let ((icicle-candidate-help-fn  nil))
6143                       (icicle-help-on-candidate-symbol
6144                        (intern (icicle-anything-candidate-value obj)))))
6145               icicle-candidate-help-fn))
6146            (icicle-candidate-action-fn
6147             (if icicle-whole-candidate-as-text-prop-p
6148                 #'(lambda (obj)
6149                     (let ((icicle-last-input  (icicle-anything-candidate-value obj)))
6150                       (funcall orig-action-fn obj)))
6151               icicle-candidate-action-fn)))
6152       (if icicle-whole-candidate-as-text-prop-p
6153           (icicle-anything-candidate-value
6154            (completing-read (concat "Which (" (symbol-name type) "): ") candidates nil t))
6155         (completing-read (concat "Which (" (symbol-name type) "): ") candidates nil t)))))
6156
6157 (when (> emacs-major-version 21)
6158   (defun icicle-get-anything-req-pat-chars (type)
6159     "Return max `required-pattern' value for sources of type TYPE.
6160 The value returned is also always at least as big as
6161 `icicle-Completions-display-min-input-chars'."
6162     (let ((req-pat              icicle-Completions-display-min-input-chars)
6163           (req-pat-this-source  nil))
6164       (dolist (source  (anything-get-sources))
6165         (when (and (or (eq type (assoc-default 'type source))
6166                        (string= (symbol-name type) (assoc-default 'name source)))
6167                    (setq req-pat-this-source  (assoc-default 'requires-pattern source)))
6168           (setq req-pat  (max req-pat req-pat-this-source))))
6169       req-pat)))
6170
6171 (when (> emacs-major-version 21)
6172   (defun icicle-get-anything-input-delay (type)
6173     "Return max `delay' value for sources of type TYPE.
6174 The value returned is also always at least as big as
6175 `icicle-incremental-completion-delay'."
6176     (let ((delay              icicle-incremental-completion-delay)
6177           (delay-this-source  nil))
6178       (dolist (source  (anything-get-sources))
6179         (when (and (or (eq type (assoc-default 'type source))
6180                        (string= (symbol-name type) (assoc-default 'name source)))
6181                    (setq delay-this-source  (and (assoc 'delayed source) anything-idle-delay)))
6182           (setq delay  (max delay delay-this-source))))
6183       delay)))
6184
6185 (when (> emacs-major-version 21)
6186   (defun icicle-anything-candidate-value (candidate)
6187     "Return the real value associated with string CANDIDATE."
6188     (or (cdr-safe (funcall icicle-get-alist-candidate-function candidate)) candidate)))
6189
6190 (when (> emacs-major-version 21)
6191   (defun icicle-get-anything-default-actions-for-type (type)
6192     "Set and return `icicle-candidates-alist' of default actions for type TYPE."
6193     (setq icicle-candidates-alist  ())
6194     (let ((all-sources-actions  ())
6195           this-source-actions)
6196       (dolist (source  (anything-get-sources))
6197         (when (or (eq type (assoc-default 'type source))
6198                   (string= (symbol-name type) (assoc-default 'name source)))
6199           (setq this-source-actions  (assoc-default 'action source))
6200           (unless (memq (car this-source-actions) all-sources-actions)
6201             (push (car this-source-actions) all-sources-actions))))
6202       (setq icicle-candidates-alist
6203             (sort all-sources-actions   ; Must sort, or `icicle-candidate-nb' will be wrong.
6204                   #'(lambda (a1 a2) (funcall icicle-sort-comparer (car a1) (car a2))))))))
6205
6206 (defun icicle-choose-candidate-of-type (type)
6207   "Read an object of type TYPE (a symbol) with completion, and return it.
6208 These options, when non-nil, control buffer candidate matching and
6209 filtering:
6210  `icicle-buffer-ignore-space-prefix-flag' - Ignore space-prefix names
6211  `icicle-buffer-extras'               - Extra buffers to display
6212  `icicle-buffer-match-regexp'         - Regexp that buffers must match
6213  `icicle-buffer-no-match-regexp'      - Regexp buffers must not match
6214  `icicle-buffer-predicate'            - Predicate buffer must satisfy
6215  `icicle-buffer-sort'                 - Sort function for candidates"
6216   (let ((icicle-orig-window  (selected-window))) ; For alternative actions.
6217     (case type
6218       (buffer
6219        (let* ((completion-ignore-case
6220                (or (and (boundp 'read-buffer-completion-ignore-case)
6221                         read-buffer-completion-ignore-case)
6222                    completion-ignore-case))
6223               (icicle-must-match-regexp                icicle-buffer-match-regexp)
6224               (icicle-must-not-match-regexp            icicle-buffer-no-match-regexp)
6225               (icicle-must-pass-after-match-predicate  icicle-buffer-predicate)
6226               (icicle-require-match-flag               icicle-buffer-require-match-flag)
6227               (icicle-extra-candidates                 icicle-buffer-extras)
6228               (icicle-ignore-space-prefix-flag         icicle-buffer-ignore-space-prefix-flag)
6229               (icicle-delete-candidate-object          'icicle-kill-a-buffer) ; `S-delete' kills buf
6230               (icicle-transform-function               'icicle-remove-dups-if-extras)
6231               (icicle--temp-orders
6232                (append (list '("by last access") ; Renamed from "turned OFF'.
6233                              '("*...* last" . icicle-buffer-sort-*...*-last)
6234                              '("by buffer size" . icicle-buffer-smaller-p)
6235                              '("by major mode name" . icicle-major-mode-name-less-p)
6236                              (and (fboundp 'icicle-mode-line-name-less-p)
6237                                   '("by mode-line mode name" . icicle-mode-line-name-less-p))
6238                              '("by file/process name" . icicle-buffer-file/process-name-less-p))
6239                        (delete '("turned OFF") (copy-sequence icicle-sort-orders-alist))))
6240               ;; Put `icicle-buffer-sort' first.  If already in list, move it, else add it, to start.
6241               (icicle-sort-orders-alist
6242                (progn (when (and icicle-buffer-sort-first-time-p icicle-buffer-sort)
6243                         (setq icicle-sort-comparer             icicle-buffer-sort
6244                               icicle-buffer-sort-first-time-p  nil))
6245                       (if icicle-buffer-sort
6246                           (let ((already-there  (rassq icicle-buffer-sort icicle--temp-orders)))
6247                             (if already-there
6248                                 (cons already-there (setq icicle--temp-orders
6249                                                           (delete already-there icicle--temp-orders)))
6250                               (cons `("by `icicle-buffer-sort'" . ,icicle-buffer-sort)
6251                                     icicle--temp-orders)))
6252                         icicle--temp-orders)))
6253               (icicle-candidate-alt-action-fn
6254                (or icicle-candidate-alt-action-fn (icicle-alt-act-fn-for-type "buffer")))
6255               (icicle-all-candidates-list-alt-action-fn
6256                (or icicle-all-candidates-list-alt-action-fn (icicle-alt-act-fn-for-type "buffer"))))
6257          (get-buffer-create
6258           (completing-read "Which (buffer): " (mapcar #'(lambda (buf) (list (buffer-name buf)))
6259                                                       (buffer-list))
6260                            nil
6261                            (and (fboundp 'confirm-nonexistent-file-or-buffer) ; Emacs 23.
6262                                 (confirm-nonexistent-file-or-buffer))
6263                            nil 'buffer-name-history nil nil))))
6264       (color (icicle-read-color 1))     ; Use the color name (only).
6265       (command (let ((icicle-must-pass-after-match-predicate  #'(lambda (s) (commandp (intern s))))
6266                      (icicle-candidate-alt-action-fn
6267                       (or icicle-candidate-alt-action-fn
6268                           (icicle-alt-act-fn-for-type "command")))
6269                      (icicle-all-candidates-list-alt-action-fn
6270                       (or icicle-all-candidates-list-alt-action-fn
6271                           (icicle-alt-act-fn-for-type "command"))))
6272                  (intern (completing-read "Which (command): " obarray))))
6273       (face (let ((icicle-candidate-alt-action-fn
6274                    (or icicle-candidate-alt-action-fn
6275                        (icicle-alt-act-fn-for-type "face")))
6276                   (icicle-all-candidates-list-alt-action-fn
6277                    (or icicle-all-candidates-list-alt-action-fn
6278                        (icicle-alt-act-fn-for-type "face"))))
6279               (intern (completing-read "Which (face): " (mapcar #'(lambda (x) (list (format "%s" x)))
6280                                                                 (face-list))))))
6281       (file (let ((icicle-candidate-alt-action-fn
6282                    (or icicle-candidate-alt-action-fn
6283                        (icicle-alt-act-fn-for-type "file")))
6284                   (icicle-all-candidates-list-alt-action-fn
6285                    (or icicle-all-candidates-list-alt-action-fn
6286                        (icicle-alt-act-fn-for-type "file")))
6287                   (icicle-delete-candidate-object  'icicle-delete-file-or-directory)) ; `S-delete'
6288               (read-file-name "Which (file): " nil
6289                               (and (eq major-mode 'dired-mode)
6290                                    (fboundp 'dired-get-file-for-visit) ; Emacs 22+.
6291                                    (condition-case nil ; E.g. error because not on file line (ignore)
6292                                        (abbreviate-file-name (dired-get-file-for-visit))
6293                                      (error nil))))))
6294       (frame (let ((frame-alist  (icicle-make-frame-alist))
6295                    (icicle-candidate-alt-action-fn
6296                     (or icicle-candidate-alt-action-fn
6297                         (icicle-alt-act-fn-for-type "frame")))
6298                    (icicle-all-candidates-list-alt-action-fn
6299                     (or icicle-all-candidates-list-alt-action-fn
6300                         (icicle-alt-act-fn-for-type "frame"))))
6301                (cdr (assoc (completing-read "Which (frame): " frame-alist) frame-alist))))
6302       (function (let ((icicle-must-pass-after-match-predicate  #'(lambda (s) (fboundp (intern s))))
6303                       (icicle-candidate-alt-action-fn
6304                        (or icicle-candidate-alt-action-fn
6305                            (icicle-alt-act-fn-for-type "function")))
6306                       (icicle-all-candidates-list-alt-action-fn
6307                        (or icicle-all-candidates-list-alt-action-fn
6308                            (icicle-alt-act-fn-for-type "function"))))
6309                   (intern (completing-read "Which (function): " obarray))))
6310       (option (let ((icicle-must-pass-after-match-predicate  #'(lambda (s)
6311                                                                  (user-variable-p (intern s))))
6312                     (icicle-candidate-alt-action-fn
6313                      (or icicle-candidate-alt-action-fn
6314                          (icicle-alt-act-fn-for-type "option")))
6315                     (icicle-all-candidates-list-alt-action-fn
6316                      (or icicle-all-candidates-list-alt-action-fn
6317                          (icicle-alt-act-fn-for-type "option"))))
6318                 (intern (completing-read "Which (user option): " obarray))))
6319       (process (let ((icicle-candidate-alt-action-fn
6320                       (or icicle-candidate-alt-action-fn
6321                           (icicle-alt-act-fn-for-type "process")))
6322                      (icicle-all-candidates-list-alt-action-fn
6323                       (or icicle-all-candidates-list-alt-action-fn
6324                           (icicle-alt-act-fn-for-type "process"))))
6325                  (get-process
6326                   (completing-read
6327                    "Which (process): " (mapcar #'(lambda (proc) (list (process-name proc)))
6328                                                (process-list))))))
6329       (symbol (let ((icicle-candidate-alt-action-fn
6330                      (or icicle-candidate-alt-action-fn
6331                          (icicle-alt-act-fn-for-type "symbol")))
6332                     (icicle-all-candidates-list-alt-action-fn
6333                      (or icicle-all-candidates-list-alt-action-fn
6334                          (icicle-alt-act-fn-for-type "symbol"))))
6335                 (intern (completing-read "Which (symbol): " obarray))))
6336       (variable (let ((icicle-must-pass-after-match-predicate  #'(lambda (s) (boundp (intern s))))
6337                       (icicle-candidate-alt-action-fn
6338                        (or icicle-candidate-alt-action-fn
6339                            (icicle-alt-act-fn-for-type "variable")))
6340                       (icicle-all-candidates-list-alt-action-fn
6341                        (or icicle-all-candidates-list-alt-action-fn
6342                            (icicle-alt-act-fn-for-type "variable"))))
6343                   (intern (completing-read "Which (variable): " obarray))))
6344       (window (let ((icicle-candidate-alt-action-fn
6345                      (or icicle-candidate-alt-action-fn
6346                          (icicle-alt-act-fn-for-type "window")))
6347                     (icicle-all-candidates-list-alt-action-fn
6348                      (or icicle-all-candidates-list-alt-action-fn
6349                          (icicle-alt-act-fn-for-type "window")))
6350                     (buffers  ()))
6351                 (walk-windows #'(lambda (win)
6352                                   (push (list (format "%s" (window-buffer win))) buffers))
6353                               nil t)
6354                 (get-buffer-window (completing-read "Window showing buffer: " buffers) 0)))
6355       (otherwise (error "Bad object type: %S" type)))))
6356
6357 (defun icicle-read-var-value-satisfying (pred)
6358   "Read a variable that satisfies predicate PRED and returns its value."
6359   (symbol-value
6360    (let ((icicle-orig-window                      (selected-window))
6361          (icicle-must-pass-after-match-predicate  `(lambda (s)
6362                                                     (setq s  (intern s))
6363                                                     (and (boundp s)
6364                                                      (funcall ',pred (symbol-value s)))))
6365          (icicle-candidate-alt-action-fn          (or icicle-candidate-alt-action-fn
6366                                                       (icicle-alt-act-fn-for-type "variable")))
6367          (icicle-all-candidates-list-alt-action-fn
6368           (or icicle-all-candidates-list-alt-action-fn (icicle-alt-act-fn-for-type "variable"))))
6369      (intern (completing-read (format "Which (%s value of variable): " pred) obarray)))))
6370
6371 (defvar icicle-key-prefix nil
6372   "A prefix key.")
6373
6374 (defvar icicle-key-prefix-2 nil
6375   "A prefix key.")
6376
6377 (defvar icicle-active-map nil
6378   "An active keymap.")
6379
6380 (defvar icicle-orig-buff-key-complete nil
6381   "Current buffer when you invoked `icicle-complete-keys'.")
6382
6383 (defvar icicle-orig-extra-cands ()
6384   "Value of `icicle-extra-candidates', before command.")
6385
6386 (defvar icicle-orig-show-initially-flag nil
6387   "Value of `icicle-show-Completions-initially-flag', before command.")
6388
6389 (defvar icicle-orig-sort-orders-alist ()
6390   "Value of `icicle-sort-orders-alist', before command.")
6391
6392 (defvar icicle-orig-win-key-complete nil
6393   "Selected window when you invoked `icicle-complete-keys'.")
6394
6395 (defvar icicle-this-cmd-keys ()
6396   "Value of `this-command-keys-vector' at some point in key completion.")
6397
6398 (when (fboundp 'map-keymap)             ; Emacs 22+.
6399
6400   (defun icicle-complete-keys ()        ; Bound to prefix keys followed by `S-TAB' (unless defined).
6401     "Complete a key sequence for the currently invoked prefix key.
6402 Input-candidate completion and cycling are available.
6403
6404 You can navigate the key-binding hierarchy (prefix-key hierarchy),
6405 just as would navigate a file-system hierarchy (to complete directory
6406 and file names) or a menu hierarchy (to complete submenu and menu-item
6407 names).
6408
6409 Completion candidates generally have the form `KEY  =  COMMAND'.
6410
6411 If COMMAND is `...', then KEY is a prefix key; choosing it updates the
6412 completion candidates list to the keys under that prefix.  For
6413 example, choosing `C-x = ...' changes the candidates to those with
6414 prefix `C-x'.
6415
6416 The special candidate `..' means to go up one level of the key-binding
6417 hierarchy and complete candidates there.  For example, if you are
6418 currently completing prefix key `C-x 5', and you choose candidate
6419 `..', then you will be completing prefix `C-x', the parent of `C-x 5'.
6420
6421 Except at the top level, the default value for completion is `..'.
6422
6423 You can use `C-M-,' at any time to switch between sorting with local
6424 bindings first and sorting with prefix keys first.  You can use `C-,'
6425 at any time to change the sort order among these two and sorting by
6426 command name.
6427
6428 If option `icicle-complete-keys-self-insert-ranges' is non-nil, then
6429 some keys bound to `self-insert-command' are included as possible
6430 key-completion candidates; otherwise they are not.  The default is
6431 nil.
6432
6433 For Emacs 22, the option is effectively Boolean: any non-nil value
6434 means allow all self-inserting keys as candidates.
6435
6436 In Emacs 23+, there are thousands of self-inserting keys, so it is not
6437 practical to allow all as candidates.  Instead, a non-nil value is a
6438 list of character ranges of the form (MIN . MAX).  Characters in the
6439 inclusive range MIN through MAX are possible key-completion
6440 candidates.
6441
6442 For Emacs 23+, if you use a non-nil value for
6443 `icicle-complete-keys-self-insert-ranges' then use only small ranges
6444 for good performance.  In general, you will want to leave this option
6445 value as nil and use the vanilla Emacs 23+ command `ucs-insert' to
6446 insert characters by completing against their Unicode names.  With
6447 Icicles key completion you do not complete against the Unicode names.
6448 Instead, you can see the characters in `*Completions*'.
6449
6450 While cycling, these keys describe candidates:
6451
6452 `C-RET'   - Describe command of current completion candidate only
6453 `C-down'  - Move to next completion candidate and describe
6454 `C-up'    - Move to previous completion candidate and describe
6455 `C-next'  - Move to next apropos-completion candidate and describe
6456 `C-prior' - Move to previous apropos-completion candidate and describe
6457 `C-end'   - Move to next prefix-completion candidate and describe
6458 `C-home'  - Move to previous prefix-completion candidate and describe
6459 `C-!'     - Describe *all* candidates (or all that are saved),
6460             successively - use the [back] button in buffer *Help* to
6461             visit the descriptions
6462
6463 When candidate action and cycling are combined (e.g. `C-next'), option
6464 `icicle-act-before-cycle-flag' determines which occurs first.
6465
6466 With prefix `C-M-' instead of `C-', the same keys (`C-M-mouse-2',
6467 `C-M-RET', `C-M-down', and so on) provide help about candidates.
6468
6469 Use `mouse-2', `RET', or `S-RET' to finally choose a candidate, or
6470 `C-g' to quit.  This is an Icicles command - see command
6471 `icicle-mode'."
6472     (interactive)
6473     (let* ((icicle-transform-function               'icicle-remove-duplicates)
6474            (icicle-orig-sort-orders-alist           icicle-sort-orders-alist) ; For recursive use.
6475            (icicle-orig-show-initially-flag         icicle-show-Completions-initially-flag)
6476            (icicle-show-Completions-initially-flag  t)
6477            (icicle-candidate-action-fn              'icicle-complete-keys-action)
6478            (enable-recursive-minibuffers            t)
6479            (icicle-orig-buff-key-complete           (current-buffer))
6480            (icicle-orig-win-key-complete            (selected-window))
6481            (icicle-completing-keys-p                t) ; Provide a condition to test key completion.
6482            (icicle-sort-comparer                    'icicle-local-keys-first-p)
6483            (icicle-alternative-sort-comparer        'icicle-prefix-keys-first-p)
6484            (icicle-sort-orders-alist
6485             '(("by key name, local bindings first" . icicle-local-keys-first-p)
6486               ("by key name, prefix keys first" . icicle-prefix-keys-first-p)
6487               ("by command name" . icicle-command-names-alphabetic-p)
6488               ("turned OFF")))
6489            (icicle-hist-cands-no-highlight          '("..")))
6490       (icicle-complete-keys-1 (icicle-this-command-keys-prefix))))
6491
6492   (defun icicle-this-command-keys-prefix ()
6493     "Return the prefix of the currently invoked key sequence."
6494     (let ((this-key  (this-command-keys))) (substring this-key 0 (1- (length this-key)))))
6495
6496   ;; Free vars here: `icicle-complete-keys-alist' is bound in `icicles-var.el'.
6497   (defun icicle-complete-keys-1 (prefix) ; PREFIX is a free var in `icicle-complete-keys-action'.
6498     "Complete a key sequence for prefix key PREFIX (a vector)."
6499     ;; `icicle-orig-extra-cands' is free in `icicle-complete-keys-action'.
6500     (let ((icicle-orig-extra-cands  icicle-extra-candidates)
6501           (icicle-key-prefix        prefix))
6502       (unwind-protect
6503            (progn
6504              (icicle-keys+cmds-w-prefix prefix)
6505              (unless icicle-complete-keys-alist (error "No keys for prefix `%s'" prefix))
6506              (let* ((icicle-this-cmd-keys ; For error report - e.g. mouse command.
6507                      (this-command-keys-vector)) ; Free var in `icicle-complete-keys-action'.
6508                     (icicle-key-prefix-description
6509                      (icicle-key-description prefix (not icicle-key-descriptions-use-<>-flag)))
6510                     (prompt  (concat "Complete keys"
6511                                      (and (not (string= "" icicle-key-prefix-description))
6512                                           (concat " " icicle-key-prefix-description))
6513                                      ": ")))
6514                (put-text-property 0 1 'icicle-fancy-candidates t prompt)
6515                (icicle-complete-keys-action
6516                 (completing-read prompt icicle-complete-keys-alist nil t nil nil
6517                                  ;;$$ (if (equal [] prefix) nil "\\.\\.")
6518                                  ))))
6519         (dolist (cand  icicle-complete-keys-alist)
6520           (put (car cand) 'icicle-special-candidate nil))))) ; Reset the property.
6521
6522   ;; Free vars here:
6523   ;; `icicle-orig-buff-key-complete', `icicle-orig-win-key-complete', bound in `icicle-complete-keys'.
6524   ;; `icicle-orig-extra-cands', `icicle-this-cmd-keys', `icicle-key-prefix',
6525   ;; bound in `icicle-complete-keys-1'.
6526   (defun icicle-complete-keys-action (candidate)
6527     "Completion action function for `icicle-complete-keys'."
6528     (let* ((key+binding    (cdr-safe (assq (intern candidate) icicle-complete-keys-alist)))
6529            (key            (car-safe key+binding))
6530            (binding        (cdr-safe key+binding))
6531            (cmd-name       nil)
6532            (action-window  (selected-window)))
6533       (unwind-protect
6534            (progn
6535              (set-buffer icicle-orig-buff-key-complete)
6536              (select-window icicle-orig-win-key-complete)
6537              (if (string= ".." candidate)
6538                  (setq cmd-name  "..")
6539                (unless (and (string-match "\\(.+\\)  =  \\(.+\\)" candidate) (match-beginning 2))
6540                  (error "No match"))
6541                (setq cmd-name  (substring candidate (match-beginning 2) (match-end 2))))
6542              (cond ((string= ".." cmd-name) ; Go back up to parent prefix.
6543                     (setq last-command  'icicle-complete-keys)
6544                     (icicle-complete-keys-1 (vconcat (nbutlast (append icicle-key-prefix nil)))))
6545                    ((and key (string= "..." cmd-name)) ; Go down to prefix.
6546                     (setq last-command  'icicle-complete-keys)
6547                     (icicle-complete-keys-1 (vconcat icicle-key-prefix key)))
6548                    (t
6549                     (setq this-command             binding
6550                           last-command             binding
6551                           icicle-extra-candidates  icicle-orig-extra-cands) ; Restore it.
6552                     (when (eq 'self-insert-command binding)
6553                       (unless key (error "Cannot insert `%s'" key))
6554                       (setq last-command-char  (aref key 0)))
6555                     (when (eq 'digit-argument binding)
6556                       (setq last-command-char  (aref key 0))
6557                       (icicle-msg-maybe-in-minibuffer "Numeric argument"))
6558                     (when (eq 'negative-argument binding)
6559                       (icicle-msg-maybe-in-minibuffer "Negative argument"))
6560                     (setq last-nonmenu-event  1) ; So `*Completions*' mouse-click info is ignored.
6561                     ;; Bind so vanilla context when invoke chosen command.
6562                     (let ((icicle-candidate-action-fn              nil)
6563                           (icicle-completing-keys-p                nil)
6564                           (icicle-sort-orders-alist                icicle-orig-sort-orders-alist)
6565                           (icicle-sort-comparer                    'icicle-case-string-less-p)
6566                           (icicle-alternative-sort-comparer
6567                            'icicle-historical-alphabetic-p)
6568                           (icicle-show-Completions-initially-flag
6569                            icicle-orig-show-initially-flag))
6570                       (call-interactively binding nil icicle-this-cmd-keys)))))
6571         (select-window action-window))))
6572
6573   (defun icicle-keys+cmds-w-prefix (prefix)
6574     "Fill `icicle-complete-keys-alist' for prefix key PREFIX (a vector)."
6575     (let ((prefix-map           nil)
6576           (icicle-key-prefix-2  prefix))
6577       (setq icicle-complete-keys-alist  ())
6578       (dolist (icicle-active-map  (current-active-maps t))
6579         (setq prefix-map  (lookup-key icicle-active-map prefix))
6580         ;; NOTE: `icicle-add-key+cmd' uses `icicle-key-prefix-2' and `icicle-active-map' as free vars.
6581         (when (keymapp prefix-map) (map-keymap #'icicle-add-key+cmd prefix-map)))
6582       (unless (equal [] prefix)
6583         (push (list (intern (propertize ".." 'face 'icicle-multi-command-completion)))
6584               icicle-complete-keys-alist))
6585       icicle-complete-keys-alist))
6586
6587   ;; Free vars here: `icicle-key-prefix-2' and `icicle-active-map' are bound in
6588   ;; `icicle-keys+cmds-w-prefix'.
6589   (defun icicle-add-key+cmd (event binding)
6590     "Add completion for EVENT and BINDING to `icicle-complete-keys-alist'."
6591     (cond
6592       ;; (menu-item ITEM-STRING): non-selectable item - skip it.
6593       ((and (eq 'menu-item (car-safe binding))
6594             (null (cdr-safe (cdr-safe binding))))
6595        (setq binding  nil))             ; So `keymapp' test, below, fails.
6596
6597       ;; (ITEM-STRING): non-selectable item - skip it.
6598       ((and (stringp (car-safe binding)) (null (cdr-safe binding)))
6599        (setq binding  nil))             ; So `keymapp' test, below, fails.
6600
6601       ;; (menu-item ITEM-STRING REAL-BINDING . PROPERTIES)
6602       ((eq 'menu-item (car-safe binding))
6603        (let ((enable-condition  (memq ':enable (cdr-safe (cdr-safe (cdr-safe binding))))))
6604          (if (or (not enable-condition)
6605                  (condition-case nil    ; Don't enable if we can't check the condition.
6606                      (eval (cadr enable-condition))
6607                    (error nil)))
6608              (setq binding  (car-safe (cdr-safe (cdr-safe binding))))
6609            (setq binding  nil))))
6610
6611       ;; (ITEM-STRING . REAL-BINDING) or
6612       ;; (ITEM-STRING [HELP-STRING] . REAL-BINDING) or
6613       ;; (ITEM-STRING [HELP-STRING] (KEYBD-SHORTCUTS) . REAL-BINDING)
6614       ((stringp (car-safe binding))
6615        (setq binding  (cdr binding))
6616        ;; Skip HELP-STRING
6617        (when (stringp (car-safe binding)) (setq binding  (cdr binding)))
6618        ;; Skip (KEYBD-SHORTCUTS): cached key-equivalence data for menu items.
6619        (when (and (consp binding) (consp (car binding))) (setq binding  (cdr binding)))))
6620
6621     ;; Follow indirections to ultimate symbol naming a command.
6622     (while (and (symbolp binding) (fboundp binding) (keymapp (symbol-function binding)))
6623       (setq binding  (symbol-function binding)))
6624
6625     ;; `icicle-key-prefix-2' and `icicle-active-map' are free here, bound in
6626     ;; `icicle-keys+cmds-w-prefix'.
6627     (cond ((and (eq binding 'self-insert-command) ; Insert `self-insert-command' char ranges.
6628                 icicle-complete-keys-self-insert-ranges
6629                 (consp event)           ; Emacs 23+ uses char ranges.
6630                 (fboundp 'characterp) (characterp (car event)))
6631            (let ((chr1  (car event))
6632                  (chr2  (cdr event)))
6633              (loop for range in icicle-complete-keys-self-insert-ranges do
6634                    (loop for char from (max chr1 (car range)) to (min chr2  (cdr range)) do
6635                          (let* ((key-desc   (propertize (single-key-description
6636                                                          char
6637                                                          (not icicle-key-descriptions-use-<>-flag))
6638                                                         'face 'icicle-candidate-part))
6639                                 (candidate  (intern (concat key-desc "  =  self-insert-command"))))
6640                            (push (cons candidate (cons (vector char) 'self-insert-command))
6641                                  icicle-complete-keys-alist)
6642                            (when (eq icicle-active-map (current-local-map))
6643                              (put candidate 'icicle-special-candidate t)))))))
6644           ((and (or (keymapp binding)
6645                     (and (commandp binding)
6646                          (equal binding (key-binding (vconcat icicle-key-prefix-2 (vector event))))
6647                          (not (eq binding 'icicle-complete-keys))))
6648                 (or (not (eq binding 'self-insert-command)) ; Command, keymap.
6649                     (and icicle-complete-keys-self-insert-ranges ; Insert char (Emacs 22).
6650                          (char-valid-p event))))
6651            (let* ((key-desc   (propertize (single-key-description
6652                                            event
6653                                            (not icicle-key-descriptions-use-<>-flag))
6654                                           'face 'icicle-candidate-part))
6655                   (candidate  (intern (concat key-desc "  =  " (if (keymapp binding)
6656                                                                    "..."
6657                                                                  (prin1-to-string binding))))))
6658              ;; Skip keys bound to `undefined'.
6659              (unless (string= "undefined" (prin1-to-string binding))
6660                (push (cons candidate (cons (vector event) binding)) icicle-complete-keys-alist))
6661              (when (eq icicle-active-map (current-local-map))
6662                (put candidate 'icicle-special-candidate t))))
6663           ((and (integerp event) (generic-char-p event) ; Insert generic char (Emacs 22).
6664                 (eq 'self-insert-command binding))
6665            (ignore))))                  ; Placeholder for future use.
6666
6667   ;; $$ No longer used.  Was used in `icicle-complete-keys-1'.
6668   (defun icicle-read-single-key-description (string need-vector &optional no-angles)
6669     "If STRING contains a space, then the vector containing the symbol named STRING.
6670 Otherwise, call `icicle-read-kbd-macro'.
6671 Other args are as for `icicle-read-kbd-macro'."
6672     (cond ((and no-angles (string-match " " string)) (vector (intern string)))
6673           ((string-match "^<\\([^>]* [^>]*\\)>" string)
6674            (vector (intern (substring string (match-beginning 1) (match-end 1)))))
6675           (t (icicle-read-kbd-macro string need-vector no-angles))))
6676
6677   ;; $$ No longer used.  Was used as `icicle-candidate-action-fn' in `icicle-complete-keys'.
6678   (defun icicle-complete-keys-help (candidate)
6679     "Describe the command associated with the current completion candidate."
6680     (interactive)                       ; Interactively, just describes itself.
6681     (when (interactive-p) (icicle-barf-if-outside-Completions-and-minibuffer))
6682     (string-match "\\(.+\\)  =  \\(.+\\)" candidate)
6683     (let ((frame-with-focus  (selected-frame))
6684           (cmd               (intern-soft (substring candidate (match-beginning 2) (match-end 2)))))
6685       (if (not (fboundp cmd))
6686           (icicle-msg-maybe-in-minibuffer "No help")
6687         (describe-function cmd))
6688       (icicle-raise-Completions-frame)
6689       ;; This is a hack for MS Windows - otherwise, we can't continue to get more candidates,
6690       ;; because the *Help* frame takes the focus away from the minibuffer frame.
6691       ;; MS Windows always gives focus to a newly created frame - in this case, *Help*.
6692       (let* ((help-window  (get-buffer-window "*Help*" 0))
6693              (help-frame   (and help-window (window-frame help-window))))
6694         (when help-frame (redirect-frame-focus help-frame frame-with-focus))))
6695     (message nil))                      ; Let minibuffer contents show immediately.
6696
6697   (defun icicle-read-kbd-macro (start &optional end no-angles)
6698     "Read the region as a keyboard macro definition.
6699 The region is interpreted as spelled-out keystrokes, e.g., \"M-x abc RET\".
6700 See documentation for `edmacro-mode' for details.
6701 Leading/trailing \"C-x (\" and \"C-x )\" in the text are allowed and ignored.
6702 The resulting macro is installed as the \"current\" keyboard macro.
6703
6704 In Lisp, may also be called with a single STRING argument in which case
6705 the result is returned rather than being installed as the current macro.
6706 The result will be a string if possible, otherwise an event vector.
6707 Second argument NEED-VECTOR means to return an event vector always.
6708
6709 Optional argument NO-ANGLES non-nil means to expect key
6710 descriptions not to use angle brackets (<...>).  For example:
6711
6712  (icicle-read-kbd-macro \"<mode-line>\" t)   returns [mode-line]
6713  (icicle-read-kbd-macro  \"mode-line\"  t t) returns [mode-line]"
6714     (interactive "r")
6715     (if (stringp start)
6716         (icicle-edmacro-parse-keys start end no-angles)
6717       (setq last-kbd-macro
6718             (icicle-edmacro-parse-keys (buffer-substring start end) nil no-angles))))
6719
6720   (defun icicle-edmacro-parse-keys (string &optional need-vector no-angles)
6721     "Same as `edmacro-parse-keys', but with added NO-ANGLES argument.
6722 NO-ANGLES is the same as for `icicle-read-kbd-macro'."
6723     (let ((case-fold-search  nil)
6724           (pos               0)
6725           (res               []))
6726       (while (and (< pos (length string))
6727                   (string-match "[^ \t\n\f]+" string pos))
6728         (let ((word   (substring string (match-beginning 0) (match-end 0)))
6729               (key    nil)
6730               (times  1))
6731           (setq pos  (match-end 0))
6732           (when (string-match "\\([0-9]+\\)\\*." word)
6733             (setq times  (string-to-number (substring word 0 (match-end 1)))
6734                   word   (substring word (1+ (match-end 1)))))
6735           (cond ((string-match "^<<.+>>$" word)
6736                  (setq key  (vconcat (if (eq (key-binding [?\M-x])
6737                                              'execute-extended-command)
6738                                          [?\M-x]
6739                                        (or (car (where-is-internal
6740                                                  'execute-extended-command))
6741                                            [?\M-x]))
6742                                      (substring word 2 -2) "\r")))
6743                 ((or (equal word "REM") (string-match "^;;" word))
6744                  (setq pos  (string-match "$" string pos)))
6745                 ((and (string-match (if no-angles
6746                                         "^\\(\\([ACHMsS]-\\)*\\)\\(..+\\)$"
6747                                       "^\\(\\([ACHMsS]-\\)*\\)<\\(..+\\)>$")
6748                                     word)
6749                       (or (not no-angles)
6750                           (save-match-data (not (string-match "^\\([ACHMsS]-.\\)+$" word))))
6751                       (progn
6752                         (setq word  (concat (substring word (match-beginning 1)
6753                                                        (match-end 1))
6754                                             (substring word (match-beginning 3)
6755                                                        (match-end 3))))
6756                         (not (string-match
6757                               "\\<\\(NUL\\|RET\\|LFD\\|ESC\\|SPC\\|DEL\\)$"
6758                               word))))
6759                  (setq key  (list (intern word))))
6760                 (t
6761                  (let ((orig-word  word)
6762                        (prefix     0)
6763                        (bits       0))
6764                    (while (string-match "^[ACHMsS]-." word)
6765                      (incf bits (cdr (assq (aref word 0)
6766                                            '((?A . ?\A-\^@) (?C . ?\C-\^@)
6767                                              (?H . ?\H-\^@) (?M . ?\M-\^@)
6768                                              (?s . ?\s-\^@) (?S . ?\S-\^@)))))
6769                      (incf prefix 2)
6770                      (callf substring word 2))
6771                    (when (string-match "^\\^.$" word)
6772                      (incf bits ?\C-\^@)
6773                      (incf prefix)
6774                      (callf substring word 1))
6775                    (let ((found  (assoc word '(("NUL" . "\0") ("RET" . "\r")
6776                                                ("LFD" . "\n") ("TAB" . "\t")
6777                                                ("ESC" . "\e") ("SPC" . " ")
6778                                                ("DEL" . "\177")))))
6779                      (when found (setq word  (cdr found))))
6780                    (when (string-match "^\\\\[0-7]+$" word)
6781                      (loop for ch across word
6782                            for n = 0 then (+ (* n 8) ch -48)
6783                            finally do (setq word  (vector n))))
6784                    (cond ((= bits 0)
6785                           (setq key  word))
6786                          ((and (= bits ?\M-\^@) (stringp word)
6787                                (string-match "^-?[0-9]+$" word))
6788                           (setq key  (loop for x across word collect (+ x bits))))
6789                          ((/= (length word) 1)
6790                           (error "%s must prefix a single character, not %s"
6791                                  (substring orig-word 0 prefix) word))
6792                          ((and (/= (logand bits ?\C-\^@) 0) (stringp word)
6793                                ;; We used to accept . and ? here,
6794                                ;; but . is simply wrong,
6795                                ;; and C-? is not used (we use DEL instead).
6796                                (string-match "[@-_a-z]" word))
6797                           (setq key  (list (+ bits (- ?\C-\^@) (logand (aref word 0) 31)))))
6798                          (t
6799                           (setq key  (list (+ bits (aref word 0)))))))))
6800           (when key
6801             (loop repeat times do (callf vconcat res key)))))
6802       (when (and (>= (length res) 4)
6803                  (eq (aref res 0) ?\C-x)
6804                  (eq (aref res 1) ?\()
6805                  (eq (aref res (- (length res) 2)) ?\C-x)
6806                  (eq (aref res (- (length res) 1)) ?\)))
6807         (setq res  (edmacro-subseq res 2 -2)))
6808       (if (and (not need-vector)
6809                (loop for ch across res
6810                      always (and (char-valid-p ch)
6811                                  (let ((ch2  (logand ch (lognot ?\M-\^@))))
6812                                    (and (>= ch2 0) (<= ch2 127))))))
6813           (concat (loop for ch across res
6814                         collect (if (= (logand ch ?\M-\^@) 0)
6815                                     ch (+ ch 128))))
6816         res))))
6817
6818 (when (fboundp 'define-minor-mode)      ; Emacs 21+ ------------
6819   (eval '(define-minor-mode icicle-ido-like-mode
6820           "Ido-like mode for use with Icicles.
6821 No, this mode does not pretend to give you exactly the Ido behavior.
6822
6823 Turning the mode ON sets these options to t:
6824  `icicle-show-Completions-initially-flag'
6825  `icicle-top-level-when-sole-completion-flag'
6826 Turning the mode OFF sets those options to non-nil.
6827
6828 A positive prefix arg turns the mode on and also sets option
6829 `icicle-max-candidates' to the prefix-arg numeric value.  By default,
6830 that option is nil, meaning that there is no limit to the number of
6831 completion candidates.
6832
6833 Since Ido shows only a few completion candidates, you might want to
6834 customize that option or use a prefix arg with this mode to set it.
6835 You can also use `C-x #' in the minibuffer to increment or decrement
6836 the option at any time during completion.
6837
6838 Turning the mode off by toggling (no prefix arg) resets option
6839 `icicle-max-candidates' to nil.  If you have customized that option to
6840 a non-nil value and do not want to lose that preference, then use a
6841 zero or negative prefix arg to turn the mode off.
6842
6843 See also these options, which control how much time you have to edit
6844 input before automatic incremental completion and automatic acceptance
6845 of a sole candidate kick in:
6846
6847  `icicle-incremental-completion-delay'
6848  `icicle-top-level-when-sole-completion-delay'
6849
6850 When you use this mode, you might also want to use nil or t as the
6851 value of option `icicle-default-value', in order to not insert the
6852 default value in the minibuffer.  If you want to change that option
6853 dynamically for the mode, use `icicle-ido-like-mode-hook'.  E.g.:
6854
6855  (add-hook 'icicle-ido-like-mode-hook
6856            (lambda () (setq icicle-default-value
6857                        (if icicle-ido-like-mode t 'insert-end))))"
6858           nil nil nil :global t :group 'Icicles-Miscellaneous
6859           (setq
6860            icicle-show-Completions-initially-flag      icicle-ido-like-mode
6861            icicle-top-level-when-sole-completion-flag  icicle-ido-like-mode)
6862           (if icicle-ido-like-mode
6863               (when (and current-prefix-arg (not (eq 'toggle current-prefix-arg)))
6864                 (setq icicle-max-candidates  (prefix-numeric-value current-prefix-arg)))
6865             (unless (and current-prefix-arg (not (eq 'toggle current-prefix-arg)))
6866               (setq icicle-max-candidates  nil))))))
6867
6868 (defun icicle-set-TAB-methods-for-command (command methods &optional arg msgp)
6869   "Set the possible TAB completion methods for COMMAND.
6870 This works by advising COMMAND.
6871 With a negative prefix arg, restore the original, unadvised behavior.
6872 With a non-negative prefix arg, advise but do not enable the advice.
6873  You can later enable the advice and activate it, using
6874  `ad-enable-advice' and `ad-activate'.  The advice name is
6875  `icicle-TAB-completion-methods' (same name as option).
6876 See also `icicle-set-S-TAB-methods-for-command'."
6877   (interactive (icicle-read-args-for-set-completion-methods 'icicle-TAB-completion-methods))
6878   (icicle-set-completion-methods-for-command
6879    command methods 'icicle-TAB-completion-methods arg msgp))
6880
6881 (defun icicle-set-S-TAB-methods-for-command (command methods &optional arg msgp)
6882   "Set the possible S-TAB completion methods for COMMAND.
6883 This works by advising COMMAND.
6884 With a negative prefix arg, restore the original, unadvised behavior.
6885 With a non-negative prefix arg, advise but do not enable the advice.
6886  You can later enable the advice and activate it, using
6887  `ad-enable-advice' and `ad-activate'.  The advice name is
6888  `icicle-S-TAB-completion-methods-alist' (same name as option).
6889 See also `icicle-set-TAB-methods-for-command'."
6890   (interactive (icicle-read-args-for-set-completion-methods 'icicle-S-TAB-completion-methods-alist))
6891   (icicle-set-completion-methods-for-command
6892    command methods 'icicle-S-TAB-completion-methods-alist arg msgp))
6893
6894 (defun icicle-read-args-for-set-completion-methods (var)
6895   "Read arguments for `icicle-set-(S-)TAB-methods-for-command'.
6896 VAR is symbol `icicle-(S-)TAB-completion-methods(-alist)'."
6897   (let ((command  (intern (let ((icicle-must-pass-after-match-predicate
6898                                  #'(lambda (c) (commandp (intern c)))))
6899                             (completing-read "Command: " obarray nil t))))
6900         (methods  ()))
6901     (unless (< (prefix-numeric-value current-prefix-arg) 0)
6902       (let ((prompt  (if (eq var 'icicle-TAB-completion-methods) "TAB methods: " "S-TAB methods: "))
6903             (cmeths  (symbol-value var))
6904             meth)
6905         (setq cmeths  (if (consp (car cmeths))
6906                           cmeths
6907                         (mapcar (lambda (m) (list (symbol-name m))) cmeths)))
6908         (while (not (string= "" (setq meth  (completing-read prompt cmeths nil t))))
6909           (if (eq var 'icicle-TAB-completion-methods)
6910               (push (intern meth) methods)
6911             (push (assoc meth icicle-S-TAB-completion-methods-alist) methods)))
6912         (setq methods  (nreverse methods))))
6913     (list command methods current-prefix-arg (prefix-numeric-value current-prefix-arg))))
6914
6915 (defun icicle-set-completion-methods-for-command (command methods var arg msgp)
6916   "Set the possible completion methods for COMMAND.
6917 This works by advising COMMAND.
6918 VAR is the methods option to affect, `icicle-TAB-completion-methods'
6919  or `icicle-S-TAB-completion-methods-alist'.
6920 Negative ARG means restore the original, unadvised behavior.
6921 Non-negative ARG means advise but do not enable the advice.
6922 Null ARG means advise and enable."
6923   (let ((type  (if (eq var 'icicle-TAB-completion-methods) "TAB methods" "S-TAB methods")))
6924     (cond ((< (prefix-numeric-value arg) 0)
6925            (condition-case nil
6926                (ad-remove-advice command 'around var)
6927              (error nil))
6928            (ad-activate command)        ; This restores original definition unless otherwise advised.
6929            (when msgp (message "`%s' now uses default %s" command type)))
6930           (t
6931            (ad-add-advice command `(,var
6932                                     nil ,(not arg)
6933                                     (advice . (lambda () (let ((,var  ',methods)) ad-do-it))))
6934                           'around 'first)
6935            (ad-activate command)
6936            (when msgp (message "`%s' %s: %s" command type
6937                                (if (consp (car methods)) (mapcar #'car methods) methods)))))))
6938  
6939 ;;(@* "Icicles Commands for Other Packages")
6940 ;;; ** Icicles Commands for Other Packages **
6941
6942 ;;; Library `highlight.el' - Icicles multi-commands.  Emacs 21+.
6943 ;;;
6944 ;;;###autoload (autoload 'icicle-choose-faces           "icicles-cmd2.el")
6945 ;;;###autoload (autoload 'icicle-choose-invisible-faces "icicles-cmd2.el")
6946 ;;;###autoload (autoload 'icicle-choose-visible-faces   "icicles-cmd2.el")
6947 ;;;###autoload (autoload 'icicle-hide-faces             "icicles-cmd2.el")
6948 ;;;###autoload (autoload 'icicle-hide-only-faces        "icicles-cmd2.el")
6949 ;;;###autoload (autoload 'icicle-show-faces             "icicles-cmd2.el")
6950 ;;;###autoload (autoload 'icicle-show-only-faces        "icicles-cmd2.el")
6951 (eval-after-load "highlight"
6952   '(when (fboundp 'next-single-char-property-change) ; Don't bother, for Emacs 20.
6953
6954     (icicle-define-command icicle-choose-faces
6955       "Choose a list of face names (strings).
6956 Option `hlt-act-on-any-face-flag' determines whether only highlighting
6957 faces in the buffer are candidates.  The list of names (strings) is
6958 returned."
6959       (lambda (name) (push name face-names)) ; Action function
6960       prompt                            ; `completing-read' args
6961       (mapcar #'icicle-make-face-candidate
6962               (if hlt-act-on-any-face-flag
6963                   (face-list)
6964                 (hlt-highlight-faces-in-buffer (point-min) (point-max))))
6965       nil (not (stringp icicle-WYSIWYG-Completions-flag)) nil
6966       (if (boundp 'face-name-history) 'face-name-history 'icicle-face-name-history) nil nil
6967       ((icicle-list-nth-parts-join-string  ": ") ; Additional bindings
6968        (icicle-list-join-string            ": ")
6969        ;; $$$$$$ (icicle-list-end-string             "")
6970        (icicle-list-use-nth-parts          '(1))
6971        (prompt                             (copy-sequence "Choose face (`RET' when done): "))
6972        (face-names                         ()))
6973       (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code.
6974       nil                               ; Undo code.
6975       (prog1 (setq face-names  (delete "" face-names)) ; Return the list of faces.
6976         (when (interactive-p) (message "Faces: %S" face-names))))
6977
6978     (icicle-maybe-byte-compile-after-load icicle-choose-faces)
6979
6980
6981     (icicle-define-command icicle-choose-invisible-faces
6982       "Choose a list of face names (strings) from currently invisible faces.
6983 Option `hlt-act-on-any-face-flag' determines whether only highlighting
6984 faces in the buffer are candidates.  The list of names (strings) is
6985 returned."
6986       (lambda (name) (push name face-names)) ; Action function
6987       prompt                            ; `completing-read' args
6988       (mapcar #'icicle-make-face-candidate
6989               (icicle-remove-if-not #'icicle-invisible-face-p
6990                                     (if hlt-act-on-any-face-flag
6991                                         (face-list)
6992                                       (hlt-highlight-faces-in-buffer (point-min) (point-max)))))
6993       nil (not (stringp icicle-WYSIWYG-Completions-flag)) nil
6994       (if (boundp 'face-name-history) 'face-name-history 'icicle-face-name-history) nil nil
6995       ((icicle-list-nth-parts-join-string  ": ") ; Additional bindings
6996        (icicle-list-join-string            ": ")
6997        ;; $$$$$$ (icicle-list-end-string             "")
6998        (icicle-list-use-nth-parts          '(1))
6999        (prompt                             (copy-sequence "Choose face (`RET' when done): "))
7000        (face-names                         ()))
7001       (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code.
7002       nil                               ; Undo code.
7003       (prog1 (setq face-names  (delete "" face-names)) ; Return the list of faces.
7004         (when (interactive-p) (message "Faces: %S" face-names))))
7005
7006     (icicle-maybe-byte-compile-after-load icicle-choose-invisible-faces)
7007
7008
7009     (icicle-define-command icicle-choose-visible-faces
7010       "Choose a list of face names (strings) from currently visible faces.
7011 Option `hlt-act-on-any-face-flag' determines whether only highlighting
7012 faces in the buffer are candidates.  The list of names (strings) is
7013 returned."
7014       (lambda (name) (push name face-names)) ; Action function
7015       prompt                            ; `completing-read' args
7016       (mapcar #'icicle-make-face-candidate
7017               (icicle-remove-if #'icicle-invisible-face-p
7018                                 (if hlt-act-on-any-face-flag
7019                                     (face-list)
7020                                   (hlt-highlight-faces-in-buffer (point-min) (point-max)))))
7021       nil (not (stringp icicle-WYSIWYG-Completions-flag)) nil
7022       (if (boundp 'face-name-history) 'face-name-history 'icicle-face-name-history) nil nil
7023       ((icicle-list-nth-parts-join-string  ": ") ; Additional bindings
7024        (icicle-list-join-string            ": ")
7025        ;; $$$$$$ (icicle-list-end-string             "")
7026        (icicle-list-use-nth-parts          '(1))
7027        (prompt                             (copy-sequence "Choose face (`RET' when done): "))
7028        (face-names                         ()))
7029       (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code.
7030       nil                               ; Undo code.
7031       (prog1 (setq face-names  (delete "" face-names)) ; Return the list of faces.
7032         (when (interactive-p) (message "Faces: %S" face-names))))
7033   
7034     (icicle-maybe-byte-compile-after-load icicle-choose-visible-faces)
7035
7036
7037     (defun icicle-show-only-faces (&optional start end faces)
7038       "Show only the faces you choose, hiding all others.
7039 Non-nil `hlt-act-on-any-face-flag' means choose from among all
7040 faces.  Nil means choose only from among faces used to highlight.
7041
7042 When choosing faces, completion and cycling are available. During
7043 cycling, these keys with prefix `C-' act on the current face name:
7044
7045 `C-mouse-2', `C-RET' - Choose current face candidate only
7046 `C-down'  - Choose, then move to next prefix-completion candidate
7047 `C-up'    - Choose, then move to previous prefix-completion candidate
7048 `C-next'  - Choose, then move to next apropos-completion candidate
7049 `C-prior' - Choose, then move to previous apropos-completion candidate
7050 `C-!'     - Choose *all* matching face names"
7051       (interactive `(,@(hlt-region-or-buffer-limits)
7052                      ,(mapcar #'intern (icicle-choose-faces)))) ; An Icicles multi-command
7053       (dolist (face (if hlt-act-on-any-face-flag
7054                         (face-list)
7055                       (hlt-highlight-faces-in-buffer start end)))
7056         (if (memq face faces)
7057             (hlt-show-default-face face)
7058           (hlt-hide-default-face start end face))))
7059   
7060     (icicle-maybe-byte-compile-after-load icicle-show-only-faces)
7061
7062
7063     (defun icicle-hide-only-faces (&optional start end faces)
7064       "Hide only the faces you choose, showing all others.
7065 Non-nil `hlt-act-on-any-face-flag' means choose from among all
7066 faces.  Nil means choose only from among faces used to highlight.
7067
7068 When choosing faces, completion and cycling are available. During
7069 cycling, these keys with prefix `C-' act on the current face name:
7070
7071 `C-mouse-2', `C-RET' - Choose current face candidate only
7072 `C-down'  - Choose, then move to next prefix-completion candidate
7073 `C-up'    - Choose, then move to previous prefix-completion candidate
7074 `C-next'  - Choose, then move to next apropos-completion candidate
7075 `C-prior' - Choose, then move to previous apropos-completion candidate
7076 `C-!'     - Choose *all* matching face names"
7077       (interactive `(,@(hlt-region-or-buffer-limits)
7078                      ,(mapcar #'intern (icicle-choose-faces)))) ; An Icicles multi-command
7079       (dolist (face (if hlt-act-on-any-face-flag
7080                         (face-list)
7081                       (hlt-highlight-faces-in-buffer start end)))
7082         (if (memq face faces)
7083             (hlt-hide-default-face start end face)
7084           (hlt-show-default-face face))))
7085
7086     (icicle-maybe-byte-compile-after-load icicle-hide-only-faces)
7087
7088
7089     (defun icicle-show-faces (faces)
7090       "Show invisible faces that you choose.  Do nothing to other faces.
7091 Non-nil `hlt-act-on-any-face-flag' means choose from among all
7092 invisible faces.  Nil means choose only from among invisible faces
7093 used to highlight.
7094
7095 When choosing faces, completion and cycling are available. During
7096 cycling, these keys with prefix `C-' act on the current face name:
7097
7098 `C-mouse-2', `C-RET' - Choose current face candidate only
7099 `C-down'  - Choose, then move to next prefix-completion candidate
7100 `C-up'    - Choose, then move to previous prefix-completion candidate
7101 `C-next'  - Choose, then move to next apropos-completion candidate
7102 `C-prior' - Choose, then move to previous apropos-completion candidate
7103 `C-!'     - Choose *all* matching face names"
7104       (interactive
7105        (list (let ((fs  (icicle-remove-if-not #'icicle-invisible-face-p
7106                                               (if hlt-act-on-any-face-flag
7107                                                   (face-list)
7108                                                 (hlt-highlight-faces-in-buffer
7109                                                  (point-min) (point-max))))))
7110                (if fs
7111                    (mapcar #'intern (icicle-choose-invisible-faces)) ; An Icicles multi-command
7112                  (error "No%s faces are invisible"
7113                         (if hlt-act-on-any-face-flag "" " highlight"))))))
7114       (dolist (face faces) (hlt-show-default-face face)))
7115   
7116     (icicle-maybe-byte-compile-after-load icicle-show-faces)
7117
7118
7119     (defun icicle-hide-faces (&optional start end faces)
7120       "Hide visible faces that you choose.  Do nothing to other faces.
7121 Non-nil `hlt-act-on-any-face-flag' means choose from among all
7122 visible faces.  Nil means choose only from among visible faces used to
7123 highlight.
7124
7125 When choosing faces, completion and cycling are available. During
7126 cycling, these keys with prefix `C-' act on the current face name:
7127
7128 `C-mouse-2', `C-RET' - Choose current face candidate only
7129 `C-down'  - Choose, then move to next prefix-completion candidate
7130 `C-up'    - Choose, then move to previous prefix-completion candidate
7131 `C-next'  - Choose, then move to next apropos-completion candidate
7132 `C-prior' - Choose, then move to previous apropos-completion candidate
7133 `C-!'     - Choose *all* matching face names"
7134       (interactive `(,@(hlt-region-or-buffer-limits)
7135                      ,(mapcar #'intern (icicle-choose-faces)))) ; An Icicles multi-command
7136       (dolist (face faces) (hlt-hide-default-face start end face)))
7137
7138     (icicle-maybe-byte-compile-after-load icicle-hide-faces)
7139
7140     ))
7141
7142
7143 ;;; Library `palette.el' - Icicles multi-commands.
7144 ;;;
7145 ;;;###autoload (autoload 'icicle-pick-color-by-name "icicles-cmd2.el")
7146 (eval-after-load "palette"
7147   '(progn
7148
7149     (icicle-define-command icicle-pick-color-by-name ; Bound to `c' in color palette.
7150       "Set the current color to a color you name.
7151 Instead of a color name, you can use an RGB string #XXXXXXXXXXXX,
7152 where each X is a hex digit.  The number of Xs must be a multiple of
7153 3, with the same number of Xs for each of red, green, and blue.
7154 If you enter an empty color name, then a color is picked randomly.
7155 The new current color is returned."     ; Doc string
7156       icicle-pick-color-by-name-action  ; Action function
7157       "Color (name or #R+G+B+): "       ; `completing-read' arguments
7158       (hexrgb-defined-colors-alist) nil nil nil nil nil nil
7159       ((completion-ignore-case  t)))    ; Bindings
7160
7161     (icicle-maybe-byte-compile-after-load icicle-pick-color-by-name)
7162
7163
7164     (defun icicle-pick-color-by-name-action (color)
7165       "Action function for `icicle-pick-color-by-name'."
7166       (if (string= "" color)
7167           (let* ((colors  (hexrgb-defined-colors))
7168                  (rand    (random (length colors)))) ; Random color.
7169             (setq color  (elt colors rand)))
7170         (let ((hex-string  (hexrgb-rgb-hex-string-p color t)))
7171           (when (and hex-string (not (eq 0 hex-string))) (setq color  (concat "#" color))) ; Add #.
7172           (if (not (or hex-string (if (fboundp 'test-completion) ; Not defined in Emacs 20.
7173                                       (test-completion color (hexrgb-defined-colors-alist))
7174                                     (try-completion color (hexrgb-defined-colors-alist)))))
7175               (error "No such color: %S" color)
7176             (setq color  (hexrgb-color-name-to-hex color))))
7177         (setq palette-last-color  palette-current-color)
7178         (save-selected-window
7179           (setq color  (hexrgb-color-name-to-hex color)) ; Needed if not interactive.
7180           (palette-set-current-color color)
7181           (palette-where-is-color color)
7182           (palette-brightness-scale)
7183           (palette-swatch))
7184         palette-current-color))
7185
7186     (icicle-maybe-byte-compile-after-load icicle-pick-color-by-name-action)
7187
7188
7189     (define-key palette-mode-map "c"  'icicle-pick-color-by-name)
7190     (define-key palette-popup-map [pick-color-by-name] ; Use same name as in `palette.el'.
7191       `(menu-item "Choose Color By Name" icicle-pick-color-by-name
7192         :help "Set the current color to a color you name"))
7193     ))
7194
7195
7196 ;;; Library `synonyms.el' - Icicles multi-commands.
7197 ;;;
7198 ;;;###autoload (autoload 'synonyms                        "icicles-cmd2.el")
7199 ;;;###autoload (autoload 'icicle-synonyms                 "icicles-cmd2.el")
7200 ;;;###autoload (autoload 'icicle-insert-thesaurus-entry   "icicles-cmd2.el")
7201 ;;;###autoload (autoload 'icicle-complete-thesaurus-entry "icicles-cmd2.el")
7202 (eval-after-load "synonyms"
7203   '(progn
7204
7205     (defalias 'synonyms 'icicle-synonyms)
7206     (icicle-define-command icicle-synonyms ; Command
7207       "Show synonyms that match a regular expression (e.g. a word or phrase).
7208 You are prompted for the regexp.  By default, it is the text
7209 of the region, if it is active and `transient-mark-mode' is enabled,
7210 or the nearest word to the cursor, if not.
7211
7212 Option `synonyms-match-more-flag' non-nil means additional thesaurus
7213   entries can be matched.  This can be more time-consuming.  It means
7214   two things:
7215
7216   1) Input can match parts of synonyms, in addition to whole synonyms.
7217   2) All synonyms are shown, even if input matches a thesaurus entry.
7218
7219 Option `synonyms-append-result-flag' non-nil means to append search
7220   result to previous results.
7221
7222 A prefix argument toggles the meaning of each of those options for the
7223 duration of the command:
7224
7225   If `C-u' or `C-u C-u', then toggle `synonyms-match-more-flag'.
7226   If negative or `C-u C-u', then toggle `synonyms-append-result-flag'.
7227
7228 \(`C-u C-u' thus means toggle both options.)
7229
7230 When called from Lisp, optional second argument REGEXP is the regexp
7231 to match (no prompting)."               ; Doc string
7232       synonyms-action                   ; Action function,  defined in `synonyms.el'.
7233       "Show synonyms for word or phrase (regexp): " ; `completing-read' arguments
7234       synonyms-obarray nil nil nil 'synonyms-history (synonyms-default-regexp) nil
7235       ((num-arg (prefix-numeric-value current-prefix-arg)) ; Bindings
7236        (morep (eq synonyms-match-more-flag (atom current-prefix-arg)))
7237        (appendp (eq synonyms-append-result-flag (and (wholenump num-arg) (/= 16 num-arg))))
7238        (icicle-sort-function 'icicle-case-insensitive-string-less-p))
7239       (synonyms-ensure-synonyms-read-from-cache)) ; Fill `synonyms-obarray' initially, for completion.
7240
7241     (icicle-maybe-byte-compile-after-load icicle-synonyms)
7242
7243
7244     (icicle-define-command icicle-insert-thesaurus-entry ; Command name
7245       "Insert an entry from a thesaurus.
7246 Library `synonyms.el' is needed for this.  If you have never used
7247 command `synonyms' before, then the first use of
7248 `icicle-insert-thesaurus-entry' will take a while, because it will
7249 build a cache file of synonyms that are used for completion.  See
7250 `synonyms.el'.
7251
7252 Remember that you can use `\\<minibuffer-local-completion-map>\
7253 \\[icicle-toggle-incremental-completion] to toggle incremental completion." ; Doc string
7254       icicle-insert-thesaurus-entry-cand-fn ; Action function
7255       "Thesaurus entry to match: " synonyms-obarray ; `completing-read' args
7256       nil t nil 'icicle-dictionary-history nil nil
7257       ((icicle-track-pt  (point)))      ; Bindings
7258       (progn                            ; First code
7259         (unless (or (boundp 'synonyms-obarray) (require 'synonyms nil t))
7260           (error "You must first load library `synonyms.el'"))
7261         (synonyms-ensure-synonyms-read-from-cache))
7262       nil                               ; Undo code
7263       (when (window-live-p icicle-orig-window) ; Last code
7264         (select-window icicle-orig-window)
7265         (select-frame-set-input-focus (selected-frame))
7266         (goto-char icicle-track-pt)))
7267
7268     (icicle-maybe-byte-compile-after-load icicle-insert-thesaurus-entry)
7269
7270
7271     ;; Free vars here: `icicle-orig-buff' is bound in `icicle-insert-thesaurus-entry'.
7272     (defun icicle-insert-thesaurus-entry-cand-fn (string)
7273       "Action function for `icicle-insert-thesaurus-entry'.
7274 Insert STRING, followed by a space, at position TRACK-PT of buffer
7275 ORIG-BUFF."
7276       (set-buffer icicle-orig-buff)
7277       (goto-char icicle-track-pt)
7278       (insert string " ")
7279       (setq icicle-track-pt  (point))
7280       (unless (pos-visible-in-window-p) (recenter icicle-recenter))
7281       (with-current-buffer (window-buffer (minibuffer-window)) (icicle-clear-minibuffer))
7282       (save-selected-window (icicle-remove-Completions-window)))
7283
7284     (icicle-maybe-byte-compile-after-load icicle-insert-thesaurus-entry-cand-fn)
7285
7286
7287     (defun icicle-complete-thesaurus-entry (word) ; Bound to `C-c /' in Icicle mode.
7288       "Complete WORD to an entry from a thesaurus.
7289 The default value of WORD is the word at the cursor.
7290 Library `synonyms.el' is needed for this.  If you have never used
7291 command `synonyms' before, then the first use of
7292 `icicle-insert-thesaurus-entry' will take a while, because it will
7293 build a cache file of synonyms that are used for completion.  See
7294 `synonyms.el'."
7295       (interactive (list (word-at-point)))
7296       (unless word (error "No word at point to complete"))
7297       (unless (or (boundp 'synonyms-obarray) (require 'synonyms nil t))
7298         (error "You must first load library `synonyms.el'"))
7299       (synonyms-ensure-synonyms-read-from-cache)
7300       (when (and (looking-at "\\b") (not (looking-at "\\s-"))) (forward-word 1))
7301       (delete-region (progn (forward-word -1) (point)) (progn (forward-word 1) (point)))
7302       (insert (completing-read "Thesaurus entry to match: " synonyms-obarray
7303                                nil nil word 'icicle-dictionary-history word))
7304       (unless (looking-at "\\s-") (insert " ")))
7305
7306     (icicle-maybe-byte-compile-after-load icicle-complete-thesaurus-entry)
7307
7308     ))
7309
7310 ;;; Library `Bookmark+' - Icicles multi-commands.
7311 ;;;
7312 ;;;###autoload (autoload 'icicle-tag-a-file                              "icicles-cmd2.el")
7313 ;;;###autoload (autoload 'icicle-untag-a-file                            "icicles-cmd2.el")
7314 ;;;###autoload (autoload 'icicle-find-file-tagged                        "icicles-cmd2.el")
7315 ;;;###autoload (autoload 'icicle-find-file-tagged-other-window           "icicles-cmd2.el")
7316 ;;;###autoload (autoload 'icicle-find-file-all-tags                      "icicles-cmd2.el")
7317 ;;;###autoload (autoload 'icicle-find-file-all-tags-other-window         "icicles-cmd2.el")
7318 ;;;###autoload (autoload 'icicle-find-file-all-tags-regexp               "icicles-cmd2.el")
7319 ;;;###autoload (autoload 'icicle-find-file-all-tag-regexp-other-windows  "icicles-cmd2.el")
7320 ;;;###autoload (autoload 'icicle-find-file-some-tags                     "icicles-cmd2.el")
7321 ;;;###autoload (autoload 'icicle-find-file-some-tags-other-window        "icicles-cmd2.el")
7322 ;;;###autoload (autoload 'icicle-find-file-some-tags-regexp              "icicles-cmd2.el")
7323 ;;;###autoload (autoload 'icicle-find-file-some-tags-regexp-other-window "icicles-cmd2.el")
7324 (eval-after-load "bookmark+"
7325   '(progn
7326
7327     (icicle-define-file-command icicle-bookmark-a-file ; `C-x p c a'
7328       "Bookmark a file (create an autofile bookmar).
7329 \(You need library `Bookmark+' for this command.)
7330 When prompted for the file you can use `M-n' to pick up the file name
7331 at point, or if none then the visited file.
7332 The autofile bookmark created has the same name as the file.
7333
7334 During file-name completion:
7335  You can use `C-x a +' or `C-x a -' to add or remove tags from the
7336   current-candidate file.  You are prompted for the tags.
7337   (This action requires library `Bookmark+'.)
7338  You can use `C-c C-d' (a la `cd') to change the `default-directory'.
7339  You can use `C-c +' to create a new directory.
7340  You can use `M-|' to open Dired on currently matching file names.
7341  You can use `S-delete' to delete a candidate file or (empty) dir."
7342       (lambda (file) (bmkp-bookmark-a-file file nil nil 'MSG))
7343       "File to bookmark (autofile): " nil nil nil nil nil ; `read-file-name' args
7344       (icicle-file-bindings             ; Bindings
7345        ((icicle-use-candidates-only-once-flag  t)
7346         (icicle-all-candidates-list-alt-action-fn ; `M-|'
7347          (lambda (files) (let ((enable-recursive-minibuffers  t))
7348                            (dired-other-window (cons (read-string "Dired buffer name: ") files)))))))
7349       (icicle-bind-file-candidate-keys) ; First code
7350       nil                               ; Undo code
7351       (icicle-unbind-file-candidate-keys)) ; Last code
7352
7353     (icicle-maybe-byte-compile-after-load icicle-bookmark-a-file)
7354
7355
7356     (icicle-define-file-command icicle-tag-a-file ; `C-x p t + a'
7357       "Tag a file (an autofile bookmark) with one or more tags.
7358 You are prompted for the tags, then the file name.
7359 Hit `RET' to enter each tag, then hit `RET' again after the last tag.
7360 You can use completion to enter each tag.  Completion is lax: you are
7361 not limited to existing tags.
7362
7363 When prompted for the file you can use `M-n' to pick up the file name
7364 at point, or if none then the visited file.
7365
7366 The tags are added to an autofile bookmark for the same file name and
7367 directory.  If the bookmark does not yet exist it is created.
7368 Candidate help shows information about the file's autofile bookmark if
7369 it already exists, or the file itself if not."
7370       (lambda (file) (bmkp-autofile-add-tags file tags nil nil 'MSG))
7371       "File to tag: " nil nil nil nil nil ; `read-file-name' args
7372       (icicle-file-bindings             ; Bindings
7373        ((tags                                  (bmkp-read-tags-completing))
7374         (icicle-use-candidates-only-once-flag  t))))
7375
7376     (icicle-maybe-byte-compile-after-load icicle-tag-a-file)
7377
7378
7379     (icicle-define-file-command icicle-untag-a-file ; `C-x p t - a'
7380       "Remove one or more tags from a file (an autofile bookmark).
7381 You are prompted for the tags, then the file name.
7382 Hit `RET' to enter each tag, then hit `RET' again after the last tag.
7383 You can use completion to enter each tag.  Completion is lax: you are
7384 not limited to existing tags.
7385
7386 When prompted for the file you can use `M-n' to pick up the file name
7387 at point, or if none then the visited file.
7388
7389 The tags are removed from an autofile bookmark for the same file name
7390 and directory.  During file-name completion, only files tagged with
7391 all of the given input tags are completion candidates."
7392       (lambda (file)
7393         (bmkp-autofile-remove-tags file tags nil nil 'MSG))
7394       "File to untag: " nil nil t nil nil ; `read-file-name' args
7395       (icicle-file-bindings             ; Bindings
7396        ((tags                                  (bmkp-read-tags-completing)) ; Pre bindings
7397         (icicle-use-candidates-only-once-flag  t))
7398        ((icicle-must-pass-after-match-predicate ; Post bindings
7399          #'(lambda (ff)
7400              ;; Expand relative file name, using directory from minibuffer.
7401              (setq ff  (expand-file-name ff (icicle-file-name-directory-w-default
7402                                              (icicle-input-from-minibuffer))))
7403              (let* ((bmk   (bmkp-get-autofile-bookmark ff))
7404                     (btgs  (and bmk (bmkp-get-tags bmk))))
7405                (and btgs  (catch 'icicle-untag-a-file
7406                             (dolist (tag  tags) (when (not (member tag btgs))
7407                                                   (throw 'icicle-untag-a-file nil)))
7408                             t))))))))
7409
7410     (icicle-maybe-byte-compile-after-load icicle-untag-a-file)
7411
7412
7413     ;;$$$  Do not bother with autofiles that have a PREFIX.
7414     (icicle-define-command icicle-find-file-tagged ; Command name
7415       "Find one or more files with tags that match your input.
7416 By default, only tagged files are candidates.  With a prefix argument,
7417 all autofiles are candidates.  (Autofiles are autofile bookmarks - you
7418 need library `Bookmark+' for this command.)
7419
7420 Each completion candidate is a multi-completion composed of these
7421 fields: an absolute file name plus the file's tags, all separated by
7422 `icicle-list-join-string' (\"^G^J\", by default).  As always, you can
7423 type `C-M-j' to insert this separator into the minibuffer.
7424
7425 For this command, by default `.' in your input matches any character,
7426 including a newline.  As always, you can use `C-M-.' to toggle
7427 this (so `.' does not match newline).
7428
7429 You can match your input against the file name or tags or both.
7430
7431 E.g., type:
7432
7433  `red S-TAB'                    to match all files with the tag `red'
7434  `red M-SPC green M-SPC blue'   to match all files with tags `red',
7435                                 `green', and `blue' (in any order)
7436
7437 That assumes that these tags do not also match any file names.
7438
7439 If you need to match against a particular field (e.g. the file name or
7440 a specific tag position), then use the field separator.  Otherwise,
7441 just use progressive completion, as shown above.
7442
7443 E.g., to match only tags and not the filename, start with `C-M-j' to
7444 get past the file-name field.  To match both file name and tags, type
7445 something to match the file name before the `C-M-j'.  E.g., type:
7446
7447  `2011 C-M-j red M-SPC blue'    to match all files tagged `red' and
7448                                 `blue' that have `2011' in their names
7449
7450 During completion (`*': requires library `Bookmark+'):
7451
7452  *You can use `C-x a +' or `C-x a -' to add or remove tags from the
7453    current-candidate file.  You are prompted for the tags.
7454  *You can use `C-x m' to access file bookmarks (not just autofiles).
7455   You can use `C-c C-d' (a la `cd') to change the `default-directory'.
7456   You can use `C-c +' to create a new directory.
7457   You can use `M-|' to open Dired on currently matching file names.
7458   You can use `S-delete' to delete a candidate file or (empty) dir." ; Doc string
7459       (lambda (f) (find-file (icicle-transform-multi-completion f) 'WILDCARDS)) ; Action function
7460       prompt icicle-abs-file-candidates ; `completing-read' args
7461       nil nil nil 'icicle-filetags-history nil nil
7462       (icicle-file-bindings             ; Bindings
7463        ((prompt                             "FILE `C-M-j' TAGS: ")
7464         (icicle-full-cand-fn                (lambda (file)
7465                                               (list (cons file
7466                                                           (bmkp-get-tags
7467                                                            (bmkp-get-autofile-bookmark file))))))
7468         (icicle-abs-file-candidates     ; An alist whose items are ((FILE TAG...)).
7469          (let ((result  ()))
7470            (dolist (autofile  (bmkp-autofile-alist-only))
7471              (let ((tags  (bmkp-get-tags autofile)))
7472                (when (or tags current-prefix-arg)
7473                  (push (list (cons (bookmark-get-filename autofile) tags)) result))))
7474            result))
7475         (icicle-dot-string                      (icicle-anychar-regexp))
7476         (icicle-candidate-properties-alist      '((1 (face icicle-candidate-part))))
7477         (icicle-list-use-nth-parts              '(1))
7478         (icicle-whole-candidate-as-text-prop-p  t)))
7479       (progn                            ; First code
7480         (put-text-property 0 1 'icicle-fancy-candidates t prompt)
7481         (icicle-highlight-lighter)
7482         (message "Gathering tagged files...")
7483         (icicle-bind-file-candidate-keys))
7484       nil                               ; Undo code
7485       (icicle-unbind-file-candidate-keys)) ; Last code
7486
7487     (icicle-maybe-byte-compile-after-load icicle-find-file-tagged)
7488
7489
7490     (icicle-define-command icicle-find-file-tagged-other-window ; Command name
7491       "Same as `icicle-find-file-tagged', except uses another window." ; Doc string
7492       (lambda (f) (find-file-other-window (icicle-transform-multi-completion f) 'WILDCARDS)) ; Action
7493       prompt icicle-abs-file-candidates ; `completing-read' args
7494       nil nil nil 'icicle-filetags-history nil nil
7495       (icicle-file-bindings             ; Bindings
7496        ((prompt                                 "FILE `C-M-j' TAGS: ")
7497         (icicle-full-cand-fn                    (lambda (file)
7498                                                   (list (cons file
7499                                                               (bmkp-get-tags
7500                                                                (bmkp-get-autofile-bookmark file))))))
7501         (icicle-abs-file-candidates     ; An alist whose items are ((FILE TAG...)).
7502          (let ((result  ()))
7503            (dolist (autofile  (bmkp-autofile-alist-only))
7504              (let ((tags  (bmkp-get-tags autofile)))                  
7505                (when (or tags current-prefix-arg)
7506                  (push (list (cons (bookmark-get-filename autofile) tags)) result))))
7507            result))
7508         (icicle-dot-string                      (icicle-anychar-regexp))
7509         (icicle-candidate-properties-alist      '((1 (face icicle-candidate-part))))
7510         (icicle-list-use-nth-parts              '(1))
7511         (icicle-whole-candidate-as-text-prop-p  t)))
7512       (progn                            ; First code
7513         (put-text-property 0 1 'icicle-fancy-candidates t prompt)
7514         (icicle-highlight-lighter)
7515         (message "Gathering tagged files...")
7516         (icicle-bind-file-candidate-keys))
7517       nil                               ; Undo code
7518       (icicle-unbind-file-candidate-keys)) ; Last code
7519
7520     (icicle-maybe-byte-compile-after-load icicle-find-file-tagged-other-window)
7521
7522
7523 ;;; These are like multi-command versions of `bmkp-find-file-all-tags' etc.,
7524 ;;; except that the predicate is applied after matching the user's input
7525 ;;; (`icicle-must-pass-after-match-predicate').
7526
7527     (icicle-define-file-command icicle-find-file-all-tags ; `C-x j t a *'
7528       "Visit a file or directory that has all of the tags you enter.
7529 This is otherwise like `icicle-find-file'.
7530 You are prompted for the tags, then the file name.
7531 Hit `RET' to enter each tag, then hit `RET' again after the last tag.
7532 You can use completion to enter each tag.  Completion is lax: you are
7533 not limited to existing tags.
7534
7535 When prompted for the file you can use `M-n' to pick up the file name
7536 at point, or if none then the visited file."
7537       (lambda (file)                    ; Function to perform the action
7538         (let* ((r-o  (if (eq this-command 'icicle-candidate-action)
7539                          (or (and init-pref-arg        (not current-prefix-arg))
7540                              (and (not init-pref-arg)  current-prefix-arg))
7541                        init-pref-arg))
7542                (fn   (if r-o 'find-file-read-only 'find-file)))
7543           (funcall fn file 'WILDCARDS)))
7544       "Find file: " nil nil t nil nil
7545       (icicle-file-bindings             ; Bindings
7546        ((init-pref-arg  current-prefix-arg) ; Pre bindings
7547         (tags           (bmkp-read-tags-completing))
7548         (icicle-all-candidates-list-alt-action-fn ; `M-|'
7549          (lambda (files) (let ((enable-recursive-minibuffers  t))
7550                            (dired-other-window (cons (read-string "Dired buffer name: ") files))))))
7551        ((icicle-must-pass-after-match-predicate ; Post bindings
7552          (lambda (ff) (let* ((bmk   (bmkp-get-autofile-bookmark ff))
7553                              (btgs  (and bmk (bmkp-get-tags bmk))))
7554                         (and btgs  (bmkp-every #'(lambda (tag) (bmkp-has-tag-p bmk tag)) tags))))))))
7555
7556     (icicle-maybe-byte-compile-after-load icicle-find-file-all-tags)
7557
7558
7559     (icicle-define-file-command icicle-find-file-all-tags-other-window ; `C-x 4 j t a *'
7560       "Same as `icicle-find-file-all-tags', except uses another window."
7561       (lambda (file)                    ; Function to perform the action
7562         (let* ((r-o  (if (eq this-command 'icicle-candidate-action)
7563                          (or (and init-pref-arg        (not current-prefix-arg))
7564                              (and (not init-pref-arg)  current-prefix-arg))
7565                        init-pref-arg))
7566                (fn   (if r-o 'find-file-read-only-other-window 'find-file-other-window)))
7567           (funcall fn file 'WILDCARDS)))
7568       "Find file: " nil nil t nil nil
7569       (icicle-file-bindings             ; Bindings
7570        ((init-pref-arg  current-prefix-arg) ; Pre bindings
7571         (tags           (bmkp-read-tags-completing))
7572         (icicle-all-candidates-list-alt-action-fn ; `M-|'
7573          (lambda (files) (let ((enable-recursive-minibuffers  t))
7574                            (dired-other-window (cons (read-string "Dired buffer name: ") files))))))
7575        ((icicle-must-pass-after-match-predicate ; Post bindings
7576          (lambda (ff) (let* ((bmk   (bmkp-get-autofile-bookmark ff))
7577                              (btgs  (and bmk (bmkp-get-tags bmk))))
7578                         (and btgs  (bmkp-every #'(lambda (tag) (bmkp-has-tag-p bmk tag)) tags))))))))
7579
7580     (icicle-maybe-byte-compile-after-load icicle-find-file-all-tags-other-window)
7581
7582
7583     (icicle-define-file-command icicle-find-file-all-tags-regexp ; `C-x j t a % *'
7584       "Visit a file or directory that has each tag matching a regexp you enter.
7585 When prompted for the file you can use `M-n' to pick up the file name
7586 at point, or if none then the visited file."
7587       (lambda (file)                    ; Function to perform the action
7588         (let* ((r-o  (if (eq this-command 'icicle-candidate-action)
7589                          (or (and init-pref-arg        (not current-prefix-arg))
7590                              (and (not init-pref-arg)  current-prefix-arg))
7591                        init-pref-arg))
7592                (fn   (if r-o 'find-file-read-only 'find-file)))
7593           (funcall fn file 'WILDCARDS)))
7594       "Find file: " nil nil t nil nil
7595       (icicle-file-bindings             ; Bindings
7596        ((init-pref-arg  current-prefix-arg) ; Pre bindings
7597         (regexp         (read-string "Regexp for tags: "))
7598         (icicle-all-candidates-list-alt-action-fn ; `M-|'
7599          (lambda (files) (let ((enable-recursive-minibuffers  t))
7600                            (dired-other-window (cons (read-string "Dired buffer name: ") files))))))
7601        ((icicle-must-pass-after-match-predicate ; Post bindings
7602          (lambda (ff)
7603            (let* ((bmk   (bmkp-get-autofile-bookmark ff))
7604                   (btgs  (and bmk (bmkp-get-tags bmk))))
7605              (and btgs  (bmkp-every #'(lambda (tag) (string-match regexp (bmkp-tag-name tag)))
7606                                     btgs))))))))
7607
7608     (icicle-maybe-byte-compile-after-load icicle-find-file-all-tags-regexp)
7609
7610
7611     (icicle-define-file-command icicle-find-file-all-tags-regexp-other-window ; `C-x 4 j t a % *'
7612       "Same as `icicle-find-file-all-tags-regexp', except uses another window."
7613       (lambda (file)                    ; Function to perform the action
7614         (let* ((r-o  (if (eq this-command 'icicle-candidate-action)
7615                          (or (and init-pref-arg        (not current-prefix-arg))
7616                              (and (not init-pref-arg)  current-prefix-arg))
7617                        init-pref-arg))
7618                (fn   (if r-o 'find-file-read-only-other-window 'find-file-other-window)))
7619           (funcall fn file 'WILDCARDS)))
7620       "Find file: " nil nil t nil nil
7621       (icicle-file-bindings             ; Bindings
7622        ((init-pref-arg  current-prefix-arg) ; Pre bindings
7623         (regexp         (read-string "Regexp for tags: "))
7624         (icicle-all-candidates-list-alt-action-fn ; `M-|'
7625          (lambda (files) (let ((enable-recursive-minibuffers  t))
7626                            (dired-other-window (cons (read-string "Dired buffer name: ") files))))))
7627        ((icicle-must-pass-after-match-predicate ; Post bindings
7628          (lambda (ff)
7629            (let* ((bmk   (bmkp-get-autofile-bookmark ff))
7630                   (btgs  (and bmk (bmkp-get-tags bmk))))
7631              (and btgs  (bmkp-every #'(lambda (tag) (string-match regexp (bmkp-tag-name tag)))
7632                                     btgs))))))))
7633
7634     (icicle-maybe-byte-compile-after-load icicle-find-file-all-tags-regexp-other-window)
7635
7636
7637     (icicle-define-file-command icicle-find-file-some-tags ; `C-x j t a +'
7638       "Visit a file or directory that has at least one of the tags you enter.
7639 This is otherwise like `icicle-find-file'.
7640 You are prompted for the tags, then the file name.
7641 Hit `RET' to enter each tag, then hit `RET' again after the last tag.
7642 You can use completion to enter each tag.  Completion is lax: you are
7643 not limited to existing tags.
7644
7645 When prompted for the file you can use `M-n' to pick up the file name
7646 at point, or if none then the visited file."
7647       (lambda (file)                    ; Function to perform the action
7648         (let* ((r-o  (if (eq this-command 'icicle-candidate-action)
7649                          (or (and init-pref-arg        (not current-prefix-arg))
7650                              (and (not init-pref-arg)  current-prefix-arg))
7651                        init-pref-arg))
7652                (fn   (if r-o 'find-file-read-only 'find-file)))
7653           (funcall fn file 'WILDCARDS)))
7654       "Find file: " nil nil t nil nil
7655       (icicle-file-bindings             ; Bindings
7656        ((init-pref-arg  current-prefix-arg) ; Pre bindings
7657         (tags           (bmkp-read-tags-completing))
7658         (icicle-all-candidates-list-alt-action-fn ; `M-|'
7659          (lambda (files) (let ((enable-recursive-minibuffers  t))
7660                            (dired-other-window (cons (read-string "Dired buffer name: ") files))))))
7661        ((icicle-must-pass-after-match-predicate ; Post bindings
7662          (lambda (ff) (let* ((bmk   (bmkp-get-autofile-bookmark ff))
7663                              (btgs  (and bmk (bmkp-get-tags bmk))))
7664                         (and btgs  (bmkp-some  #'(lambda (tag) (bmkp-has-tag-p bmk tag)) tags))))))))
7665
7666     (icicle-maybe-byte-compile-after-load icicle-find-file-some-tags)
7667
7668
7669     (icicle-define-file-command icicle-find-file-some-tags-other-window ; `C-x 4 j t a +'
7670       "Same as `icicle-find-file-some-tags', except uses another window."
7671       (lambda (file)                    ; Function to perform the action
7672         (let* ((r-o  (if (eq this-command 'icicle-candidate-action)
7673                          (or (and init-pref-arg        (not current-prefix-arg))
7674                              (and (not init-pref-arg)  current-prefix-arg))
7675                        init-pref-arg))
7676                (fn   (if r-o 'find-file-read-only-other-window 'find-file-other-window)))
7677           (funcall fn file 'WILDCARDS)))
7678       "Find file: " nil nil t nil nil
7679       (icicle-file-bindings             ; Bindings
7680        ((init-pref-arg  current-prefix-arg) ; Pre bindings
7681         (tags           (bmkp-read-tags-completing))
7682         (icicle-all-candidates-list-alt-action-fn ; `M-|'
7683          (lambda (files) (let ((enable-recursive-minibuffers  t))
7684                            (dired-other-window (cons (read-string "Dired buffer name: ") files))))))
7685        ((icicle-must-pass-after-match-predicate ; Post bindings
7686          (lambda (ff) (let* ((bmk   (bmkp-get-autofile-bookmark ff))
7687                              (btgs  (and bmk (bmkp-get-tags bmk))))
7688                         (and btgs  (bmkp-some #'(lambda (tag) (bmkp-has-tag-p bmk tag)) tags))))))))
7689
7690     (icicle-maybe-byte-compile-after-load icicle-find-file-some-tags-other-window)
7691
7692
7693     (icicle-define-file-command icicle-find-file-some-tags-regexp ; `C-x j t a % +'
7694       "Visit a file or directory that has a tag matching a regexp you enter.
7695 When prompted for the file you can use `M-n' to pick up the file name
7696 at point, or if none then the visited file."
7697       (lambda (file)                    ; Function to perform the action
7698         (let* ((r-o  (if (eq this-command 'icicle-candidate-action)
7699                          (or (and init-pref-arg        (not current-prefix-arg))
7700                              (and (not init-pref-arg)  current-prefix-arg))
7701                        init-pref-arg))
7702                (fn   (if r-o 'find-file-read-only 'find-file)))
7703           (funcall fn file 'WILDCARDS)))
7704       "Find file: " nil nil t nil nil
7705       (icicle-file-bindings             ; Bindings
7706        ((init-pref-arg  current-prefix-arg) ; Pre bindings
7707         (regexp         (read-string "Regexp for tags: "))
7708         (icicle-all-candidates-list-alt-action-fn ; `M-|'
7709          (lambda (files) (let ((enable-recursive-minibuffers  t))
7710                            (dired-other-window (cons (read-string "Dired buffer name: ") files))))))
7711        ((icicle-must-pass-after-match-predicate ; Post bindings
7712          (lambda (ff)
7713            (let* ((bmk   (bmkp-get-autofile-bookmark ff))
7714                   (btgs  (and bmk (bmkp-get-tags bmk))))
7715              (and btgs  (bmkp-some #'(lambda (tag) (string-match regexp (bmkp-tag-name tag)))
7716                                    btgs))))))))
7717
7718     (icicle-maybe-byte-compile-after-load icicle-find-file-some-tags-regexp)
7719
7720
7721     (icicle-define-file-command icicle-find-file-some-tags-regexp-other-window ; `C-x 4 j t a % +'
7722       "Same as `icicle-find-file-some-tags-regexp', except uses another window."
7723       (lambda (file)                    ; Function to perform the action
7724         (let* ((r-o  (if (eq this-command 'icicle-candidate-action)
7725                          (or (and init-pref-arg        (not current-prefix-arg))
7726                              (and (not init-pref-arg)  current-prefix-arg))
7727                        init-pref-arg))
7728                (fn   (if r-o 'find-file-read-only-other-window 'find-file-other-window)))
7729           (funcall fn file 'WILDCARDS)))
7730       "Find file: " nil nil t nil nil
7731       (icicle-file-bindings             ; Bindings
7732        ((init-pref-arg  current-prefix-arg) ; Pre bindings
7733         (regexp         (read-string "Regexp for tags: "))
7734         (icicle-all-candidates-list-alt-action-fn ; `M-|'
7735          (lambda (files) (let ((enable-recursive-minibuffers  t))
7736                            (dired-other-window (cons (read-string "Dired buffer name: ") files))))))
7737        ((icicle-must-pass-after-match-predicate ; Post bindings
7738          (lambda (ff)
7739            (let* ((bmk   (bmkp-get-autofile-bookmark ff))
7740                   (btgs  (and bmk (bmkp-get-tags bmk))))
7741              (and btgs  (bmkp-some #'(lambda (tag) (string-match regexp (bmkp-tag-name tag)))
7742                                    btgs))))))))
7743
7744     (icicle-maybe-byte-compile-after-load icicle-find-file-some-tags-regexp-other-window)
7745
7746     ))
7747
7748 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7749
7750 (provide 'icicles-cmd2)
7751
7752 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7753 ;;; icicles-cmd2.el ends here