comparison lisp/dired/gmhist-mh.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-mh.el - emulate proposed Emacs 19 builtin Minibuffer History
2 ;;;; Id: gmhist-mh.el,v 4.8 1991/09/20 13:15:40 sk RelBeta
3
4 ;;;; This package redefines the functions
5 ;;;;
6 ;;;; read-string
7 ;;;; completing-read
8 ;;;; write-region
9 ;;;; delete-file
10 ;;;; read-buffer
11 ;;;; read-file-name
12 ;;;; switch-to-buffer
13 ;;;;
14 ;;;; to implement the variables
15 ;;;;
16 ;;;; minibuffer-history-symbol
17 ;;;; file-history-symbol
18 ;;;; buffer-history-symbol
19 ;;;; buffer-history-lru-order
20 ;;;; max-minibuffer-history-length
21 ;;;;
22 ;;;; and the hooks
23 ;;;;
24 ;;;; after-write-region-hook
25 ;;;; after-delete-file-hook
26
27 (require 'gmhist)
28 (provide 'gmhist-mh)
29
30 (defvar max-minibuffer-history-length 'not-implemented)
31
32 ;;;; Redefining basic Emacs functions
33
34 (defun gmhist-overwrite (fun)
35 ;; Overwrite FUN (a symbol, the name of a function) with gmhist-new-FUN.
36 ;; Save the old def of FUN in gmhist-old-FUN.
37 ;; Conventions: gmhist-FUN emulates FUN, but with history.
38 ;; gmhist-new-FUN may take additional care of the case
39 ;; that history is disabled before calling gmhist-FUN
40 ;; to do the real work.
41 (let* ((fun-name (symbol-name fun))
42 (old-name (intern (concat "gmhist-old-" fun-name)))
43 (new-name (intern (concat "gmhist-new-" fun-name))))
44 (or (fboundp old-name)
45 (fset old-name (symbol-function fun)))
46 (fset fun new-name)))
47
48 ;;; Minibuffer history (not specialized like file or buffer history)
49
50 ;;; Should perhaps modify minibuffer keymaps directly:
51 ;;; minibuffer-local-completion-map
52 ;;; minibuffer-local-map
53 ;;; minibuffer-local-must-match-map
54 ;;; minibuffer-local-ns-map
55
56 (defun gmhist-new-read-string (gnrs-prompt &optional initial-input)
57 "Read a string from the minibuffer, prompting with string PROMPT.
58 If non-nil second arg INITIAL-INPUT is a string to insert before reading.
59 See also `minibuffer-history-symbol'."
60 (if minibuffer-history-symbol
61 (gmhist-read-from-minibuffer gnrs-prompt initial-input gmhist-map)
62 (gmhist-old-read-string gnrs-prompt initial-input)))
63
64 (gmhist-overwrite 'read-string)
65
66 (defun gmhist-new-completing-read
67 (gncr-prompt table &optional predicate mustmatch initial)
68 "Read a string in the minibuffer, with completion and history.
69 Args are PROMPT, TABLE, PREDICATE, REQUIRE-MATCH and INITIAL-INPUT.
70 PROMPT is a string to prompt with; normally it ends in a colon and a space.
71 TABLE is an alist whose elements' cars are strings, or an obarray (see
72 try-completion).
73 PREDICATE limits completion to a subset of TABLE see try-completion
74 for details.
75 If REQUIRE-MATCH is non-nil, the user is not allowed to exit unless
76 the input is (or completes to) an element of TABLE.
77 If it is also not t, Return does not exit if it does non-null completion.
78 If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.
79 Case is ignored if ambient value of completion-ignore-case is non-nil.
80
81 *** This is the gmhist version ***
82 See variable `minibuffer-history-symbol'."
83 (if minibuffer-history-symbol
84 (gmhist-completing-read gncr-prompt table predicate mustmatch initial)
85 (gmhist-old-completing-read gncr-prompt table predicate mustmatch initial)))
86
87 (gmhist-overwrite 'completing-read)
88
89 ;;; File history
90
91 (defvar file-history (get file-history-symbol 'initial-hist)
92 "Default history of file names read with read-file-name.
93 This symbol is the default value of file-history-symbol (q.v.).")
94
95 (defvar insert-file-default nil
96 "*If non-nil, defaults for filenames will be inserted into the
97 minibuffer prompt. This has the advantage of putting the default onto
98 the file-history (which see).")
99
100 (defun gmhist-new-read-file-name (gnrfn-prompt
101 &optional dir default mustmatch initial)
102 "Read file name, maintaining history in value of
103 file-history-symbol, prompting with PROMPT, completing in directory DIR.
104
105 Value is not expanded! You must call expand-file-name yourself.
106
107 Default name to third arg DEFAULT if user enters a null string.
108 \(If DEFAULT is omitted, the visited file name is used.)
109
110 Fourth arg MUSTMATCH non-nil means require existing file's name.
111 Non-nil and non-t means also require confirmation after completion.
112
113 Fifth arg INITIAL specifies text to start with.
114 DIR defaults to current buffer's default-directory.
115
116 *** This is the gmhist version ***
117
118 It differs from the original read-file-name in providing a
119 history of filenames in the variable whose name is the value of
120 file-history-symbol (usually 'file-history) (both of which see).
121
122 INITIAL defaults to default-directory's value if
123 insert-default-directory is non-nil. Also, if insert-file-default is
124 non-nil, it inserts the DEFAULT string if no INITIAL is given, which
125 has the advantage of putting the default onto the file-history.
126 However, setting INITIAL to a string is a way for providing an
127 editable default, something not possible with (pre Emacs-19)
128 read-file-name. Setting INITIAL and insert-default-directory to nil
129 will yield a basename for the file, relative to default-directory.
130
131 See function read-with-history-in for a list of properties you can put
132 on file-history-symbol."
133 (if (null file-history-symbol)
134 (gmhist-old-read-file-name gnrfn-prompt dir default mustmatch)
135 (gmhist-read-file-name gnrfn-prompt dir default mustmatch
136 (if (and insert-file-default
137 (not initial))
138 default
139 initial))))
140
141 ;; It is a shame that none of the standard hooks are defvar'd!
142 ;; Also, the coexistence of `hooks' vs `hook' is annoying.
143 ;; The singular seems to be the majority, so I'll use that.
144
145 (defvar after-write-region-hook nil
146 "Run after the gmhist version of `write-region'.
147 The variables `start', `end', `filename', `append', `visit' are bound
148 around the call to the hook.")
149
150 ;; Don't use &rest args, as the hook may want to take advantage of our
151 ;; arglist.
152 (defun gmhist-new-write-region (start end filename
153 &optional append visit)
154 "Write current region into specified file.
155 When called from a program, takes three arguments:
156 START, END and FILENAME. START and END are buffer positions.
157 Optional fourth argument APPEND if non-nil means
158 append to existing file contents (if any).
159 Optional fifth argument VISIT if t means
160 set last-save-file-modtime of buffer to this file's modtime
161 and mark buffer not modified.
162 If VISIT is neither t nor nil, it means do not print
163 the \"Wrote file\" message.
164
165 *** This is the gmhist version ***
166 See variable `after-write-region-hook'."
167 (interactive "r\nFWrite region to file: ")
168 (prog1
169 (gmhist-old-write-region start end filename append visit)
170 (condition-case err
171 ;; basic-save-buffer would assume an error to mean
172 ;; write-region failed
173 (run-hooks 'after-write-region-hook)
174 (error (message "Error in after-write-region-hook %s" err)
175 (sit-for 1)))))
176
177 (defvar after-delete-file-hook nil
178 "Run after the gmhist version of `delete-file'.
179 The hook is run with `filename' bound to the filename.")
180
181 (defun gmhist-new-delete-file (filename)
182 "Delete specified file. One argument, a file name string.
183 If file has multiple names, it continues to exist with the other names.
184
185 *** This is the gmhist version ***
186 See variable `after-delete-file-hook'."
187 (interactive "fDelete file: ")
188 (prog1
189 (gmhist-old-delete-file filename)
190 (condition-case err
191 ;; We don't want callers to assume an error in the hook to
192 ;; mean delete-file failed - or do we?
193 (run-hooks 'after-delete-file-hook)
194 (error (message "Error in after-delete-file-hook %s" err)
195 (sit-for 1)))))
196
197 (gmhist-overwrite 'read-file-name)
198 (gmhist-overwrite 'write-region)
199 (gmhist-overwrite 'delete-file)
200
201 ;; Redefining read-file-name does not suffice as interactive "f"
202 ;; calls the C version of read-file-name.
203 ;; gmhist-interactive of gmhist.el,v 4.4 and later understands the
204 ;; indirection from file-history-symbol to 'file-history (or whatever
205 ;; the current value may be).
206 (gmhist-make-magic 'find-file 'file-history-symbol)
207 (gmhist-make-magic 'find-file-other-window 'file-history-symbol)
208 (gmhist-make-magic 'find-file-read-only 'file-history-symbol)
209 (gmhist-make-magic 'insert-file 'file-history-symbol)
210 (gmhist-make-magic 'load-file 'file-history-symbol)
211 (gmhist-make-magic 'set-visited-file-name 'file-history-symbol)
212 (gmhist-make-magic 'append-to-file 'file-history-symbol)
213 ;; write-region is wrapped by gmhist, no longer a subr, thus this works:
214 (gmhist-make-magic 'write-region 'file-history-symbol)
215 ;; ditto for delete-file:
216 (gmhist-make-magic 'delete-file 'file-history-symbol)
217 (if gmhist-emacs-19-p
218 ;; In Emacs 19, these call the redefined read-file-name inside
219 ;; interactive, so we don't need to do anything
220 nil
221 (gmhist-make-magic 'write-file 'file-history-symbol)
222 (gmhist-make-magic 'find-alternate-file 'file-history-symbol))
223
224
225 ;;; Buffer history
226
227 (defvar buffer-history-lru-order nil
228 "*If non-nil, the buffer history will be the complete buffer
229 list in most recently used order (as returned by buffer-list).
230
231 Usually, the buffer history is in the order entered using read-buffer.")
232
233 (defvar buffer-history (get 'buffer-history 'initial-hist)
234 "History of all buffer names read with read-buffer.")
235
236 (defun gmhist-new-read-buffer (gnrb-prompt &optional default existing)
237 "One arg PROMPT, a string. Read the name of a buffer and return as a string.
238 Prompts with PROMPT.
239 Optional second arg is value to return if user enters an empty line.
240 If optional third arg REQUIRE-MATCH is non-nil, only existing buffer names are allowed.
241
242 *** This is the gmhist version ***
243
244 See variables `buffer-history-symbol' and `buffer-history-lru-order'."
245 (if (and buffer-history-symbol
246 buffer-history-lru-order)
247 (set buffer-history-symbol
248 (mapcar (function buffer-name) (buffer-list))))
249 (gmhist-read-buffer gnrb-prompt default existing))
250
251 (defun gmhist-new-switch-to-buffer (buffer &optional norecord)
252 "Select buffer BUFFER in the current window.
253 BUFFER may be a buffer or a buffer name.
254 Optional second arg NORECORD non-nil means
255 do not put this buffer at the front of the list of recently selected ones.
256
257 WARNING: This is NOT the way to work on another buffer temporarily
258 within a Lisp program! Use `set-buffer' instead. That avoids messing with
259 the window-buffer correspondences.
260
261 *** This is the gmhist version ***
262
263 It adds buffer-history to switch-to-buffer."
264 (interactive
265 ;; should perhaps bypass gmhist if NORECORD is given?
266 (list (gmhist-new-read-buffer "Switch to buffer: " (other-buffer) nil)))
267 (gmhist-old-switch-to-buffer buffer norecord))
268
269 (gmhist-overwrite 'read-buffer)
270 ;; switch-to-buffer is a subr:
271 (gmhist-overwrite 'switch-to-buffer)
272 ;; Redefining read-buffer does not suffice as interactive "b"
273 ;; calls the C version of read-buffer.
274 ;; gmhist-interactive of gmhist.el,v 4.4 and later understands the
275 ;; indirection from buffer-history-symbol to 'buffer-history (or
276 ;; whatever the current value may be).
277 (mapcar (function (lambda (fun)
278 (gmhist-make-magic fun 'buffer-history-symbol)))
279 '(switch-to-buffer-other-window ; files.el
280 append-to-buffer ; the rest from simple.el
281 prepend-to-buffer
282 copy-to-buffer))
283
284
285 ;;; read-from-minibuffer
286 ;;; saved and defined in gmhist.el, just need to overwrite:
287
288 (fset 'read-from-minibuffer 'gmhist-new-read-from-minibuffer)
289
290 ;; Now that we've redefined read-from-minibuffer we need to make sure
291 ;; that repeat-complex-command (C-x ESC), which calls
292 ;; read-from-minibuffer, adds the command to command-history and not
293 ;; to the ambient value of minibuffer-history-symbol. The latter
294 ;; could be confusing if e.g. inside a C-x C-f a C-x ESC is done (with
295 ;; enable-recursive-minibuffers t): it would add a command to the
296 ;; file-history.
297
298 ;(defun repeat-complex-command (repeat-complex-command-arg)
299 ; "Edit and re-evaluate last complex command, or ARGth from last.
300 ;A complex command is one which used the minibuffer.
301 ;The command is placed in the minibuffer as a Lisp form for editing.
302 ;The result is executed, repeating the command as changed.
303 ;If the command has been changed or is not the most recent previous command
304 ;it is added to the front of the command history.
305 ;Whilst editing the command, the following commands are available:
306 ;\\{repeat-complex-command-map}"
307 ; (interactive "p")
308 ; (let ((elt (nth (1- repeat-complex-command-arg) command-history))
309 ; newcmd)
310 ; (if elt
311 ; (progn
312 ; (setq newcmd
313 ; (let ((minibuffer-history-symbol nil))
314 ; ;; Don't let gmhist interfere with command-history.
315 ; ;; command-history is special because it's builtin to M-x.
316 ; ;; Also, gmhist would store commands as strings, not
317 ; ;; as s-exprs.
318 ; ;; When gmhist is implemented in C, M-x must be
319 ; ;; fixed to store strings, too.
320 ; (read-from-minibuffer "Redo: "
321 ; (prin1-to-string elt)
322 ; repeat-complex-command-map
323 ; t)))
324 ; ;; If command to be redone does not match front of history,
325 ; ;; add it to the history.
326 ; (or (equal newcmd (car command-history))
327 ; (setq command-history (cons newcmd command-history)))
328 ; (eval newcmd))
329 ; (ding))))
330
331 ;; Actually, it's easier to just use the gmhist re-implementation instead
332 (define-key ctl-x-map "\e" 'gmhist-repeat-complex-command)
333
334 (defun gmhist-repeat-complex-command (arg) ; C-x ESC
335 ;; This function from Mike Williams <Mike.Williams@comp.vuw.ac.nz>
336 "Edit and re-evaluate last complex command, or ARGth from last.
337 A complex command is one which used the minibuffer.
338 The command is placed in the minibuffer as a Lisp form for editing.
339 The result is executed, repeating the command as changed.
340 If the command has been changed or is not the most recent previous command
341 it is added to the front of the command history."
342 (interactive "p")
343 (let ((print-escape-newlines t))
344 (put 'command-history 'backup arg)
345 (put 'command-history 'cursor-end t)
346 (eval (read-with-history-in 'command-history "Redo: " nil 'lisp))
347 (put 'command-history 'backup nil)))
348
349 ;; TODO:
350 ;; read-minibuffer
351 ;; eval-minibuffer
352 ;; read-no-blanks-input
353 ;; read-command
354 ;; read-variable