Mercurial > hg > xemacs-beta
comparison lisp/dired/gmhist.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 ;;;; gmhist.el - Provide generic minibuffer history for commands | |
2 | |
3 (defconst gmhist-version (substring "!Revision: 4.27 !" 11 -2) | |
4 "Id: gmhist.el,v 4.27 1992/04/20 17:17:47 sk RelBeta | |
5 Report bugs to Sebastian Kremer <sk@thp.uni-koeln.de>.") | |
6 | |
7 ;; Copyright (C) 1990 by Sebastian Kremer <sk@thp.uni-koeln.de> | |
8 | |
9 ;; This program is free software; you can redistribute it and/or modify | |
10 ;; it under the terms of the GNU General Public License as published by | |
11 ;; the Free Software Foundation; either version 1, or (at your option) | |
12 ;; any later version. | |
13 ;; | |
14 ;; This program is distributed in the hope that it will be useful, | |
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 ;; GNU General Public License for more details. | |
18 ;; | |
19 ;; You should have received a copy of the GNU General Public License | |
20 ;; along with this program; if not, write to the Free Software | |
21 ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
22 | |
23 ;; LISPDIR ENTRY for the Elisp Archive =============================== | |
24 ;; LCD Archive Entry: | |
25 ;; gmhist|Sebastian Kremer|sk@thp.uni-koeln.de | |
26 ;; |Generic minibuffer history package. | |
27 ;; |Date: 1992/04/20 17:17:47 |Revision: 4.27 | | |
28 | |
29 ;; INSTALLATION ====================================================== | |
30 ;; | |
31 ;; Put this file into your load-path and the following in your | |
32 ;; ~/.emacs: | |
33 ;; | |
34 ;; (autoload 'read-with-history-in "gmhist") | |
35 ;; (autoload 'read-file-name-with-history-in "gmhist") | |
36 ;; (autoload 'completing-read-with-history-in "gmhist") | |
37 ;; (autoload 'gmhist-make-magic "gmhist" nil t) | |
38 | |
39 ;; USAGE ============================================================= | |
40 ;; | |
41 ;; - as an Elisp programmer: use functions read-with-history-in, | |
42 ;; completing-read-with-history-in, read-file-name-with-history-in or | |
43 ;; gmhist-interactive inside the interactive clause of your functions | |
44 ;; instead of a string specification. See the examples at the end of | |
45 ;; the file. | |
46 ;; | |
47 ;; - as an Emacs user: To provide `simple' functions with history, | |
48 ;; just type M-x gmhist-make-magic and enter the name of the | |
49 ;; function, e.g., `eval-expression'. This function's arguments | |
50 ;; are then remembered across calls and are available by typing | |
51 ;; M-p to the minibuffer prompt of the function. More history | |
52 ;; commands are mentioned in the documentation of variable | |
53 ;; gmhist-map. | |
54 ;; | |
55 ;; Type M-x gmhist-remove-magic to restore the function's old | |
56 ;; interactive behaviour. | |
57 ;; | |
58 ;; `Simple' functions are those that prompt for strings, file | |
59 ;; names or lisp objects and perhaps use prefix args and the | |
60 ;; region. See the file gmhist-app.el for examples with simple | |
61 ;; and other functions. | |
62 | |
63 ;; I'd like to thank Jamie Zawinski, Piet van Oostrum and Mike | |
64 ;; Williams for very helpful feedback and ideas. | |
65 | |
66 | |
67 (provide 'gmhist) | |
68 | |
69 ;; Emacs 19 has s-expr interactive's on some functions (sometimes to | |
70 ;; emulate functionality gmhist would give). So we sometimes have to | |
71 ;; test this to avoid letting gmhist-make-magic bombing on non-string | |
72 ;; interactive specifications: | |
73 ;; XEmacs fix: | |
74 (defvar gmhist-emacs-19-p (not (equal (substring emacs-version 0 2) "18"))) | |
75 | |
76 (defvar gmhist-default-format "[%s] " ; saves screen space, too | |
77 "Format used by gmhist to indicate the presence of a default value. | |
78 Set this to \"(default %s) \" to get the standard format.") | |
79 | |
80 (defvar gmhist-search-history nil "History of history searches.") | |
81 | |
82 (defun read-with-history-in (GMHIST-SYMBOL rwhi-prompt &optional | |
83 GMHIST-INITIAL GMHIST-READ) | |
84 ;; We have to be careful about dynamical scoping here so as not to | |
85 ;; shadow other lisp code that depends on fluid vars like `prompt | |
86 ;; (notorious in minibuffer code, e.g. electric-replace). | |
87 ;; That's why our own fluid vars have upper-case names starting with | |
88 ;; GMHIST- and why `rwhi-prompt' instead of `prompt' is used as | |
89 ;; formal argument. Similar below. | |
90 "\ | |
91 Read a string, maintaining minibuffer history across calls in GMHIST-SYMBOL, | |
92 prompting with PROMPT, with optional GMHIST-INITIAL as initial contents. | |
93 If optional fourth arg GMHIST-READ is non-nil, then interpret the | |
94 result as a lisp object and return that object. | |
95 See variable gmhist-map for history commands available during edit. | |
96 Example: | |
97 (defun foo-command (cmd) | |
98 (interactive (list (read-with-history-in 'foo-history \"Foo: \" ))) | |
99 (message \"Fooing %s...\" cmd)) | |
100 | |
101 See function gmhist-make-magic on how to give an existing function | |
102 history. | |
103 | |
104 These properties (see function put) of GMHIST-SYMBOL are supported: | |
105 | |
106 cursor-end Put cursor at end of a newly retrieved history line. | |
107 cursor-pos A regexp to put the cursor on. | |
108 keep-dups If t, duplicate commands are remembered, too. | |
109 initial-hist Initial value of the history list. | |
110 hist-ignore Regexp of commands that are not to be added to the history. | |
111 backup If t, backup in the history list (as if user had typed | |
112 M-p as first thing). Can also be an integer to backup | |
113 more than one history item. | |
114 default An empty string as input will default to the last | |
115 command (whether the last command was added to the | |
116 history or not). The default is stored in this | |
117 property, thus its initial value is the first default. | |
118 dangerous Commands matching this regexp will never be the default. | |
119 no-default If you don't want defaults at all, set this to t. | |
120 | |
121 Use the following only if you know what you are doing: | |
122 | |
123 hist-function Name of a function to call instead of doing normal | |
124 history processing. read-with-history-in becomes | |
125 effectively an alias for this function. | |
126 | |
127 These will be flushed soon (use let-binding minibuffer-completion-table | |
128 etc. instead): | |
129 | |
130 hist-map Minibuffer key map to use instead of gmhist-map. | |
131 completion-table | |
132 completion-predicate | |
133 Used in completion on history strings, when the hist-map | |
134 property has gmhist-completion-map as value. | |
135 The special value `t' for the table means to use the | |
136 current history list. | |
137 Thus, to get completion on history items just do: | |
138 (put 'foo-history 'hist-map gmhist-completion-map) | |
139 (put 'foo-history 'completion-table t) | |
140 | |
141 Hooks: | |
142 gmhist-after-insert-hook is run after a history item is | |
143 inserted into the minibuffer. | |
144 gmhist-load-hook is run after this package is loaded. | |
145 gmhist-hook is run as first thing inside read-with-history-in. | |
146 gmhist-before-move-hook is run before history motion takes place. | |
147 Function gmhist-remember-zero is a candidate for that hook. | |
148 " | |
149 ;; We don't use property names prefixed with 'ghmist-' because the | |
150 ;; caller has freedom to use anything for GMHIST-SYMBOL. | |
151 ;; The history list is never truncated, but I don't think this will | |
152 ;; cause problems. All histories together have at most a few k. | |
153 ;; On the other hand, some people run an Emacs session for weeks. | |
154 ;; Could use gmhist-hook to truncate the current history list. | |
155 ;; You can use 'initial-hist to save (part of) the history in a file | |
156 ;; and provide it at next startup. [Is there an exit-emacs-hook?] | |
157 ;; You can use 'hist-function to implement a completely different | |
158 ;; history mechanism, e.g., a ring instead of a list, without having | |
159 ;; to modify existing gmhist applications. | |
160 (run-hooks 'gmhist-hook) | |
161 (let ((hist-function (get GMHIST-SYMBOL 'hist-function))) | |
162 (if (fboundp hist-function) ; hist-function must be a symbol | |
163 (funcall hist-function ; not lambda | |
164 GMHIST-SYMBOL rwhi-prompt GMHIST-INITIAL GMHIST-READ) | |
165 (or (boundp GMHIST-SYMBOL) ; history list defaults to nil | |
166 (set GMHIST-SYMBOL (get GMHIST-SYMBOL 'initial-hist))) | |
167 ;; else do the usual history processing simply using lists: | |
168 (let* ((history (symbol-value GMHIST-SYMBOL)) | |
169 (minibuffer-completion-table (let ((table | |
170 (get GMHIST-SYMBOL | |
171 'completion-table))) | |
172 (if (eq t table) | |
173 (mapcar (function list) | |
174 history) | |
175 table))) | |
176 (minibuffer-completion-predicate (get GMHIST-SYMBOL | |
177 'completion-predicate)) | |
178 (minibuffer-history-symbol GMHIST-SYMBOL)) | |
179 (gmhist-new-read-from-minibuffer rwhi-prompt | |
180 GMHIST-INITIAL | |
181 (or (get GMHIST-SYMBOL 'hist-map) | |
182 gmhist-map) | |
183 GMHIST-READ))))) | |
184 | |
185 (defun completing-read-with-history-in (crwhi-hist-sym &rest args) | |
186 "Like completing-read, but with additional first arg HISTORY-SYMBOL." | |
187 (let ((minibuffer-history-symbol crwhi-hist-sym)) | |
188 (apply 'gmhist-completing-read args))) | |
189 | |
190 (defun gmhist-completing-read (crwhi-prompt table | |
191 &optional predicate | |
192 mustmatch initial) | |
193 "Like completing-read, but see minibuffer-history-symbol." | |
194 (let ((minibuffer-completion-confirm (if (eq mustmatch t) nil t)) | |
195 (minibuffer-completion-table table) | |
196 (minibuffer-completion-predicate predicate)) | |
197 (gmhist-new-read-from-minibuffer crwhi-prompt | |
198 initial | |
199 (gmhist-lookup-keymap | |
200 (if mustmatch | |
201 gmhist-must-match-map | |
202 gmhist-completion-map))))) | |
203 | |
204 | |
205 (defun read-file-name-with-history-in (crwhi-hist-sym &rest args) | |
206 "Like read-file-name, but with additional first arg HISTORY-SYMBOL." | |
207 (let ((file-history-symbol crwhi-hist-sym)) | |
208 (apply 'gmhist-read-file-name args))) | |
209 | |
210 (defvar file-history-symbol 'file-history | |
211 "*If non-nil, it is the name (a symbol) of a variable on which to cons | |
212 filenames entered in the minibuffer. | |
213 You may let-bind this to another symbol around calls to read-file-name.") | |
214 | |
215 (defun gmhist-read-file-name | |
216 (grfn-prompt &optional dir default mustmatch initial) | |
217 "Args: PROMPT &optional DIR DEFAULT MUSTMATCH INITIAL. | |
218 Read file name, maintaining history in file-history-symbol, prompting | |
219 with PROMPT, with optional INITIAL input and completing in directory DIR. | |
220 Value is not expanded! You must call expand-file-name yourself. | |
221 Default name to arg DEFAULT if user enters a null string (or, if | |
222 INITIAL was given, leaves it unchanged). | |
223 MUSTMATCH non-nil means require existing file's name. | |
224 Non-nil and non-t means also require confirmation after completion. | |
225 DIR defaults to current buffer's default-directory. | |
226 | |
227 This function differs from read-file-name in providing a history of | |
228 filenames bound to file-history-symbol and (for pre-Emacs 19) in | |
229 providing an argument INITIAL not present in Emacs 18's read-file-name." | |
230 (setq dir (or dir default-directory) | |
231 default (or default buffer-file-name)) | |
232 (if file-history-symbol | |
233 (progn (put file-history-symbol 'cursor-end t) | |
234 (put file-history-symbol 'no-default t))) | |
235 ;; $'s should be quoted (against substitute-in-file-name) in file | |
236 ;; names inserted here | |
237 (if initial | |
238 (setq initial (gmhist-quote-dollars (gmhist-unexpand-home initial))) | |
239 (if insert-default-directory | |
240 (setq initial (gmhist-quote-dollars (gmhist-unexpand-home dir))))) | |
241 (let* ((minibuffer-completion-confirm (if (eq mustmatch t) nil t)) | |
242 (minibuffer-completion-table 'read-file-name-internal) | |
243 (minibuffer-completion-predicate dir) | |
244 (minibuffer-history-symbol file-history-symbol) | |
245 (val (gmhist-new-read-from-minibuffer | |
246 grfn-prompt initial (gmhist-lookup-keymap | |
247 (if mustmatch | |
248 gmhist-filename-must-match-map | |
249 gmhist-filename-completion-map))))) | |
250 | |
251 (or (and (or (and (stringp initial) | |
252 (string= initial val)) | |
253 (and (null initial) | |
254 (zerop (length val)))) | |
255 default) | |
256 (substitute-in-file-name val)))) | |
257 | |
258 (defun gmhist-unexpand-home (file) | |
259 ;; Make prompt look nicer by un-expanding home dir. | |
260 ;; read-file-name does this, too. | |
261 ;; Avoid clobbering match-data with string-match. | |
262 (let* ((home (expand-file-name "~/")) | |
263 (home-len (length home)) | |
264 (file-len (length file))) | |
265 (if (and home | |
266 (stringp file) | |
267 (>= file-len home-len) | |
268 (string= home (substring file 0 home-len)) | |
269 (eq ?/ (aref file (1- home-len)))) | |
270 (concat "~/" (substring file home-len)) | |
271 file))) | |
272 | |
273 ; (defun gmhist-quote-dollars (file) | |
274 ; "Quote `$' as `$$' in FILE to get it past function `substitute-in-file-name.'" | |
275 ; (apply (function concat) | |
276 ; (mapcar (function | |
277 ; (lambda (char) | |
278 ; (if (= char ?$) | |
279 ; "$$" | |
280 ; (vector char)))) | |
281 ; file))) | |
282 ;; 10000 iterations of (gmhist-quote-dollars "foo") took 19 seconds | |
283 ;; and *lots* of garbage collections (about a dozen or more) | |
284 | |
285 ;; This version does not cons and is much faster in the usual case | |
286 ;; without $ present: | |
287 ;; 10000 iterations of (gmhist-quote-dollars "foo") took 4 seconds and | |
288 ;; not a single garbage collection. | |
289 (defun gmhist-quote-dollars (file) | |
290 "Quote `$' as `$$' in FILE to get it past function `substitute-in-file-name.'" | |
291 (let ((pos 0)) | |
292 (while (setq pos (string-match "\\$" file pos)) | |
293 (setq file (concat (substring file 0 pos) | |
294 "$";; precede by escape character (also a $) | |
295 (substring file pos)) | |
296 ;; add 2 instead 1 since another $ was inserted | |
297 pos (+ 2 pos))) | |
298 file)) | |
299 | |
300 | |
301 | |
302 (defun read-buffer-with-history-in (rbwhi-hist-sym &rest args) | |
303 "Like read-buffer, but with additional first arg HISTORY-SYMBOL." | |
304 (let ((buffer-history-symbol rbwhi-hist-sym)) | |
305 (apply 'gmhist-read-buffer args))) | |
306 | |
307 (defvar buffer-history-symbol 'buffer-history | |
308 "*If non-nil, it is the name (a symbol) of a variable on which to cons | |
309 buffer names entered in the minibuffer.") | |
310 | |
311 (defun gmhist-read-buffer (grb-prompt &optional default existing) | |
312 "Read a buffer name, maintaining history in buffer-history-symbol and return as string. | |
313 Args PROMPT &optional DEFAULT EXISTING. | |
314 Optional arg EXISTING means an existing buffer must be entered." | |
315 (if (bufferp default);; want string in prompt, not buffer object | |
316 (setq default (buffer-name default))) | |
317 (if buffer-history-symbol | |
318 (put buffer-history-symbol 'default default)) ; also if nil | |
319 (let* ((minibuffer-history-symbol buffer-history-symbol) | |
320 (name (gmhist-completing-read | |
321 grb-prompt | |
322 ;;(function (lambda (buf) (list (buffer-name buf)))) | |
323 ;; convert to alist in format (BUF-NAME . BUF-OBJ) | |
324 (mapcar | |
325 (function (lambda (arg) (cons (buffer-name arg) arg))) | |
326 (buffer-list)) | |
327 (function (lambda (elt) (get-buffer (car elt)))) | |
328 existing))) | |
329 (if (equal "" name) | |
330 default | |
331 name))) | |
332 | |
333 (defvar minibuffer-history-symbol 'minibuffer-history | |
334 "*If non-nil, it is the name (a symbol) of a variable on which to cons | |
335 the string entered in the minibuffer. | |
336 Input is stored as string, even for e.g. `read-buffer'.") | |
337 | |
338 (defvar minibuffer-history nil | |
339 "List of strings entered using the minibuffer, most recent first.") | |
340 | |
341 (put 'minibuffer-history 'no-default t) | |
342 | |
343 (defvar minibuffer-history-read-only nil | |
344 "If non-nil, nothing will be stored on `minibuffer-history-symbol'. | |
345 History motions commands are still available in the minibuffer.") | |
346 | |
347 (defvar minibuffer-history-position nil | |
348 "If currently reading the minibuffer, the history position.") | |
349 | |
350 (defvar minibuffer-initial-contents nil | |
351 "If currently reading the minibuffer, the initial contents.") | |
352 | |
353 ;; Save the subr, we need it inside the redefined version: | |
354 (or (fboundp 'gmhist-old-read-from-minibuffer) | |
355 (fset 'gmhist-old-read-from-minibuffer | |
356 (symbol-function 'read-from-minibuffer))) | |
357 | |
358 (defun gmhist-new-read-from-minibuffer | |
359 (gnrfm-prompt &optional initial-contents keymap read position) | |
360 "Read a string from the minibuffer, prompting with string PROMPT. | |
361 If optional second arg INITIAL-CONTENTS is non-nil, it is a string | |
362 to be inserted into the minibuffer before reading input. | |
363 Third arg KEYMAP is a keymap to use whilst reading; | |
364 if omitted or nil, the default is `minibuffer-local-map'. | |
365 If fourth arg READ is non-nil, then interpret the result as a lisp object | |
366 and return that object: | |
367 in other words, do `(car (read-from-string INPUT-STRING))' | |
368 Fifth arg POSITION, if non-nil, is where to put point | |
369 in the minibuffer after inserting INITIAL-CONTENTS. | |
370 | |
371 The ambient value of `minibuffer-history-symbol' (q.v.) is used and set. | |
372 | |
373 *** This is the gmhist version.***" | |
374 (if (null minibuffer-history-symbol) | |
375 (if gmhist-emacs-19-p | |
376 (gmhist-old-read-from-minibuffer | |
377 gnrfm-prompt initial-contents keymap read position) | |
378 (gmhist-old-read-from-minibuffer gnrfm-prompt initial-contents | |
379 keymap read)) | |
380 (gmhist-read-from-minibuffer | |
381 gnrfm-prompt initial-contents keymap read position))) | |
382 | |
383 (defun gmhist-read-from-minibuffer (grfm-prompt | |
384 &optional | |
385 initial-contents keymap read position) | |
386 (or keymap (setq keymap minibuffer-local-map)) | |
387 (or minibuffer-history-read-only | |
388 (boundp minibuffer-history-symbol) ; history list defaults to nil | |
389 ;; create history list if not already done | |
390 (set minibuffer-history-symbol | |
391 (get minibuffer-history-symbol 'initial-hist))) | |
392 (let* ((minibuffer-history-position 0) ; fluid var for motion commands | |
393 (minibuffer-initial-contents initial-contents) ; ditto | |
394 (history (symbol-value minibuffer-history-symbol)) | |
395 ;; Command is an s-exp when read->t. In this case, | |
396 ;; cannot have empty input: | |
397 (no-default (or read | |
398 (get minibuffer-history-symbol 'no-default))) | |
399 (dangerous (if no-default | |
400 nil | |
401 (get minibuffer-history-symbol 'dangerous))) | |
402 ;; Idea for 'backup feature by Mike Williams | |
403 (backup (get minibuffer-history-symbol 'backup)) | |
404 (default (if no-default | |
405 nil | |
406 (get minibuffer-history-symbol 'default))) | |
407 (the-prompt (if default | |
408 (concat grfm-prompt (format gmhist-default-format | |
409 default)) | |
410 grfm-prompt)) | |
411 (the-initial (if (or minibuffer-initial-contents | |
412 (not backup)) | |
413 minibuffer-initial-contents | |
414 ;; else we must backup in the history list | |
415 (setq backup (min (max 0 (or (and (integerp backup) | |
416 backup) | |
417 1)) | |
418 (length history))) | |
419 (if (zerop (setq minibuffer-history-position backup)) | |
420 nil | |
421 ;; else backup is at least 1 | |
422 (let ((backup-input (nth (1- backup) history))) | |
423 (if read | |
424 (prin1-to-string backup-input) | |
425 backup-input))))) | |
426 command) | |
427 ;; Read the command from minibuffer, providing history motion | |
428 ;; key map and minibuffer completion | |
429 (setq command | |
430 (if position | |
431 ;; avoid passing POSITION arg unless given (presumably | |
432 ;; we are in Emacs 19 then) | |
433 (gmhist-old-read-from-minibuffer the-prompt the-initial keymap | |
434 position) | |
435 (gmhist-old-read-from-minibuffer the-prompt the-initial keymap))) | |
436 ;; Care about default values unless forbidden: | |
437 (or no-default | |
438 (setq command (gmhist-handle-default command default dangerous))) | |
439 (if minibuffer-history-read-only | |
440 nil | |
441 (let (ignore) | |
442 ;; Add to history if first command, or not a dup, or not to be ignored | |
443 (or (and history | |
444 (or (if (get minibuffer-history-symbol 'keep-dups) | |
445 nil | |
446 (equal command (car history))) | |
447 (if (stringp (setq ignore (get minibuffer-history-symbol | |
448 'hist-ignore))) | |
449 (string-match ignore | |
450 (gmhist-stringify (car history)))))) | |
451 (set minibuffer-history-symbol (cons command history))))) | |
452 ;; Return command's value to caller: | |
453 (if read | |
454 (car (read-from-string command)) | |
455 command))) | |
456 | |
457 (defun gmhist-handle-default (command default dangerous) | |
458 (if (string= "" command) | |
459 (if default (setq command default))) | |
460 ;; Set default value unless it is dangerous. | |
461 (or (and (stringp dangerous) | |
462 ;; Should actually save match-data as we call string-match | |
463 (string-match dangerous (gmhist-stringify command))) | |
464 (put minibuffer-history-symbol 'default command)) | |
465 ;; Return the prefrobnicated command: | |
466 command) | |
467 | |
468 | |
469 ;; Minibuffer key maps to implement history | |
470 | |
471 (defvar gmhist-define-keys-hook nil | |
472 "Hook run inside function `gmhist-define-keys' (q.v.), after the | |
473 standard gmhist bindings.") | |
474 | |
475 (or (fboundp 'gmhist-define-keys) | |
476 (defun gmhist-define-keys (map) | |
477 "Bind the standard history commands in MAP, a key map. | |
478 | |
479 When gmhist is loaded, this function is only defined if you have not | |
480 already defined it, so that you can customize it without worrying | |
481 about load order. | |
482 You can also use `gmhist-define-keys-hook' if you just want to add to | |
483 existing bindings." | |
484 (define-key map "\M-p" 'gmhist-previous) | |
485 (define-key map "\M-n" 'gmhist-next) | |
486 (define-key map "\M-r" 'gmhist-search-backward) | |
487 (define-key map "\M-s" 'gmhist-search-forward) | |
488 ;;(define-key map "\M-<" 'gmhist-beginning) | |
489 ;;(define-key map "\M-<" 'gmhist-beginning) | |
490 ;; Last two for bash/readline compatibility. Better M-a and M-e ? | |
491 ;; In query-replace, multi-line text together with next-line's | |
492 ;; misfeature of adding blank lines really lets you lose without M-< | |
493 ;; and M->. | |
494 ;;(define-key map "\M-a" 'gmhist-beginning) | |
495 ;;(define-key map "\M-e" 'gmhist-end) | |
496 ;; M-a is already used in electric replace | |
497 ;; Try this as general purpose mover: | |
498 (define-key map "\M-g" 'gmhist-toggle) | |
499 (define-key map "\M-G" 'gmhist-switch-history) | |
500 (define-key map "\M-?" 'gmhist-show) | |
501 (run-hooks 'gmhist-define-keys-hook))) | |
502 | |
503 (defun gmhist-lookup-keymap (map) | |
504 (if (keymapp map) | |
505 map | |
506 (gmhist-lookup-keymap (symbol-value map)))) | |
507 | |
508 (defvar gmhist-map nil | |
509 "Key map for generic minibuffer history. | |
510 \\<gmhist-map>\\[gmhist-previous], \\[gmhist-next], \ | |
511 \\[gmhist-beginning], \\[gmhist-end] move through, \ | |
512 \\[gmhist-search-backward] and \\[gmhist-search-forward] search, | |
513 \\[gmhist-show] displays the history: | |
514 \\{gmhist-map}") | |
515 | |
516 (if gmhist-map | |
517 nil | |
518 (setq gmhist-map (copy-keymap minibuffer-local-map)) | |
519 (gmhist-define-keys gmhist-map)) | |
520 | |
521 (defvar gmhist-completion-map nil | |
522 "Key map for generic minibuffer history with completion, see gmhist-map.") | |
523 | |
524 (if gmhist-completion-map | |
525 nil | |
526 ;; If you have loaded D. Gillespie's complete.el or Christopher | |
527 ;; McConnell's completer.el *before* gmhist, you get it in gmhist, | |
528 ;; too: | |
529 (setq gmhist-completion-map (copy-keymap minibuffer-local-completion-map)) | |
530 (gmhist-define-keys gmhist-completion-map)) | |
531 | |
532 (defvar gmhist-must-match-map nil | |
533 "Key map for generic minibuffer history with completion that must match, | |
534 see gmhist-map.") | |
535 | |
536 (if gmhist-must-match-map | |
537 nil | |
538 (setq gmhist-must-match-map (copy-keymap minibuffer-local-must-match-map)) | |
539 (gmhist-define-keys gmhist-must-match-map)) | |
540 | |
541 (defvar gmhist-filename-completion-map 'gmhist-completion-map | |
542 "A keymap (or a symbol pointing to one) to use in filename | |
543 completion that need not match. Defaults to 'gmhist-completion-map.") | |
544 | |
545 (defvar gmhist-filename-must-match-map 'gmhist-must-match-map | |
546 | |
547 "A keymap (or a symbol pointing to one) to use in filename | |
548 completion that must match. Defaults to 'gmhist-must-match-map.") | |
549 | |
550 | |
551 ;; Minibuffer commands to implement history | |
552 ;; They run inside read-with-history-in and heavily depend on fluid | |
553 ;; vars from there. | |
554 | |
555 (defun gmhist-goto (n) | |
556 ;; Go to history position N, 1 <= N <= length of history | |
557 ;; N<0 means the future and inserts an empty string | |
558 ;; N=0 means minibuffer-initial-contents (fluid var from | |
559 ;; gmhist-new-read-from-minibuffer) | |
560 (run-hooks 'gmhist-before-move-hook) | |
561 (erase-buffer) | |
562 (setq minibuffer-history-position n) | |
563 (if (< n 0) | |
564 nil | |
565 (insert | |
566 (gmhist-stringify | |
567 (if (= n 0) | |
568 (or minibuffer-initial-contents "") | |
569 (nth (1- n) (symbol-value minibuffer-history-symbol))))) | |
570 (run-hooks 'gmhist-after-insert-hook) | |
571 ;; next two actually would be a good application for this hook | |
572 (goto-char (if (get minibuffer-history-symbol 'cursor-end) | |
573 (point-max) | |
574 (point-min))) | |
575 (let ((pos (get minibuffer-history-symbol 'cursor-pos))) | |
576 (if (stringp pos) | |
577 (if (eobp) | |
578 (re-search-backward pos nil t) | |
579 (re-search-forward pos nil t)))))) | |
580 | |
581 (defun gmhist-beginning () | |
582 "Go to the oldest command in the history." | |
583 (interactive) | |
584 (gmhist-goto (length (symbol-value minibuffer-history-symbol)))) | |
585 | |
586 (defun gmhist-end () | |
587 "Position before the most recent command in the history." | |
588 (interactive) | |
589 (gmhist-goto 0)) | |
590 | |
591 (defun gmhist-toggle (&optional n) | |
592 "If at end of history, move to beginning, else move to end. | |
593 Prefix arg is history position to go to." | |
594 (interactive "P") | |
595 (if n | |
596 (gmhist-goto (prefix-numeric-value n)) | |
597 (if (= 0 minibuffer-history-position) | |
598 (gmhist-beginning) | |
599 (gmhist-end)))) | |
600 | |
601 (defun gmhist-switch-history (new-history) | |
602 "Switch to a different history." | |
603 (interactive | |
604 (let ((enable-recursive-minibuffers t)) | |
605 (list (read-from-minibuffer "Switch to history: " nil nil t)))) | |
606 (setq minibuffer-history-symbol new-history | |
607 minibuffer-history-position 0)) | |
608 | |
609 (defun gmhist-next (n) | |
610 "Go to next history position." | |
611 ;; fluid vars: minibuffer-history-symbol minibuffer-history-position | |
612 ;; Inserts the next element of minibuffer-history-symbol's value | |
613 ;; into the minibuffer. | |
614 ;; minibuffer-history-position is the current history position. | |
615 (interactive "p") | |
616 ;; clip the new history position to the valid range: | |
617 (let ((narg (min (max 0 (- minibuffer-history-position n)) | |
618 (length (symbol-value minibuffer-history-symbol))))) | |
619 (if (= minibuffer-history-position narg) | |
620 (error "No %s item in %s" | |
621 (if (= 0 minibuffer-history-position) "following" "preceding") | |
622 minibuffer-history-symbol) | |
623 (gmhist-goto narg)))) | |
624 | |
625 (defun gmhist-previous (n) | |
626 "Go to previous history position." | |
627 (interactive "p") | |
628 (gmhist-next (- n))) | |
629 | |
630 ;; Searching the history | |
631 | |
632 (defun gmhist-search-backward (regexp &optional forward) | |
633 "Search backward in the history list for REGEXP. | |
634 With prefix argument, search for line that contains match for current line." | |
635 (interactive | |
636 (if current-prefix-arg | |
637 (list (regexp-quote (buffer-string))) | |
638 (let ((enable-recursive-minibuffers t)) | |
639 (list (read-with-history-in 'gmhist-search-history | |
640 "History search (regexp): "))))) | |
641 (let* (found | |
642 (direction (if forward -1 1)) | |
643 (pos (+ minibuffer-history-position direction)) ; find _next_ match! | |
644 (history (symbol-value minibuffer-history-symbol)) | |
645 (len (length history))) | |
646 (while (and (if forward (> pos 0) (<= pos len)) | |
647 (not (setq found | |
648 (string-match | |
649 regexp | |
650 (gmhist-stringify (nth (1- pos) history)))))) | |
651 (setq pos (+ pos direction))) | |
652 (or found (error "%s not found in %s" regexp minibuffer-history-symbol)) | |
653 (gmhist-goto pos))) | |
654 | |
655 (defun gmhist-search-forward (regexp &optional backward) | |
656 "Search forward in the history list for REGEXP. | |
657 With prefix argument, search for line that matches current line | |
658 instead of prompting for REGEXP." | |
659 (interactive | |
660 (if current-prefix-arg | |
661 (list (regexp-quote (buffer-string))) | |
662 (let ((enable-recursive-minibuffers t)) | |
663 (list (read-with-history-in 'gmhist-search-history | |
664 "History search forward (regexp): "))))) | |
665 (gmhist-search-backward regexp (not backward))) | |
666 | |
667 ;; Misc. | |
668 | |
669 (defun gmhist-stringify (elt) | |
670 ;; If ELT is not a string, convert it to one. | |
671 (if (stringp elt) elt (prin1-to-string elt))) | |
672 | |
673 (defun gmhist-show () | |
674 "Show the history list in another buffer. | |
675 Use \\[scroll-other-window] to scroll, with negative arg to scroll back." | |
676 (interactive) | |
677 (let ((count 0)) | |
678 (with-output-to-temp-buffer (concat "*" (symbol-name minibuffer-history-symbol) "*") | |
679 (mapcar | |
680 (function | |
681 (lambda (x) | |
682 (princ (format "%2s%2d: %s\n" | |
683 (if (eq (setq count (1+ count)) | |
684 minibuffer-history-position) | |
685 "> " | |
686 " ") | |
687 count x)))) | |
688 (symbol-value minibuffer-history-symbol))))) | |
689 | |
690 (defun gmhist-remember-zero () | |
691 "Put this function on gmhist-before-move-hook to make gmhist | |
692 remember the initial value even after you edited it: | |
693 | |
694 (setq gmhist-before-move-hook 'gmhist-remember-zero)" | |
695 (if (zerop minibuffer-history-position) | |
696 (setq minibuffer-initial-contents (buffer-string)))) | |
697 | |
698 ;; Hack up interactive specifications of existing functions | |
699 | |
700 (defun gmhist-copy-function (fun) | |
701 (let ((old (gmhist-symbol-function fun))) | |
702 (if (consp old) ; interpreted, or v18 compiled | |
703 ;; copy-sequence does not copy recursively. | |
704 ;; Iteration is faster than recursion, and we need just two levels | |
705 ;; to be able to use setcdr to mung the interactive spec. | |
706 (let (new elt) | |
707 (while old | |
708 (setq elt (car old) | |
709 old (cdr old) | |
710 new (cons (if (sequencep elt) | |
711 (copy-sequence elt) | |
712 elt) | |
713 new))) | |
714 (nreverse new)) | |
715 ;; else v19 compiled | |
716 (let ((new (append old nil))) | |
717 (setcar (nthcdr 5 new) (copy-sequence (aref old 5))) | |
718 (apply 'make-byte-code new))))) | |
719 | |
720 (defun gmhist-check-autoload (fun) | |
721 "If FUN is an autoload, load its definition." | |
722 (let ((lis (symbol-function fun))) | |
723 (if (and (listp lis) ; FUN could also be a subr | |
724 (eq 'autoload (car lis))) | |
725 (load (nth 1 lis))))) | |
726 | |
727 (defun gmhist-replace-spec (fun new-spec &optional copy-first) | |
728 "Replace the interactive specification of FUN with NEW-SPEC. | |
729 FUN must be a symbol with a function definition. | |
730 Autoload functions are taken care of by loading the appropriate file first. | |
731 If FUN is a pure storage function (one dumped into Emacs) it is first | |
732 copied onto itself, because pure storage cannot be modified. | |
733 Optional non-nil third arg COPY-FIRST is used internally for this. | |
734 The old spec is put on FUN's gmhist-old-interactive-spec property. | |
735 That property is never overwritten by this function. It is used by | |
736 function gmhist-remove-magic." | |
737 (gmhist-check-autoload fun) | |
738 (if copy-first ; copy (from pure storage) | |
739 (fset fun (gmhist-copy-function fun))) | |
740 (let* ((flambda (gmhist-symbol-function fun)) | |
741 (fint (and (consp flambda) | |
742 (if (eq 'interactive (car-safe (nth 2 flambda))) | |
743 (nth 2 flambda) | |
744 (if (eq 'interactive (car-safe (nth 3 flambda))) | |
745 (nth 3 flambda) | |
746 (error "%s is not interactive" fun))))) | |
747 (old-spec (if fint | |
748 (nth 1 fint) | |
749 (gmhist-spec fun)))) | |
750 ;; Save old interactive spec as property of FUN: | |
751 (or (get fun 'gmhist-old-interactive-spec) | |
752 (put fun 'gmhist-old-interactive-spec old-spec)) | |
753 ;; Replace '(interactive OLD-SPEC) with '(interactive NEW-SPEC) | |
754 (if copy-first | |
755 ;; This should not fail - if it does, we must abort. | |
756 (if (consp flambda) | |
757 (setcdr fint (list new-spec)) | |
758 ;; can't "aset" a #<byte-code> object, though aref works... | |
759 (setq flambda (append flambda nil)) | |
760 (setcar (nthcdr 5 flambda) new-spec) | |
761 (setq flambda (apply 'make-byte-code flambda)) | |
762 (fset fun flambda)) | |
763 ;; else prepare for a second try | |
764 (condition-case err | |
765 (setcdr fint (list new-spec)) | |
766 (error | |
767 ;; Setcdr bombs on preloaded functions: | |
768 ;; (error "Attempt to modify read-only object") | |
769 ;; There seems to be no simple way to test whether an object | |
770 ;; resides in pure storage, so we let it bomb and try again | |
771 ;; after copying it into writable storage. | |
772 (gmhist-replace-spec fun new-spec t)))))) | |
773 | |
774 (defun gmhist-spec (fun) | |
775 "Get the current interactive specification for FUN (a symbol). | |
776 Signal an error if FUN is not interactive." | |
777 (let ((flambda (gmhist-symbol-function fun)) | |
778 fint) | |
779 (cond ((consp flambda) ; interpreted, or v18 compiled | |
780 ;; do it exactly like call-interactively, even if this | |
781 ;; means (interactive...) can come arbitrary late in FUN's body | |
782 (setq fint (assq 'interactive (cdr (cdr flambda)))) | |
783 (or fint | |
784 (error "Cannot get spec of a non-interactive command: %s!" fun)) | |
785 (nth 1 fint)) | |
786 (t ; otherwise it's a v19 compiled-code object | |
787 (aref flambda 5))))) | |
788 | |
789 (defun gmhist-symbol-function (fun) | |
790 ;; Return FUN's ultimate definition. | |
791 ;; Recurse if FUN is fset to another function's name. | |
792 (let ((flambda (symbol-function fun))) | |
793 (if (symbolp flambda) | |
794 ;; Prefer recursion over while because infinite loop is caught | |
795 ;; by max-lisp-eval-depth. | |
796 (gmhist-symbol-function flambda) | |
797 flambda))) | |
798 | |
799 ;; Automagic gmhistification | |
800 | |
801 ;; There should be a builtin split function - inverse to mapconcat. | |
802 (defun gmhist-split (pat str &optional limit) | |
803 "Splitting on regexp PAT, turn string STR into a list of substrings. | |
804 Optional third arg LIMIT (>= 1) is a limit to the length of the | |
805 resulting list. | |
806 Thus, if SEP is a regexp that only matches itself, | |
807 | |
808 (mapconcat 'identity (gmhist-split SEP STRING) SEP) | |
809 | |
810 is always equal to STRING." | |
811 (let* ((start (string-match pat str)) | |
812 (result (list (substring str 0 start))) | |
813 (count 1) | |
814 (end (if start (match-end 0)))) | |
815 (if end ; else nothing left | |
816 (while (and (or (not (integerp limit)) | |
817 (< count limit)) | |
818 (string-match pat str end)) | |
819 (setq start (match-beginning 0) | |
820 count (1+ count) | |
821 result (cons (substring str end start) result) | |
822 end (match-end 0) | |
823 start end) | |
824 )) | |
825 (if (and (or (not (integerp limit)) | |
826 (< count limit)) | |
827 end) ; else nothing left | |
828 (setq result | |
829 (cons (substring str end) result))) | |
830 (nreverse result))) | |
831 | |
832 (defun gmhist-interactive (spec hist) | |
833 "Interpret SPEC, an interactive string, like call-interactively | |
834 would, only with minibuffer history in HIST (a symbol). | |
835 | |
836 If the value of HIST is another symbol (which can never happen if | |
837 history lists are already stored on it), this symbol is taken instead | |
838 to facilitate dynamic indirections. | |
839 | |
840 Currently recognized key letters are: | |
841 | |
842 a b B c C d D k m N n s S x X f F r p P v | |
843 | |
844 and initial `*'. | |
845 | |
846 Use it inside interactive like this | |
847 | |
848 \(interactive \(gmhist-interactive \"sPrompt: \\nP\" 'foo-history\)\) | |
849 | |
850 or even like this: | |
851 | |
852 \(interactive | |
853 \(gmhist-interactive \"sReplace: \\nsReplace %s with: \" 'replace-history\)\) | |
854 " | |
855 (or (stringp spec) | |
856 (error "gmhist-interactive: not a string %s" spec)) | |
857 (if (and (> (length spec) 0) (eq ?\* (aref spec 0))) | |
858 (progn | |
859 (barf-if-buffer-read-only) | |
860 (setq spec (substring spec 1)))) | |
861 (if (and (boundp hist) | |
862 (symbolp (symbol-value hist)) | |
863 (not (null (symbol-value hist)))) | |
864 (setq hist (symbol-value hist))) | |
865 (let ((spec-list (mapcar '(lambda (x) | |
866 ;; forgive empty entries like | |
867 ;; call-interactively does: | |
868 (if (equal "" x) | |
869 nil | |
870 (cons (aref x 0) (substring x 1)))) | |
871 (gmhist-split "\n" spec))) | |
872 cur-arg args-so-far special elt char prompt xprompt) | |
873 (setq spec-list (delq nil spec-list)) | |
874 (while spec-list | |
875 (setq elt (car spec-list) | |
876 spec-list (cdr spec-list) | |
877 special nil ; special handling of args-so-far | |
878 char (car elt) | |
879 prompt (cdr elt) | |
880 xprompt (apply (function format) prompt (reverse args-so-far))) | |
881 (cond ((eq char ?a) ; Symbol defined as a function | |
882 (setq cur-arg (intern | |
883 (completing-read-with-history-in | |
884 hist xprompt obarray 'fboundp t nil)))) | |
885 ((eq char ?b) ; Name of existing buffer | |
886 (setq cur-arg (read-buffer-with-history-in | |
887 hist xprompt (other-buffer) t))) | |
888 ((eq char ?B) ; Name of possibly non-existing buffer | |
889 (setq cur-arg (read-buffer-with-history-in | |
890 hist xprompt (other-buffer) nil))) | |
891 ((eq char ?c) ; Character | |
892 (message xprompt) ; history doesn't make sense for this | |
893 (setq cur-arg (read-char))) | |
894 ((eq char ?C) ; Command | |
895 (setq cur-arg (intern | |
896 (completing-read-with-history-in | |
897 hist xprompt obarray 'commandp t nil)))) | |
898 ((eq char ?d) ; Value of point. Does not do I/O. | |
899 (setq cur-arg (point))) | |
900 ((eq char ?D) ; directory name | |
901 ;; This does not check file-directory-p, but neither does | |
902 ;; call-interactively. | |
903 (setq cur-arg (read-file-name-with-history-in | |
904 hist | |
905 xprompt | |
906 nil | |
907 default-directory | |
908 'confirm))) | |
909 ((eq char ?f) ; existing file name | |
910 (setq cur-arg (read-file-name-with-history-in | |
911 hist | |
912 xprompt | |
913 nil nil 'confirm))) | |
914 ((eq char ?F) ; possibly nonexistent file name | |
915 (setq cur-arg (read-file-name-with-history-in | |
916 hist | |
917 xprompt))) | |
918 ((eq char ?k) ; Key sequence (string) | |
919 (setq cur-arg (read-key-sequence (if (equal xprompt "") | |
920 nil xprompt)))) | |
921 ((eq char ?m) ; Value of mark. Does not do I/O. | |
922 (setq cur-arg (or (mark) (error "The mark is not set now")))) | |
923 ((eq char ?N) ; Prefix arg, else number from minibuf | |
924 (if current-prefix-arg | |
925 (setq cur-arg (prefix-numeric-value current-prefix-arg)) | |
926 (while (not (integerp | |
927 (setq cur-arg | |
928 (read-with-history-in hist xprompt nil t))))))) | |
929 ((eq char ?n) ; Read number from minibuffer | |
930 (while (not (integerp | |
931 (setq cur-arg | |
932 (read-with-history-in hist xprompt nil t)))))) | |
933 ((eq char ?p) ; cooked prefix arg | |
934 (setq cur-arg (prefix-numeric-value current-prefix-arg))) | |
935 ((eq char ?P) ; raw prefix arg | |
936 (setq cur-arg current-prefix-arg)) | |
937 ((eq char ?r) ; region | |
938 (let (region-min region-max) | |
939 ;; take some pains to behave exactly like interactive "r" | |
940 (setq region-min (min (or (mark) | |
941 (error "The mark is not set now")) | |
942 (point)) | |
943 region-max (max (or (mark) | |
944 (error "The mark is not set now")) | |
945 (point))) | |
946 (setq args-so-far | |
947 (append (list region-max region-min) args-so-far) | |
948 special t))) | |
949 ((eq char '?s) ; string | |
950 (setq cur-arg (read-with-history-in hist xprompt))) | |
951 ((eq char ?S) ; any symbol | |
952 (setq cur-arg (read-with-history-in hist xprompt nil t))) | |
953 ((eq char ?v) ; Variable name | |
954 (setq cur-arg (completing-read-with-history-in | |
955 hist xprompt obarray 'user-variable-p t nil))) | |
956 ((memq char '(?x ?X)) ; lisp expression | |
957 (setq cur-arg (read-with-history-in | |
958 hist | |
959 xprompt | |
960 nil | |
961 ;; have to tell gmhist to read s-exps | |
962 ;; instead of strings: | |
963 t)) | |
964 (if (eq char ?X) ; lisp expression, evaluated | |
965 (setq cur-arg (eval cur-arg)))) | |
966 | |
967 (t | |
968 (error "Invalid control letter `%c' in gmhist-interactive" char))) | |
969 (or special | |
970 (setq args-so-far (cons cur-arg args-so-far)))) | |
971 (reverse args-so-far))) | |
972 | |
973 (defun gmhist-new-spec (fun &optional hist no-error) | |
974 "Return a new interactive specification for FUN, suitable for use | |
975 with setcdr in function gmhist-replace-spec. | |
976 Use symbol HIST to store the history. HIST defaults to `FUN-history'. | |
977 The returned spec does the same as the old one, only with history in HIST. | |
978 | |
979 If FUN is an autoload object, its file is loaded first. | |
980 | |
981 See function gmhist-interactive for a list of recognized interactive | |
982 keys letters. | |
983 | |
984 Unless optional third arg NO-ERROR is given, signals an error if FUN's | |
985 interactive string contains unknown key letters or has no interactive string. | |
986 With NO-ERROR, it returns nil." | |
987 (or hist (setq hist (intern (concat (symbol-name fun) "-history")))) | |
988 (gmhist-check-autoload fun) | |
989 (let ((spec (gmhist-spec fun))) | |
990 (if (stringp spec) | |
991 (list 'gmhist-interactive spec (list 'quote hist)) | |
992 (if no-error | |
993 nil | |
994 (error "Can't gmhistify %s's spec: %s" fun spec))))) | |
995 | |
996 (defun gmhist-make-magic (fun &optional hist) | |
997 "Make FUN magically maintain minibuffer history in symbol HIST. | |
998 HIST defaults to `FUN-history'. | |
999 This works by modifying the interactive specification, which must be a | |
1000 string. For more complicated cases, see gmhist-replace-spec. | |
1001 The magic goes away when you call gmhist-remove-magic on FUN." | |
1002 (interactive "CPut gmhist magic on command: ") | |
1003 (let ((new-spec (gmhist-new-spec fun hist t))) | |
1004 (if new-spec | |
1005 (gmhist-replace-spec fun new-spec) | |
1006 ;; else there was some error. Try to find out if this is a retry. | |
1007 (if (not (get fun 'gmhist-old-interactive-spec)) | |
1008 (error "Too complicated for gmhist: %s" fun) | |
1009 (message "Another attempt to put magic on %s..." fun) | |
1010 (gmhist-remove-magic fun) ; will abort if not a retry | |
1011 ;; This time we don't catch errors - magic or blow! | |
1012 (gmhist-replace-spec fun (gmhist-new-spec fun hist)) | |
1013 (message "Another attempt to put magic on %s...done." fun))))) | |
1014 | |
1015 (defun gmhist-remove-magic (fun) | |
1016 "Remove the magic that gmhist-make-magic put on FUN, | |
1017 restoring the old interactive spec." | |
1018 (interactive "CRemove gmhist magic from command: ") | |
1019 (gmhist-replace-spec | |
1020 fun | |
1021 (or (get fun 'gmhist-old-interactive-spec) | |
1022 (error "Can't find %s's old interactive spec!" fun)))) | |
1023 | |
1024 ;; Now make yourself magic | |
1025 (gmhist-make-magic 'gmhist-make-magic 'gmhist-make-magic-history) | |
1026 (gmhist-make-magic 'gmhist-remove-magic 'gmhist-make-magic-history) | |
1027 | |
1028 | |
1029 ;; Examples, pedagogic and serious ones. More in gmhist-app.el. | |
1030 | |
1031 ;;(defun foo-command (cmd) | |
1032 ;; (interactive (list | |
1033 ;; (read-with-history-in 'foo-history "Foo: "))) | |
1034 ;; (message "Foo %s" cmd)) | |
1035 ;; | |
1036 ;; ;; The interactive clause could also have been the simpler | |
1037 ;; ;; (interactive (gmhist-interactive "sFoo: " 'foo-history)) | |
1038 ;; | |
1039 ;; | |
1040 ;;;(put 'foo-history 'hist-map minibuffer-local-map) ; disable motion ... | |
1041 ;;;(put 'foo-history 'hist-function 'gmhist-read-nohistory) ; and history | |
1042 ;; | |
1043 ;;(put 'foo-history 'hist-function nil) ; enable history ... | |
1044 ;;(put 'foo-history 'hist-map nil) ; and motion again | |
1045 ;; | |
1046 ;;(defun gmhist-read-nohistory (symbol prompt initial-input read) | |
1047 ;; "An example function to put on the hist-function property." | |
1048 ;; (message "read-nohistory...") | |
1049 ;; (sit-for 2) | |
1050 ;; (read-string prompt initial-input)) | |
1051 ;; | |
1052 ;; Example for reading file names: | |
1053 ;;(defun bar-command (cmd) | |
1054 ;; (interactive | |
1055 ;; (list | |
1056 ;; (read-file-name-with-history-in | |
1057 ;; ;; HIST-SYM PROMPT DIR DFLT MUSTMATCH | |
1058 ;; 'bar-history "Bar: " nil nil 'confirm))) | |
1059 ;; (message "Bar %s" cmd)) | |
1060 ;; | |
1061 ;; Example function to apply gmhist-make-magic to. | |
1062 ;; Compare the missing initial input in bar to the magic version of zod. | |
1063 ;;(defun zod-command (cmd) | |
1064 ;; (interactive "fZod: ") | |
1065 ;; (message "Zod %s" cmd)) | |
1066 | |
1067 ;; Finally run the load-hook | |
1068 | |
1069 (run-hooks 'gmhist-load-hook) | |
1070 | |
1071 ;; End of file gmhist.el |