1 ;;; icicles-cmd2.el --- Top-level commands for Icicles
3 ;; Filename: icicles-cmd2.el
4 ;; Description: Top-level commands for Icicles
6 ;; Maintainer: Drew Adams
7 ;; Copyright (C) 1996-2011, Drew Adams, all rights reserved.
8 ;; Created: Thu May 21 13:31:43 2009 (-0700)
10 ;; Last-Updated: Fri Sep 9 13:53:30 2011 (-0700)
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
18 ;; Features that might be required by this library:
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'.
30 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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).
40 ;; For commands to be used mainly in the minibuffer or buffer
41 ;; `*Completions*', see `icicles-mcmd.el'.
43 ;; For Icicles documentation, see `icicles-doc1.el' and
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.
51 ;; Macros defined here:
53 ;; `icicle-define-search-bookmark-command',
54 ;; `icicle-with-comments-hidden'.
56 ;; Commands defined here - (+) means a multi-command:
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'.
154 ;; Non-interactive functions defined here:
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'.
230 ;; Internal variables defined here:
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'.
243 ;; ***** NOTE: The following functions defined in `cus-edit.el' have
244 ;; been REDEFINED HERE:
246 ;; `customize-face', `customize-face-other-window' - Multi-commands.
249 ;; Key bindings made by Icicles: See "Key Bindings" in
250 ;; `icicles-doc2.el'.
252 ;; For descriptions of changes to this file, see `icicles-chg.el'.
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.
263 ;; (@> "Icicles Top-Level Commands, Part 2")
264 ;; (@> "Icicles Commands for Other Packages")
266 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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.
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.
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.
283 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
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
324 (or (condition-case nil
325 (load-library "icicles-mac") ; Use load-library to ensure latest .elc.
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
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'.
366 ;;; Some defvars to quiet byte-compiler a bit:
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'.
380 ;; (< emacs-major-version 21)
381 (defvar tooltip-mode) ; In `tooltip.el'
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)
397 (defvar yow-load-message)
399 ;; (> emacs-major-version 21)
400 (defvar Info-saved-nodes) ; In `info+.el'
402 ;; (< emacs-major-version 23)
403 (defvar read-buffer-completion-ignore-case)
405 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
407 ;;(@* "Icicles Top-Level Commands, Part 2")
408 ;;; Icicles Top-Level Commands, Part 2 . . . . . . . . .
411 (defvar icicle-orig-font nil
412 "Font of selected frame, before command.")
414 (defvar icicle-orig-frame nil
415 "Selected frame, before command.")
417 (defvar icicle-orig-menu-bar nil
418 "`menu-bar-lines' of selected frame, before command.")
420 (defvar icicle-orig-pixelsize nil
421 "Size of font of selected frame in pixels, before command.")
423 (defvar icicle-orig-pointsize nil
424 "Size of font of selected frame in points, before command.")
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
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.
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.
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)))))
472 (defvar icicle-named-colors ()
475 ;;;###autoload (autoload 'icicle-frame-bg "icicles-cmd2.el")
476 ;;;###autoload (autoload 'icicle-frame-fg "icicles-cmd2.el")
477 (eval-after-load "hexrgb"
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.
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: \").
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.
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
503 \(You can copy a color using eyedropper commands such as
504 `eyedrop-pick-foreground-at-mouse'.)
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''.
511 As always, you can toggle the use of proxy candidates using `\\<minibuffer-local-completion-map>\
512 \\[icicle-toggle-proxy-candidates]' in
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).
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'.
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.
524 In the plain `C-u' case, your input is checked to ensure that it
525 represents a valid color.
529 - You can complete your input against the color name, the RGB value,
532 - If you enter input without completing or cycling, the input is not
533 checked: whatever is entered is returned as the string value.
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.
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
546 During completion, candidate help (e.g. `C-M-RET') shows you the RGB
547 and HSV (hue, saturation, value) color components.
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)."
552 (unless (featurep 'hexrgb) (error "`icicle-read-color' requires library `hexrgb.el'"))
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.
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)
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'
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
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
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
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))
621 (icicle-maybe-byte-compile-after-load icicle-read-color)
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.
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
638 \(You can copy a color using eyedropper commands such as
639 `eyedrop-pick-foreground-at-mouse'.)
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''.
646 As always, you can toggle the use of proxy candidates using `\\<minibuffer-local-completion-map>\
647 \\[icicle-toggle-proxy-candidates]' in
650 You can complete your input against the color name, the RGB value, or
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
661 During completion, candidate help (e.g. `C-M-RET') shows you the RGB
662 and HSV (hue, saturation, value) color components.
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")))
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
687 (icicle-maybe-byte-compile-after-load icicle-frame-bg)
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")))
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
715 (icicle-maybe-byte-compile-after-load icicle-frame-fg)
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:
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)))
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 "^[*'].+[*']"
768 icicle-named-colors (mapcar #'icicle-make-color-candidate
769 (hexrgb-defined-colors))
770 icicle-proxy-candidates
771 (mapcar ; Convert multi-completions to strings.
773 ;; $$$$$$ (concat (mapconcat #'identity (car entry) icicle-list-join-string)
774 ;; icicle-list-end-string) ; $$$$$$
775 (mapconcat #'identity (car entry) icicle-list-join-string))
777 (and (fboundp 'eyedrop-foreground-at-point)
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)))))))
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))))
807 (icicle-maybe-byte-compile-after-load icicle-color-completion-setup)
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)
821 (princ "HSV:") (mapcar (lambda (component) (princ (format " %.18f" component))) hsv)))))
823 (icicle-maybe-byte-compile-after-load icicle-color-help)
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))
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))))
850 (icicle-maybe-byte-compile-after-load icicle-make-color-candidate)
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
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)))))
865 (icicle-maybe-byte-compile-after-load icicle-color-red-lessp)
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
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)))))
880 (icicle-maybe-byte-compile-after-load icicle-color-green-lessp)
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
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)))))
895 (icicle-maybe-byte-compile-after-load icicle-color-blue-lessp)
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).
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
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
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)))))
928 (icicle-maybe-byte-compile-after-load icicle-color-distance-rgb-lessp)
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
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)))))
943 (icicle-maybe-byte-compile-after-load icicle-color-hue-lessp)
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
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)))))
958 (icicle-maybe-byte-compile-after-load icicle-color-saturation-lessp)
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
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)))))
973 (icicle-maybe-byte-compile-after-load icicle-color-value-lessp)
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
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)))))))
997 (icicle-maybe-byte-compile-after-load icicle-color-hsv-lessp)
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).
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
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
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
1023 (elt (split-string s1 icicle-list-join-string) 1))))
1024 (s2-hsv (apply #'hexrgb-rgb-to-hsv
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)))))
1035 (defvar icicle-info-buff nil
1036 "Info buffer before command was invoked.")
1038 (defvar icicle-info-window nil
1039 "Info window before command was invoked.")
1042 (defun icicle-Info-index ()
1043 "Like vanilla `Info-index', but you can use multi-command keys `C-RET', `C-up' etc."
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))
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))))
1057 ;; Thx to Tamas Patrovics for this Emacs 20 version.
1059 (defun icicle-Info-index-20 ()
1060 "Like `Info-index', but you can use completion for the index topic."
1062 (let* ((symb (or (and (fboundp 'symbol-nearest-point) ; Defined in `thingatpt+.el'.
1063 (symbol-nearest-point))
1065 (topic (and symb (symbol-name symb))))
1067 (let ((pattern "\\* +\\([^:]*\\):.")
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)))))
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)))
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)
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
1100 (match-string-no-properties 1)))))
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)))
1110 (all-completions "" 'Info-complete-menu-item))))
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.
1121 With a prefix argument:
1123 * Plain `C-u' means prepend the current Info file name (manual name)
1124 to each node name. For example: `(emacs)Paragraphs' instead of
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.
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'.)
1137 In Lisp code, if optional argument ARG is a string, then show the node
1138 in a new Info buffer named `*info-ARG*'.
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.
1144 Input-candidate completion and cycling are available. While cycling,
1145 these keys with prefix `C-' are active:
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
1155 Use `mouse-2', `RET', or `S-RET' to finally choose a candidate, or
1158 This is an Icicles command - see command `icicle-mode'."
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))
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"))
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))))
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))
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
1194 (if (equal nodename "") (icicle-Info-read-node-name prompt) nodename))
1195 (define-key minibuffer-local-completion-map "\C-xm" C-x-m))))
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)))))))
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)))
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))
1222 (mapcar #'(lambda (node) (cons (concat file (car node)) (cdr node))) comps))
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 `..'.
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)
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)))
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.
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
1293 Non-interactively, argument NODESET is a list of Info node names."
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)
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)))
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))))
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'.
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
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'.)
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)))
1348 ((pref-arg current-prefix-arg) ; Bindings
1349 (icicle-must-pass-after-match-predicate
1351 #'(lambda (c) (commandp (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
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)))
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")))))
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'.)
1378 OPTION is a regexp that is matched against option names.
1380 Depending on the prefix arg, TYPE is interpreted as either of these:
1382 - a regexp to match against the option type
1384 - a definition acceptable for `defcustom' :type, or its first symbol,
1385 for example, (choice (integer) (regexp)) or `choice'
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.
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.
1395 In sum, the prefix arg determines the type-matching behavior, as
1398 - None: OPTION is defined with TYPE or a subtype of TYPE.
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.
1405 - Negative: OPTION is defined with TYPE (exact match).
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.
1412 - Zero: OPTION is defined with TYPE or a subtype of TYPE.
1413 TYPE is a type definition or its first symbol.
1415 - `C-u C-u': OPTION is defined with TYPE (exact match).
1416 TYPE is a type definition or its first symbol.
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.
1424 If TYPE is nil, then *all* options that match OPTION are candidates.
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.
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.
1434 For example, to match all Icicles options whose type matches `string'
1435 \(according to the prefix arg), use `S-TAB' with this input:
1440 If you instead want all Icicles options whose type definition contains
1441 `string', as in (repeat string), then use this:
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.)
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'
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...")))
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)))))
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))))
1503 (when (if (fboundp 'custom-variable-p) (custom-variable-p symb) (user-variable-p symb))
1505 (push (list symb (get symb 'custom-type)) result)
1507 ;; Keep only candidates that correspond to input.
1509 (let ((ops-re (if (memq icicle-current-completion-mode '(nil apropos))
1512 (icicle-remove-if-not
1514 (and (string-match ops-re (symbol-name (car opt+typ)))
1517 (icicle-var-is-of-type-p (car opt+typ) (list tp)
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)))
1525 ;; Change alist entries to multi-completions: "op^G^Jtp". Add short help for mode-line, tooltip.
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))
1544 result ; `all-completions', `test-completion'
1545 (try-completion strg (mapcar #'list result) pred)))) ; `try-completion'
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.
1556 For example, use input
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.
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.
1571 With a non-positive prefix arg, use only user variables (options) as
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)
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))))))
1593 (setq icicle-vardoc-last-initial-option-cand-set result)
1594 (setq icicle-vardoc-last-initial-cand-set 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))
1602 (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code
1603 (icicle-highlight-lighter)
1604 (message "Gathering variable descriptions...")))
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)))
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.
1619 For example, use input
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.
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.
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)).
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))
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))
1657 (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code
1658 (icicle-highlight-lighter)
1659 (message "Gathering function descriptions...")))
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)))
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.
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
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
1687 The time to repeat (positive prefix arg) is the same, whether or not
1688 candidates were pretty-printed the first time.
1690 Note: Plists are never pretty-printed for Emacs 20, because that seems
1691 to cause an Emacs crash.
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))
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)))
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.
1709 (pp-to-string plist))))
1712 (setq icicle-plist-last-initial-cand-set 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))
1720 (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code
1721 (icicle-highlight-lighter)
1722 (message "Gathering property lists...")))
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.
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
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.
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).
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)
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) "}"))
1771 (setq doc (concat doc "\n\n"))
1772 (push (cons (list (concat (symbol-name symb) icicle-list-join-string "VARIABLE") doc)
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)
1780 (setq icicle-doc-last-initial-cand-set 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))
1790 (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code
1791 (icicle-highlight-lighter)
1792 (message "Gathering documentation...")))
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)))
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."
1810 (let ((orig-syntable (syntax-table)))
1813 (set-syntax-table (standard-syntax-table))
1814 (and (stringp string) (> (length string) 0) (string-match "\\S-" string)))
1815 (set-syntax-table orig-syntable))))
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'."
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))
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."
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
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"))))
1868 (concat "Apropos variable (regexp" (and (>= emacs-major-version 22) " or words")
1870 obarray nil nil nil 'regexp-history)))
1871 (mapatoms #'(lambda (symb) (put symb 'icicle-special-candidate nil))))))
1872 (apropos-variable pattern))
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."
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)))
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."
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"))))
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))
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."
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))))
1931 ;; My versions are not available. Use the vanilla Emacs versions of the `apropos...' commands.
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.
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'."
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)
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
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
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))
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'.
1982 See `apropos-command' for a description of PATTERN.
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'.
1988 If VAR-PREDICATE is non-nil, show only variables, and only those that
1989 satisfy the predicate VAR-PREDICATE."
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
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
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))))
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*"
2041 (princ (car matches))
2042 (setq matches (cdr matches))
2043 (and matches (princ "\n\n")))))
2044 matches)) ; Return matching Zippyisms.
2047 (defalias 'icicle-map 'icicle-apply)
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.
2056 Argument FN is a function.
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
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).
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.
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.
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.
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'.
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.
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
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).
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:
2117 ((\"\\.el\\'\" . emacs-lisp-mode) (\"\\.elc'\" . emacs-lisp-mode))
2121 When candidate action and cycling are combined (e.g. `C-next'), option
2122 `icicle-act-before-cycle-flag' determines which occurs first.
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.
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
2131 `icicle-apply' overrides `icicle-ignore-space-prefix-flag', binding it
2132 to nil so that candidates with initial spaces can be matched."
2136 (let ((icicle-must-pass-after-match-predicate
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)))))
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))))))
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))
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))))
2180 (let ((result (funcall icicle-candidate-entry-fn icicle-explore-final-choice-full)))
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)))
2186 (defun icicle-apply-action (string)
2187 "Completion action function for `icicle-apply'."
2189 (icicle-condition-case-no-debug icicle-apply-action
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))))
2202 (defun icicle-apply-list-action (strings)
2203 "Completion action list function for `icicle-apply'."
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))))
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'."
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)))
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'."
2236 (if (wholenump (prefix-numeric-value arg))
2238 (icicle-goto-global-marker)))
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.
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
2249 During completion you can use these keys:
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
2260 When candidate action and cycling are combined (e.g. `C-next'), option
2261 `icicle-act-before-cycle-flag' determines which occurs first.
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.
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'."
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)))
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."
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)))
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."
2297 (let* ((global-ring-p
2298 (memq this-command '(icicle-goto-global-marker
2299 icicle-goto-global-marker-or-pop-global-mark)))
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
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))
2316 #'icicle-goto-marker-1-action
2319 (marker-buffer (cdr cand)))))
2320 ((= (point) (car markers)) (message "Already at marker: %d" (point)))
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))))
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)))
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)
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>"))
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))))))
2358 (defun icicle-markers (ring)
2359 "Marks in mark RING that are in live buffers other than a minibuffer."
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)))
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.
2374 * Plain `C-u': select (activate) one or more bookmarked regions.
2376 * Numeric prefix arg: bookmark (save) the active region using
2377 `icicle-bookmark-cmd'.
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
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'."
2390 (let ((bplus (featurep 'bookmark+)))
2392 (call-interactively #'exchange-point-and-mark)
2393 (unless bplus (error "You must load library `Bookmark+' to use a prefix 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)))
2399 (bookmark-maybe-load-default-file)
2400 (unless (consp (bmkp-region-alist-only)) (error "No bookmarked regions"))
2401 (call-interactively #'icicle-select-bookmarked-region))))))
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'."
2410 (call-interactively icicle-search-command))
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').
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.
2425 By default, candidates are in order of buffer occurrence, but you can
2426 sort them in various ways using `C-,'.
2428 You can replace individual matches with another string, as in
2429 `query-replace' or `query-replace-regexp'. See the Icicles Search doc
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.
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.
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.)
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.
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
2470 Optional Behaviors: Prefix Argument
2471 -----------------------------------
2473 By default, search only the current buffer. Search the active region,
2474 or, if there is none, then search the entire buffer.
2476 With a prefix argument, you can search multiple buffers, files, or
2477 bookmarks, as follows:
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'.)
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'.
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'.
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.
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
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.
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).
2528 In the search buffer (that is, where the hits are), `icicle-search'
2531 - Highlights the current match (buffer zone) for the initial (context)
2532 regexp, using face `icicle-search-main-regexp-current'.
2534 - Highlights the first `icicle-search-highlight-threshold' context
2535 matches, using face `icicle-search-main-regexp-others'.
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.
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-^'.
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.
2555 `*Completions*' Display
2556 -----------------------
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.
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.)
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).
2584 Unlike `query-replace', you need not visit search matches successively
2585 or exhaustively. You can visit and replace selected matches in any
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.
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.
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.
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
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).
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).
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.
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:
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.
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'...
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
2654 What your input matches, hence what gets replaced if
2655 `icicle-search-replace-whole-candidate-flag' is nil, depends on a few
2658 - `icicle-regexp-quote-flag' determines whether to use regexp
2659 matching or literal matching.
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
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
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]'.
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.
2698 Additional Information
2699 ----------------------
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.
2707 Completion is lax if `icicle-show-multi-completion-flag' is non-nil;
2708 otherwise, it is strict.
2710 After you visit a completion candidate, the hooks in variable
2711 `icicle-search-hook' are run.
2713 `icicle-search' overrides `icicle-ignore-space-prefix-flag', binding
2714 it to nil, so that candidates with initial spaces can be matched.
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.
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:
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.
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.
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)
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)
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))))
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)))))
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)))
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))))
2836 (message "Searching multiple files...") (sit-for 1)
2837 (let ((icicle-show-Completions-initially-flag t))
2838 (save-selected-window (icicle-file-list))))
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
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))))))
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)
2855 ;;; (regexp-quote (icicle-completing-read-history "Search for whole word: "
2856 ;;; 'icicle-search-history))
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
2871 (icicle-completing-read-history "Search for whole word: "
2872 'icicle-search-history))
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))
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)))
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)))
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))))
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.
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)
2925 (setq buf+beg (bookmark-jump-noselect bmk)
2928 end (bmkp-get-end-position bmk))
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)
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.
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)))
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.
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))
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)
2976 (icicle-condition-case-no-debug icicle-search-regexp-scan
2978 (goto-char (setq last-beg beg))
2979 (while (and beg (< beg end) (not (eobp))
2981 (while (and (setq beg (re-search-forward regexp end t))
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
2993 (match-beginning icicle-search-context-level)))
2994 (hit-end (if icicle-search-complement-domain-p
2996 (match-beginning icicle-search-context-level)
2998 (match-end icicle-search-context-level)))
2999 (IGNORE (when action
3002 (setq hit-end (point)))))
3003 (hit-string (buffer-substring-no-properties hit-beg hit-end))
3005 (when (and (not (string= "" hit-string)) ; Do nothing if empty hit.
3006 (setq end-marker (copy-marker hit-end))
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)))
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
3020 (let ((string (copy-sequence (buffer-name))))
3021 (put-text-property 0 (length string) 'face
3022 'icicle-candidate-part string)
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))))))))
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."
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))
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)))
3080 (while (and (not (eobp))
3082 (re-search-forward (or icicle-search-ecm input)
3085 (if (or (and (equal (match-beginning 0) (match-end 0)) (not (eobp)))
3086 (equal (point) pos))
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)))))))))))))))
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'
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.
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)))
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
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*'.
3149 Note: The replacement can be nearly anything allowed as a
3150 replacement by `query-replace-regexp', including Lisp-evaluation
3151 constructs (`\,...')."
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))))
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
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))
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
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.
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)
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)))
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))
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))
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))
3291 (icicle-search-replace-match replace-string
3292 (icicle-search-replace-fixed-case-p
3293 icicle-current-input)))))))
3295 ;; Update the alist and `minibuffer-completion-table' with the new text.
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.
3308 (icicle-search-replace-cand-in-mct cand+mrker (buffer-substring (point-min) (point-max)))
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.
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)
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))))
3334 (let ((icicle-candidate-nb icicle-candidate-nb)
3335 (icicle-minibuffer-message-ok-p nil)) ; Inhibit no-candidates message.
3336 (icicle-complete-again-update))
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.
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.
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)))
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.
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)))
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)
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)))
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))))
3416 (while (and (not (eobp)) (re-search-forward (or icicle-search-ecm icicle-current-input)
3418 (if (equal (match-beginning 0) (match-end 0))
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)))))))
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))))))
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
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))
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))
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))
3461 (old-cand (if (consp (car cand+mrker)) (caar cand+mrker) (car cand+mrker)))
3463 (setcar newlist (icicle-mctized-full-candidate (cons new-compl (cdr-safe cand+mrker))))
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))
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))
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))
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))))))
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.
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
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'.
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.)
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'
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))
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))))
3549 (defun icicle-group-regexp (regexp)
3550 "Wrap REGEXP between regexp parens, as a regexp group."
3551 (concat "\\(" regexp "\\)"))
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.
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.
3567 If you use library `Bookmark+' then:
3569 a. If a bookmark specifies a nonempty region, then search only the text
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 `>'),
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'.
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)
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)
3620 ("marked before unmarked (in *Bookmark List*)" (bmkp-marked-cp)
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)
3627 ("by last local file update" (bmkp-local-file-updated-more-recently-cp)
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)
3635 '(("by previous use alphabetically" . icicle-historical-alphabetic-p)
3636 ("case insensitive" . icicle-case-insensitive-string-less-p))))
3637 (icicle-candidate-help-fn
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
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))
3665 (tags (bmkp-get-tags bmk)))
3666 (cons `(,(icicle-candidate-short-help
3667 (icicle-bookmark-help-string bname)
3668 (icicle-bookmark-propertize-candidate bname))
3670 ,@(and tags (list (format "%S" tags))))
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))
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)))
3687 (setq bmkp-sorted-alist (bmkp-sort-omit bookmark-alist)))))))
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
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)
3721 (or (and (featurep 'bookmark+) (bmkp-region-bookmark-p bookmark-name)
3722 (bookmark-get-position bookmark-name))
3725 (or (and (featurep 'bookmark+) (bmkp-region-bookmark-p bookmark-name)
3726 (bmkp-get-end-position bookmark-name))
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)))
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.
3741 The command defined raises an error unless library `Bookmark+' can be
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)
3753 ((IGNORED1 (unless (require 'bookmark+ nil t) ; Bindings
3754 (error "You need library `Bookmark+' for this \
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)
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
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)
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)
3796 ("by last local file update" (bmkp-local-file-updated-more-recently-cp)
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)
3802 (and (get-buffer "*Bookmark List*")
3803 '(("marked before unmarked (in *Bookmark List*)" (bmkp-marked-cp)
3805 '(("by previous use alphabetically" . icicle-historical-alphabetic-p)
3806 ("case insensitive" . icicle-case-insensitive-string-less-p))))
3807 (icicle-candidate-help-fn
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
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))
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))
3833 (and tags (list (format "%S" tags))))
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))
3846 (bmkp-sort-omit (funcall ',(intern (format "bmkp-%s-alist-only" type)) ,@args)))))
3848 (icicle-bookmark-cleanup-on-quit) ; Undo code
3849 (icicle-bookmark-cleanup))) ; Last code
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'
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")
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).")
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.
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.
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.)
3915 You probably need nXML for this command. It is included in vanilla
3916 Emacs, starting with Emacs 23."
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
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))))))))
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.
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
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.)
3949 You probably need nXML for this command. It is included in vanilla
3950 Emacs, starting with Emacs 23."
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
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)))))
3968 (let* ((tag-end (string-match ,(format "\\`\\s-*<\\s-*%s\\s-*>" element)
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]\\)")
3980 (not (if (fboundp 'string-match-p)
3981 (string-match-p tag-regexp (car child))
3982 (string-match tag-regexp (car child))))
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.
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
3996 You can search the region, buffer, multiple buffers, or multiple
3997 files. See `icicle-search' for a full explanation.
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
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'.
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).
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
4024 This command is intended only for use in Icicle mode.
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))
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))
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)))
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',
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)))
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))))
4097 ;;; Same as `hide/show-comments' in `hide-comnt.el'.
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'
4106 Uses `save-excursion', restoring point.
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.
4112 From Lisp, a HIDE/SHOW value of `hide' hides comments. Other values
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)
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)))))
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.
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)
4156 (setq ,result (progn (when icicle-ignore-comments-flag
4157 (icicle-hide/show-comments 'hide ,ostart ,oend))
4159 (when icicle-ignore-comments-flag (icicle-hide/show-comments 'show ,ostart ,oend))
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.
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'.
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.
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.
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))
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
4200 (icicle-condition-case-no-debug icicle-search-thing-scan
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))
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
4217 (hit-end (if icicle-search-complement-domain-p
4220 (hit-string (buffer-substring hit-beg hit-end))
4221 (end-marker (copy-marker hit-end))
4222 (filteredp (or (not predicate)
4224 (funcall predicate thg+bnds)))
4225 (new-thg+bnds (if icicle-search-complement-domain-p
4230 (funcall transform-fn 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)))
4240 (when (and icicle-ignore-comments-flag icicle-search-complement-domain-p)
4241 (put-text-property 0 (length hit-string) 'invisible nil hit-string))
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)))
4250 (push (cons (if add-bufname-p
4252 (let ((string (copy-sequence (buffer-name))))
4255 'face 'icicle-candidate-part string)
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))))
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))
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)))))))))
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)
4294 (or (memq prop buffer-invisibility-spec) (assq prop buffer-invisibility-spec))))))
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))))
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.
4307 The \"visible\" in the name refers to ignoring things that are within
4308 invisible text, such as hidden comments.
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
4313 (save-excursion (icicle-next-visible-thing thing start end)))
4315 ;;; Simple version of `previous-visible-thing' from `thing-cmds.el'.
4317 (defun icicle-previous-visible-thing (thing start &optional end)
4318 "Same as `icicle-next-visible-thing', except it moves backward."
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)))))
4325 (if mark-active (min (region-beginning) (region-end)) (point-min))))
4327 (icicle-with-comments-hidden start end (icicle-next-visible-thing thing start end 'BACKWARD))
4328 (icicle-next-visible-thing thing start end 'BACKWARD)))
4330 ;;; Simple version of `next-visible-thing' from `thing-cmds.el'.
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.
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.
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.
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
4351 Non-interactively, THING is a symbol, and optional arg BACKWARD means
4352 go to the previous thing.
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."
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)))))
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))))))
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)))
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)))
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))))
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)))
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))
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))
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.
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))))
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))))
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.
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.
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.
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
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
4451 (interactive (icicle-search-property-args))
4452 (icicle-search beg end 'icicle-search-char-property-scan require-match where prop values nil
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
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
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)))
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)
4511 (setq buf+beg (bookmark-jump-noselect bmk)
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))))
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)))
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)
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))
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.
4541 (setq beg (or (next-property-change beg nil end) end)
4542 curr-props (text-properties-at beg))
4544 (unless (memq (car curr-props) props) (push (car curr-props) props))
4545 (setq curr-props (cddr curr-props)))))))
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.
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
4560 TYPE is `overlay', `text', or nil, and specifies the type of character
4561 property - nil means look for both overlay and text properties.
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))
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)
4576 (icicle-condition-case-no-debug icicle-search-char-property-scan
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
4592 (hit-end (if icicle-search-complement-domain-p
4595 (hit-string (buffer-substring-no-properties hit-beg hit-end))
4597 (when (and (not (string= "" hit-string)) ; Do nothing if empty hit.
4598 (setq end-marker (copy-marker hit-end))
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)))
4607 (push (cons (if add-bufname-p
4609 (let ((string (copy-sequence (buffer-name))))
4610 (put-text-property 0 (length string)
4611 'face 'icicle-candidate-part string)
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)))))
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))))))))
4638 (defun icicle-flat-list (val1 val2)
4639 "Return a flat list with all values in VAL1 and VAL2."
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)))
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.
4655 POSITION is a buffer position (integer or marker).
4657 Optional third arg OBJECT is ignored. It is present for compatibility
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.
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."
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)))))
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.
4683 POSITION is a buffer position (integer or marker).
4685 Optional third arg OBJECT is ignored. It is present for compatibility
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.
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."
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)))))
4704 (defun icicle-search-highlight-cleanup ()
4705 "Remove all highlighting from the last use of `icicle-search'."
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")))
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.
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.
4739 Non-interactively, WORD-REGEXP should be a regexp that matches a word.
4740 The other arguments are the same as for `icicle-search'.
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
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
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))
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.
4765 This is the same as using a plain prefix arg, `C-u', with
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
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.)
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))
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.
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))))
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.
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))
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))
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))
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)))
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 ()))
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)))
4897 (defalias 'icicle-search-lines 'icicle-occur)
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.
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.
4912 You can use `M-*' to further narrow the match candidates, typing
4913 additional regexps to match.
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
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)))
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))))
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
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.
4948 You can use `M-*' to further narrow the match candidates, typing
4949 additional regexps to match.
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
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
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)))
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))))
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
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.
4991 You can use `M-*' to further narrow the match candidates, typing
4992 additional regexps to match.
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
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)))
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))))
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.
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.
5027 You can use `M-*' to further narrow the match candidates, typing
5028 additional regexps to match.
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
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)))
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))))
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.
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.)
5065 As for other Icicles search commands, your current input narrows the
5066 set of possible candidates. See `icicle-search' for more
5069 You can use `M-*' to further narrow the match candidates, typing
5070 additional regexps to match.
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.
5078 Also, depending on your shell, you might want to customize variables
5079 such as the following:
5081 `shell-prompt-pattern',`telnet-prompt-pattern'.
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.
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
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)
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)))
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))
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)))
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)
5129 (substring icicle-explore-final-choice input-start)
5130 icicle-explore-final-choice)))
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
5138 Note, depending on your shell, you might want to customize variables
5139 such as the following:
5141 `shell-prompt-pattern',`telnet-prompt-pattern'.
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
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))
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.
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.
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.
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.
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
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
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)))
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))))
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))
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)))
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))
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.
5231 For Emacs 22 and later, if option `isearch-allow-scroll' is non-nil
5232 then a prefix argument changes the behavior, as follows:
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
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."
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))))
5248 (defalias 'icicle-search-defs 'icicle-imenu)
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
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
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.
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
5279 See also these type-specific Icicles Imenu multi-commands:
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
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.
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'
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
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))
5311 (defalias 'icicle-search-defs-full 'icicle-imenu-full)
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.
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))
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'.
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
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
5350 (or (car (assoc "Functions" menus)) (car (assoc "Other" menus))
5351 (error "No command definitions in buffer")))))
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
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
5374 (or (car (assoc "Functions" menus)) (car (assoc "Other" menus))
5375 (error "No command definitions in buffer")))))
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))))))
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'.
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
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
5405 (or (car (assoc "Functions" menus)) (car (assoc "Other" menus))
5406 (error "No non-command function definitions in buffer")))))
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.
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
5429 (or (car (assoc "Functions" menus)) (car (assoc "Other" menus))
5430 (error "No non-command function definitions in buffer")))))
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))
5437 (buffer-substring-no-properties (match-beginning indx) (match-end indx)))))
5438 (and (fboundp fn) (not (commandp fn)))))
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
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
5455 (or (car (assoc "Macros" menus)) (car (assoc "Other" menus))
5456 (error "No macro definitions in buffer")))))
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.
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
5479 (or (car (assoc "Macro" menus)) (car (assoc "Other" menus))
5480 (error "No macro definitions in buffer")))))
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
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
5497 (or (car (assoc "Variables" menus)) (car (assoc "Other" menus))
5498 (error "No non-option variable definitions in buffer")))))
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.
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
5520 (or (car (assoc "Variables" menus)) (car (assoc "Other" menus))
5521 (error "No non-option variable definitions in buffer")))))
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
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
5538 (or (car (assoc "User Options" menus)) (car (assoc "Other" menus))
5539 (error "No user option definitions in buffer")))))
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
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
5561 (or (car (assoc "User Options" menus)) (car (assoc "Other" menus))
5562 (error "No user option definitions in buffer")))))
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'.
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
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
5582 (or (car (assoc "Keys" menus)) (car (assoc "Other" menus))
5583 (error "No implicit-map key definitions in buffer")))))
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
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
5599 (or (car (assoc "Keys" menus)) (car (assoc "Other" menus))
5600 (error "No implicit-map key definitions in buffer")))))
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
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
5617 (or (car (assoc "Keys in Maps" menus)) (car (assoc "Other" menus))
5618 (error "No explicit-map key definitions in buffer")))))
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
5634 (or (car (assoc "Keys in Maps" menus)) (car (assoc "Other" menus))
5635 (error "No explicit-map key definitions in buffer")))))
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
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
5652 (or (car (assoc "Faces" menus)) (car (assoc "Other" menus))
5653 (error "No face definitions in buffer")))))
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
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
5669 (or (car (assoc "Faces" menus)) (car (assoc "Other" menus))
5670 (error "No face definitions in buffer")))))
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
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.
5694 (set-syntax-table table)
5696 (menus (mapcar #'(lambda (menu)
5697 (when (equal (car menu) "Other")
5698 (setq others (1+ others))
5700 (setcar menu (format "Other<%d>" others))))
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))
5707 (cons "Other" (cdr menu))))
5708 imenu-generic-expression))))
5709 (submenu (if submenu-fn
5710 (funcall submenu-fn 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"))
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
5728 (error (goto-char (match-end 0))))))))) ; Punt: just use regexp match.
5729 (set-syntax-table old-table))))
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)))
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.
5741 All tags in a tags file are used, including duplicate tags from the
5742 same or different source files.
5744 By default, all tags files are used, but if you provide a prefix
5745 argument then only the current tag table is used.
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
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.)"
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
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)))
5769 (let ((first-time 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)))
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 ()))
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)))
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.
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.
5804 You can use `\\<minibuffer-local-completion-map>\
5805 \\[icicle-insert-string-from-variable]' to insert a string from a
5808 (let* ((enable-recursive-minibuffers t)
5809 (icicle-must-pass-after-match-predicate #'(lambda (s) (boundp (intern s))))
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))))
5828 (when (> emacs-major-version 21)
5830 (when (and icicle-define-alias-commands-flag (not (fboundp 'any)))
5831 (defalias 'any 'icicle-anything))
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'.
5839 This command is available only if you use library `anything.el'.
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.
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.
5852 This command is intended for use only in Icicle mode."
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)))
5860 (icicle-object-action type)))
5862 (when (and icicle-define-alias-commands-flag (not (fboundp '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'.
5868 This is just `icicle-object-action' with type `file'."
5869 (interactive) (icicle-object-action 'file)))
5871 (when (and icicle-define-alias-commands-flag (not (fboundp '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'.
5877 This is just `icicle-object-action' with type `buffer'."
5878 (interactive) (icicle-object-action 'buffer)))
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))
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.
5892 The \"type\" of an object is one of these:
5894 a. A type defining an entry `icicle-predicate-types-alist'.
5895 These are type predicates, such as `bufferp', `keywordp', or `atom'.
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.
5901 c. A type defining an entry in user option
5902 `icicle-type-actions-alist'.
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
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.
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.
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.
5925 Anything types and Anything actions are highlighted when used as
5926 candidates in `*Completions*', using face `icicle-special-candidate'.
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
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
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.
5943 This command is intended for use only in Icicle mode."
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)))
5951 (let ((icicle-show-Completions-initially-flag t))
5953 (completing-read "What (type): "
5954 (icicle-remove-duplicates (append (mapcar #'list anything-types)
5955 icicle-type-actions-alist
5956 icicle-predicate-types-alist))
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))
5982 icicle-saved-completion-candidate)))
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)
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))))
5995 (mapcar #'(lambda (typ)
5996 (setq typ (copy-sequence typ))
5997 (put-text-property 0 (length typ) 'face 'icicle-special-candidate typ)
5999 (icicle-remove-duplicates types)))))))
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 ())
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))
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))
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))
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))
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)))
6045 (icicle-remove-if-not
6047 (string-match (if (eq 'prefix icicle-current-completion-mode)
6048 (concat "^" (regexp-quote string))
6052 (cond ((eq mode t) all-cands)
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))
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))
6065 (anything-transform-candidates candidates source)))))
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
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)
6104 icicle-candidates-alist))
6105 (icicle-candidate-action-fn
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
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))
6138 (orig-action-fn icicle-candidate-action-fn)
6139 (icicle-candidate-help-fn
6140 (if icicle-whole-candidate-as-text-prop-p
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
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)))))
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))))
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))))
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)))
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))))))))
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
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.
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)))
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"))))
6258 (completing-read "Which (buffer): " (mapcar #'(lambda (buf) (list (buffer-name buf)))
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)))
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))
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"))))
6327 "Which (process): " (mapcar #'(lambda (proc) (list (process-name proc)))
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")))
6351 (walk-windows #'(lambda (win)
6352 (push (list (format "%s" (window-buffer win))) buffers))
6354 (get-buffer-window (completing-read "Window showing buffer: " buffers) 0)))
6355 (otherwise (error "Bad object type: %S" type)))))
6357 (defun icicle-read-var-value-satisfying (pred)
6358 "Read a variable that satisfies predicate PRED and returns its value."
6360 (let ((icicle-orig-window (selected-window))
6361 (icicle-must-pass-after-match-predicate `(lambda (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)))))
6371 (defvar icicle-key-prefix nil
6374 (defvar icicle-key-prefix-2 nil
6377 (defvar icicle-active-map nil
6378 "An active keymap.")
6380 (defvar icicle-orig-buff-key-complete nil
6381 "Current buffer when you invoked `icicle-complete-keys'.")
6383 (defvar icicle-orig-extra-cands ()
6384 "Value of `icicle-extra-candidates', before command.")
6386 (defvar icicle-orig-show-initially-flag nil
6387 "Value of `icicle-show-Completions-initially-flag', before command.")
6389 (defvar icicle-orig-sort-orders-alist ()
6390 "Value of `icicle-sort-orders-alist', before command.")
6392 (defvar icicle-orig-win-key-complete nil
6393 "Selected window when you invoked `icicle-complete-keys'.")
6395 (defvar icicle-this-cmd-keys ()
6396 "Value of `this-command-keys-vector' at some point in key completion.")
6398 (when (fboundp 'map-keymap) ; Emacs 22+.
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.
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
6409 Completion candidates generally have the form `KEY = COMMAND'.
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
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'.
6421 Except at the top level, the default value for completion is `..'.
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
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
6433 For Emacs 22, the option is effectively Boolean: any non-nil value
6434 means allow all self-inserting keys as candidates.
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
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*'.
6450 While cycling, these keys describe candidates:
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
6463 When candidate action and cycling are combined (e.g. `C-next'), option
6464 `icicle-act-before-cycle-flag' determines which occurs first.
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.
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
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)
6489 (icicle-hist-cands-no-highlight '("..")))
6490 (icicle-complete-keys-1 (icicle-this-command-keys-prefix))))
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)))))
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))
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))
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 "\\.\\.")
6519 (dolist (cand icicle-complete-keys-alist)
6520 (put (car cand) 'icicle-special-candidate nil))))) ; Reset the property.
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))
6532 (action-window (selected-window)))
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))
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)))
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))))
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))
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'."
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.
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.
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))
6608 (setq binding (car-safe (cdr-safe (cdr-safe binding))))
6609 (setq binding nil))))
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))
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)))))
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)))
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))
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
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
6653 (not icicle-key-descriptions-use-<>-flag))
6654 'face 'icicle-candidate-part))
6655 (candidate (intern (concat key-desc " = " (if (keymapp binding)
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.
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))))
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.
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.
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.
6709 Optional argument NO-ANGLES non-nil means to expect key
6710 descriptions not to use angle brackets (<...>). For example:
6712 (icicle-read-kbd-macro \"<mode-line>\" t) returns [mode-line]
6713 (icicle-read-kbd-macro \"mode-line\" t t) returns [mode-line]"
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))))
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)
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)))
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)
6739 (or (car (where-is-internal
6740 'execute-extended-command))
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]-\\)*\\)<\\(..+\\)>$")
6750 (save-match-data (not (string-match "^\\([ACHMsS]-.\\)+$" word))))
6752 (setq word (concat (substring word (match-beginning 1)
6754 (substring word (match-beginning 3)
6757 "\\<\\(NUL\\|RET\\|LFD\\|ESC\\|SPC\\|DEL\\)$"
6759 (setq key (list (intern word))))
6761 (let ((orig-word word)
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-\^@)))))
6770 (callf substring word 2))
6771 (when (string-match "^\\^.$" word)
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))))
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)))))
6799 (setq key (list (+ bits (aref word 0)))))))))
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)
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.
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.
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.
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.
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.
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:
6847 `icicle-incremental-completion-delay'
6848 `icicle-top-level-when-sole-completion-delay'
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.:
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
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))))))
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))
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))
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))))
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))
6905 (setq cmeths (if (consp (car 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))))
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)
6926 (ad-remove-advice command 'around var)
6928 (ad-activate command) ; This restores original definition unless otherwise advised.
6929 (when msgp (message "`%s' now uses default %s" command type)))
6931 (ad-add-advice command `(,var
6933 (advice . (lambda () (let ((,var ',methods)) ad-do-it))))
6935 (ad-activate command)
6936 (when msgp (message "`%s' %s: %s" command type
6937 (if (consp (car methods)) (mapcar #'car methods) methods)))))))
6939 ;;(@* "Icicles Commands for Other Packages")
6940 ;;; ** Icicles Commands for Other Packages **
6942 ;;; Library `highlight.el' - Icicles multi-commands. Emacs 21+.
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.
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
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
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): "))
6973 (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code.
6975 (prog1 (setq face-names (delete "" face-names)) ; Return the list of faces.
6976 (when (interactive-p) (message "Faces: %S" face-names))))
6978 (icicle-maybe-byte-compile-after-load icicle-choose-faces)
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
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
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): "))
7001 (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code.
7003 (prog1 (setq face-names (delete "" face-names)) ; Return the list of faces.
7004 (when (interactive-p) (message "Faces: %S" face-names))))
7006 (icicle-maybe-byte-compile-after-load icicle-choose-invisible-faces)
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
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
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): "))
7029 (put-text-property 0 1 'icicle-fancy-candidates t prompt) ; First code.
7031 (prog1 (setq face-names (delete "" face-names)) ; Return the list of faces.
7032 (when (interactive-p) (message "Faces: %S" face-names))))
7034 (icicle-maybe-byte-compile-after-load icicle-choose-visible-faces)
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.
7042 When choosing faces, completion and cycling are available. During
7043 cycling, these keys with prefix `C-' act on the current face name:
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
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))))
7060 (icicle-maybe-byte-compile-after-load icicle-show-only-faces)
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.
7068 When choosing faces, completion and cycling are available. During
7069 cycling, these keys with prefix `C-' act on the current face name:
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
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))))
7086 (icicle-maybe-byte-compile-after-load icicle-hide-only-faces)
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
7095 When choosing faces, completion and cycling are available. During
7096 cycling, these keys with prefix `C-' act on the current face name:
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"
7105 (list (let ((fs (icicle-remove-if-not #'icicle-invisible-face-p
7106 (if hlt-act-on-any-face-flag
7108 (hlt-highlight-faces-in-buffer
7109 (point-min) (point-max))))))
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)))
7116 (icicle-maybe-byte-compile-after-load icicle-show-faces)
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
7125 When choosing faces, completion and cycling are available. During
7126 cycling, these keys with prefix `C-' act on the current face name:
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)))
7138 (icicle-maybe-byte-compile-after-load icicle-hide-faces)
7143 ;;; Library `palette.el' - Icicles multi-commands.
7145 ;;;###autoload (autoload 'icicle-pick-color-by-name "icicles-cmd2.el")
7146 (eval-after-load "palette"
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
7161 (icicle-maybe-byte-compile-after-load icicle-pick-color-by-name)
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)
7184 palette-current-color))
7186 (icicle-maybe-byte-compile-after-load icicle-pick-color-by-name-action)
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"))
7196 ;;; Library `synonyms.el' - Icicles multi-commands.
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"
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.
7212 Option `synonyms-match-more-flag' non-nil means additional thesaurus
7213 entries can be matched. This can be more time-consuming. It means
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.
7219 Option `synonyms-append-result-flag' non-nil means to append search
7220 result to previous results.
7222 A prefix argument toggles the meaning of each of those options for the
7223 duration of the command:
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'.
7228 \(`C-u C-u' thus means toggle both options.)
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.
7241 (icicle-maybe-byte-compile-after-load icicle-synonyms)
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
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
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))
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)))
7268 (icicle-maybe-byte-compile-after-load icicle-insert-thesaurus-entry)
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
7276 (set-buffer icicle-orig-buff)
7277 (goto-char icicle-track-pt)
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)))
7284 (icicle-maybe-byte-compile-after-load icicle-insert-thesaurus-entry-cand-fn)
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
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 " ")))
7306 (icicle-maybe-byte-compile-after-load icicle-complete-thesaurus-entry)
7310 ;;; Library `Bookmark+' - Icicles multi-commands.
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+"
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.
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
7351 (icicle-unbind-file-candidate-keys)) ; Last code
7353 (icicle-maybe-byte-compile-after-load icicle-bookmark-a-file)
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.
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.
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))))
7376 (icicle-maybe-byte-compile-after-load icicle-tag-a-file)
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.
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.
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."
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
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)))
7410 (icicle-maybe-byte-compile-after-load icicle-untag-a-file)
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.)
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.
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).
7429 You can match your input against the file name or tags or both.
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)
7437 That assumes that these tags do not also match any file names.
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.
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:
7447 `2011 C-M-j red M-SPC blue' to match all files tagged `red' and
7448 `blue' that have `2011' in their names
7450 During completion (`*': requires library `Bookmark+'):
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)
7467 (bmkp-get-autofile-bookmark file))))))
7468 (icicle-abs-file-candidates ; An alist whose items are ((FILE TAG...)).
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))))
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)))
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))
7485 (icicle-unbind-file-candidate-keys)) ; Last code
7487 (icicle-maybe-byte-compile-after-load icicle-find-file-tagged)
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)
7500 (bmkp-get-autofile-bookmark file))))))
7501 (icicle-abs-file-candidates ; An alist whose items are ((FILE TAG...)).
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))))
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)))
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))
7518 (icicle-unbind-file-candidate-keys)) ; Last code
7520 (icicle-maybe-byte-compile-after-load icicle-find-file-tagged-other-window)
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').
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.
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))
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))))))))
7556 (icicle-maybe-byte-compile-after-load icicle-find-file-all-tags)
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))
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))))))))
7580 (icicle-maybe-byte-compile-after-load icicle-find-file-all-tags-other-window)
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))
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
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)))
7608 (icicle-maybe-byte-compile-after-load icicle-find-file-all-tags-regexp)
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))
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
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)))
7634 (icicle-maybe-byte-compile-after-load icicle-find-file-all-tags-regexp-other-window)
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.
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))
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))))))))
7666 (icicle-maybe-byte-compile-after-load icicle-find-file-some-tags)
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))
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))))))))
7690 (icicle-maybe-byte-compile-after-load icicle-find-file-some-tags-other-window)
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))
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
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)))
7718 (icicle-maybe-byte-compile-after-load icicle-find-file-some-tags-regexp)
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))
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
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)))
7744 (icicle-maybe-byte-compile-after-load icicle-find-file-some-tags-regexp-other-window)
7748 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7750 (provide 'icicles-cmd2)
7752 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7753 ;;; icicles-cmd2.el ends here