comparison lisp/minibuf.el @ 209:41ff10fd062f r20-4b3

Import from CVS: tag r20-4b3
author cvs
date Mon, 13 Aug 2007 10:04:58 +0200
parents
children 1f0dabaa0855
comparison
equal deleted inserted replaced
208:f427b8ec4379 209:41ff10fd062f
1 ;;; minibuf.el --- Minibuffer functions for XEmacs
2
3 ;; Copyright (C) 1992, 1993, 1994, 1997 Free Software Foundation, Inc.
4 ;; Copyright (C) 1995 Tinker Systems
5 ;; Copyright (C) 1995, 1996 Ben Wing
6
7 ;; Author: Richard Mlynarik
8 ;; Created: 2-Oct-92
9 ;; Maintainer: XEmacs Development Team
10 ;; Keywords: internal, dumped
11
12 ;; This file is part of XEmacs.
13
14 ;; XEmacs is free software; you can redistribute it and/or modify it
15 ;; under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; any later version.
18
19 ;; XEmacs is distributed in the hope that it will be useful, but
20 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 ;; General Public License for more details.
23
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with XEmacs; see the file COPYING. If not, write to the
26 ;; Free Software Foundation, 59 Temple Place - Suite 330,
27 ;; Boston, MA 02111-1307, USA.
28
29 ;;; Synched up with: all the minibuffer history stuff is synched with
30 ;;; 19.30. Not sure about the rest.
31
32 ;;; Commentary:
33
34 ;; This file is dumped with XEmacs.
35
36 ;; Written by Richard Mlynarik 2-Oct-92
37
38 ;; 06/11/1997 - Use char-(after|before) instead of
39 ;; (following|preceding)-char. -slb
40
41 ;;; Code:
42
43 (defgroup minibuffer nil
44 "Minibuffer customizations"
45 :group 'environment)
46
47
48 (defcustom insert-default-directory t
49 "*Non-nil means when reading a filename start with default dir in minibuffer."
50 :type 'boolean
51 :group 'minibuffer)
52
53 (defcustom minibuffer-history-uniquify t
54 "*Non-nil means when adding an item to a minibuffer history, remove
55 previous occurances of the same item from the history list first,
56 rather than just consing the new element onto the front of the list."
57 :type 'boolean
58 :group 'minibuffer)
59
60 (defvar minibuffer-completion-table nil
61 "Alist or obarray used for completion in the minibuffer.
62 This becomes the ALIST argument to `try-completion' and `all-completions'.
63
64 The value may alternatively be a function, which is given three arguments:
65 STRING, the current buffer contents;
66 PREDICATE, the predicate for filtering possible matches;
67 CODE, which says what kind of things to do.
68 CODE can be nil, t or `lambda'.
69 nil means to return the best completion of STRING, nil if there is none,
70 or t if it is was already a unique completion.
71 t means to return a list of all possible completions of STRING.
72 `lambda' means to return t if STRING is a valid completion as it stands.")
73
74 (defvar minibuffer-completion-predicate nil
75 "Within call to `completing-read', this holds the PREDICATE argument.")
76
77 (defvar minibuffer-completion-confirm nil
78 "Non-nil => demand confirmation of completion before exiting minibuffer.")
79
80 (defvar minibuffer-confirm-incomplete nil
81 "If true, then in contexts where completing-read allows answers which
82 are not valid completions, an extra RET must be typed to confirm the
83 response. This is helpful for catching typos, etc.")
84
85 (defcustom completion-auto-help t
86 "*Non-nil means automatically provide help for invalid completion input."
87 :type 'boolean
88 :group 'minibuffer)
89
90 (defcustom enable-recursive-minibuffers nil
91 "*Non-nil means to allow minibuffer commands while in the minibuffer.
92 More precisely, this variable makes a difference when the minibuffer window
93 is the selected window. If you are in some other window, minibuffer commands
94 are allowed even if a minibuffer is active."
95 :type 'boolean
96 :group 'minibuffer)
97
98 (defcustom minibuffer-max-depth 1
99 ;; See comment in #'minibuffer-max-depth-exceeded
100 "*Global maximum number of minibuffers allowed;
101 compare to enable-recursive-minibuffers, which is only consulted when the
102 minibuffer is reinvoked while it is the selected window."
103 :type '(choice integer
104 (const :tag "Indefinite" nil))
105 :group 'minibuffer)
106
107 ;; Moved to C. The minibuffer prompt must be setup before this is run
108 ;; and that can only be done from the C side.
109 ;(defvar minibuffer-setup-hook nil
110 ; "Normal hook run just after entry to minibuffer.")
111
112 (defvar minibuffer-exit-hook nil
113 "Normal hook run just after exit from minibuffer.")
114
115 (defvar minibuffer-help-form nil
116 "Value that `help-form' takes on inside the minibuffer.")
117
118 (defvar minibuffer-local-map
119 (let ((map (make-sparse-keymap 'minibuffer-local-map)))
120 map)
121 "Default keymap to use when reading from the minibuffer.")
122
123 (defvar minibuffer-local-completion-map
124 (let ((map (make-sparse-keymap 'minibuffer-local-completion-map)))
125 (set-keymap-parents map (list minibuffer-local-map))
126 map)
127 "Local keymap for minibuffer input with completion.")
128
129 (defvar minibuffer-local-must-match-map
130 (let ((map (make-sparse-keymap 'minibuffer-must-match-map)))
131 (set-keymap-parents map (list minibuffer-local-completion-map))
132 map)
133 "Local keymap for minibuffer input with completion, for exact match.")
134
135 ;; (define-key minibuffer-local-map "\C-g" 'abort-recursive-edit)
136 (define-key minibuffer-local-map "\C-g" 'minibuffer-keyboard-quit) ;; moved here from pending-del.el
137 (define-key minibuffer-local-map "\r" 'exit-minibuffer)
138 (define-key minibuffer-local-map "\n" 'exit-minibuffer)
139
140 ;; Historical crock. Unused by anything but user code, if even that
141 ;(defvar minibuffer-local-ns-map
142 ; (let ((map (make-sparse-keymap 'minibuffer-local-ns-map)))
143 ; (set-keymap-parents map (list minibuffer-local-map))
144 ; map)
145 ; "Local keymap for the minibuffer when spaces are not allowed.")
146 ;(define-key minibuffer-local-ns-map [space] 'exit-minibuffer)
147 ;(define-key minibuffer-local-ns-map [tab] 'exit-minibuffer)
148 ;(define-key minibuffer-local-ns-map [?\?] 'self-insert-and-exit)
149
150 (define-key minibuffer-local-completion-map "\t" 'minibuffer-complete)
151 (define-key minibuffer-local-completion-map " " 'minibuffer-complete-word)
152 (define-key minibuffer-local-completion-map "?" 'minibuffer-completion-help)
153 (define-key minibuffer-local-must-match-map "\r" 'minibuffer-complete-and-exit)
154 (define-key minibuffer-local-must-match-map "\n" 'minibuffer-complete-and-exit)
155
156 (define-key minibuffer-local-map "\M-n" 'next-history-element)
157 (define-key minibuffer-local-map "\M-p" 'previous-history-element)
158 (define-key minibuffer-local-map '[next] "\M-n")
159 (define-key minibuffer-local-map '[prior] "\M-p")
160 (define-key minibuffer-local-map "\M-r" 'previous-matching-history-element)
161 (define-key minibuffer-local-map "\M-s" 'next-matching-history-element)
162 (define-key minibuffer-local-must-match-map [next]
163 'next-complete-history-element)
164 (define-key minibuffer-local-must-match-map [prior]
165 'previous-complete-history-element)
166
167 ;; This is an experiment--make up and down arrows do history.
168 (define-key minibuffer-local-map [up] 'previous-history-element)
169 (define-key minibuffer-local-map [down] 'next-history-element)
170 (define-key minibuffer-local-completion-map [up] 'previous-history-element)
171 (define-key minibuffer-local-completion-map [down] 'next-history-element)
172 (define-key minibuffer-local-must-match-map [up] 'previous-history-element)
173 (define-key minibuffer-local-must-match-map [down] 'next-history-element)
174
175 (defvar read-expression-map (let ((map (make-sparse-keymap
176 'read-expression-map)))
177 (set-keymap-parents map
178 (list minibuffer-local-map))
179 (define-key map "\M-\t" 'lisp-complete-symbol)
180 map)
181 "Minibuffer keymap used for reading Lisp expressions.")
182
183 (defvar read-shell-command-map
184 (let ((map (make-sparse-keymap 'read-shell-command-map)))
185 (set-keymap-parents map (list minibuffer-local-map))
186 (define-key map "\t" 'comint-dynamic-complete)
187 (define-key map "\M-\t" 'comint-dynamic-complete)
188 (define-key map "\M-?" 'comint-dynamic-list-completions)
189 map)
190 "Minibuffer keymap used by shell-command and related commands.")
191
192 (defcustom use-dialog-box t
193 "*Variable controlling usage of the dialog box.
194 If nil, the dialog box will never be used, even in response to mouse events."
195 :type 'boolean
196 :group 'minibuffer)
197
198 (defcustom minibuffer-electric-file-name-behavior t
199 "*If non-nil, slash and tilde in certain places cause immediate deletion.
200 These are the same places where this behavior would occur later on anyway,
201 in `substitute-in-file-name'."
202 :type 'boolean
203 :group 'minibuffer)
204
205 (defun minibuffer-electric-slash ()
206 ;; by Stig@hackvan.com
207 (interactive)
208 (and minibuffer-electric-file-name-behavior
209 (eq ?/ (char-before (point)))
210 (not (save-excursion
211 (goto-char (point-min))
212 (and (looking-at "^/.+:~?")
213 (re-search-forward "^/.+:~?[^/]*" nil t)
214 (progn
215 (delete-region (point) (point-max))
216 t))))
217 (not (eq (point) (1+ (point-min)))) ; permit `//hostname/path/to/file'
218 (not (eq ?: (char-after (- (point) 2)))) ; permit `http://url/goes/here'
219 (delete-region (point-min) (point)))
220 (insert ?/))
221
222 (defun minibuffer-electric-tilde ()
223 (interactive)
224 (and minibuffer-electric-file-name-behavior
225 (eq ?/ (char-before (point)))
226 ;; permit URL's with //, for e.g. http://hostname/~user
227 (not (save-excursion (search-backward "//" nil t)))
228 (delete-region (point-min) (point)))
229 (insert ?~))
230
231 (defvar read-file-name-map
232 (let ((map (make-sparse-keymap 'read-file-name-map)))
233 (set-keymap-parents map (list minibuffer-local-completion-map))
234 (define-key map "/" 'minibuffer-electric-slash)
235 (define-key map "~" 'minibuffer-electric-tilde)
236 map
237 ))
238
239 (defvar read-file-name-must-match-map
240 (let ((map (make-sparse-keymap 'read-file-name-map)))
241 (set-keymap-parents map (list minibuffer-local-must-match-map))
242 (define-key map "/" 'minibuffer-electric-slash)
243 (define-key map "~" 'minibuffer-electric-tilde)
244 map
245 ))
246
247 (defun minibuffer-keyboard-quit ()
248 "Abort recursive edit.
249 If `zmacs-regions' is true, and the zmacs region is active in this buffer,
250 then this key deactivates the region without beeping."
251 (interactive)
252 (if (and (region-active-p)
253 (eq (current-buffer) (zmacs-region-buffer)))
254 ;; pseudo-zmacs compatibility: don't beep if this ^G is simply
255 ;; deactivating the region. If it is inactive, beep.
256 nil
257 (abort-recursive-edit)))
258
259 ;;;; Guts of minibuffer invocation
260
261 ;;#### The only things remaining in C are
262 ;; "Vminibuf_prompt" and the display junk
263 ;; "minibuf_prompt_width" and "minibuf_prompt_pix_width"
264 ;; Also "active_frame", though I suspect I could already
265 ;; hack that in Lisp if I could make any sense of the
266 ;; complete mess of frame/frame code in XEmacs.
267 ;; Vminibuf_prompt could easily be made Lisp-bindable.
268 ;; I suspect that minibuf_prompt*_width are actually recomputed
269 ;; by redisplay as needed -- or could be arranged to be so --
270 ;; and that there could be need for read-minibuffer-internal to
271 ;; save and restore them.
272 ;;#### The only other thing which read-from-minibuffer-internal does
273 ;; which we can't presently do in Lisp is move the frame cursor
274 ;; to the start of the minibuffer line as it returns. This is
275 ;; a rather nice touch and should be preserved -- probably by
276 ;; providing some Lisp-level mechanism (extension to cursor-in-echo-area ?)
277 ;; to effect it.
278
279
280 ;; Like reset_buffer in FSF's buffer.c
281 ;; (Except that kill-all-local-variables doesn't nuke 'permanent-local
282 ;; variables -- we preserve them, reset_buffer doesn't.)
283 (defun reset-buffer (buffer)
284 (with-current-buffer buffer
285 ;(if (fboundp 'unlock-buffer) (unlock-buffer))
286 (kill-all-local-variables)
287 (setq buffer-read-only nil)
288 (erase-buffer)
289 ;(setq default-directory nil)
290 (setq buffer-file-name nil)
291 (setq buffer-file-truename nil)
292 (set-buffer-modified-p nil)
293 (setq buffer-backed-up nil)
294 (setq buffer-auto-save-file-name nil)
295 (set-buffer-dedicated-frame buffer nil)
296 buffer))
297
298 (defvar minibuffer-history-variable 'minibuffer-history
299 "History list symbol to add minibuffer values to.
300 Each minibuffer output is added with
301 (set minibuffer-history-variable
302 (cons STRING (symbol-value minibuffer-history-variable)))")
303 (defvar minibuffer-history-position)
304
305 ;; Added by hniksic:
306 (defvar initial-minibuffer-history-position)
307 (defvar current-minibuffer-contents)
308 (defvar current-minibuffer-point)
309
310 (defcustom minibuffer-history-minimum-string-length 3
311 "*If this variable is non-nil, a string will not be added to the
312 minibuffer history if its length is less than that value."
313 :type '(choice (const :tag "Any" nil)
314 integer)
315 :group 'minibuffer)
316
317 (define-error 'input-error "Keyboard input error")
318
319 (put 'input-error 'display-error
320 #'(lambda (error-object stream)
321 (princ (cadr error-object) stream)))
322
323 (defun read-from-minibuffer (prompt &optional initial-contents
324 keymap
325 readp
326 history
327 abbrev-table)
328 "Read a string from the minibuffer, prompting with string PROMPT.
329 If optional second arg INITIAL-CONTENTS is non-nil, it is a string
330 to be inserted into the minibuffer before reading input.
331 If INITIAL-CONTENTS is (STRING . POSITION), the initial input
332 is STRING, but point is placed POSITION characters into the string.
333 Third arg KEYMAP is a keymap to use whilst reading;
334 if omitted or nil, the default is `minibuffer-local-map'.
335 If fourth arg READ is non-nil, then interpret the result as a lisp object
336 and return that object:
337 in other words, do `(car (read-from-string INPUT-STRING))'
338 Fifth arg HISTORY, if non-nil, specifies a history list
339 and optionally the initial position in the list.
340 It can be a symbol, which is the history list variable to use,
341 or it can be a cons cell (HISTVAR . HISTPOS).
342 In that case, HISTVAR is the history list variable to use,
343 and HISTPOS is the initial position (the position in the list
344 which INITIAL-CONTENTS corresponds to).
345 If HISTORY is `t', no history will be recorded.
346 Positions are counted starting from 1 at the beginning of the list.
347 Sixth arg ABBREV-TABLE, if non-nil, becomes the value of `local-abbrev-table'
348 in the minibuffer.
349
350 See also the variable completion-highlight-first-word-only for control over
351 completion display."
352 (if (and (not enable-recursive-minibuffers)
353 (> (minibuffer-depth) 0)
354 (eq (selected-window) (minibuffer-window)))
355 (error "Command attempted to use minibuffer while in minibuffer"))
356
357 (if (and minibuffer-max-depth
358 (> minibuffer-max-depth 0)
359 (>= (minibuffer-depth) minibuffer-max-depth))
360 (minibuffer-max-depth-exceeded))
361
362 ;; catch this error before the poor user has typed something...
363 (if history
364 (if (symbolp history)
365 (or (boundp history)
366 (error "History list %S is unbound" history))
367 (or (boundp (car history))
368 (error "History list %S is unbound" (car history)))))
369
370 (if (noninteractive)
371 (progn
372 ;; XEmacs in -batch mode calls minibuffer: print the prompt.
373 (message "%s" (gettext prompt))
374 ;;#### force-output
375
376 ;;#### Should this even be falling though to the code below?
377 ;;#### How does this stuff work now, anyway?
378 ))
379 (let* ((dir default-directory)
380 (owindow (selected-window))
381 (oframe (selected-frame))
382 (window (minibuffer-window))
383 (buffer (if (eq (minibuffer-depth) 0)
384 (window-buffer window)
385 (get-buffer-create (format " *Minibuf-%d"
386 (minibuffer-depth)))))
387 (frame (window-frame window))
388 (mconfig (if (eq frame (selected-frame))
389 nil (current-window-configuration frame)))
390 (oconfig (current-window-configuration))
391 ;; dynamic scope sucks sucks sucks sucks sucks sucks.
392 ;; `M-x doctor' makes history a local variable, and thus
393 ;; our binding above is buffer-local and doesn't apply
394 ;; once we switch buffers!!!! We demand better scope!
395 (_history_ history))
396 (unwind-protect
397 (progn
398 (set-buffer (reset-buffer buffer))
399 (setq default-directory dir)
400 (make-local-variable 'print-escape-newlines)
401 (setq print-escape-newlines t)
402 (make-local-variable 'current-minibuffer-contents)
403 (make-local-variable 'current-minibuffer-point)
404 (make-local-variable 'initial-minibuffer-history-position)
405 (setq current-minibuffer-contents ""
406 current-minibuffer-point 1)
407 (if (not minibuffer-smart-completion-tracking-behavior)
408 nil
409 (make-local-variable 'mode-motion-hook)
410 (or mode-motion-hook
411 ;;####disgusting
412 (setq mode-motion-hook 'minibuffer-smart-mouse-tracker))
413 (make-local-variable 'mouse-track-click-hook)
414 (add-hook 'mouse-track-click-hook
415 'minibuffer-smart-maybe-select-highlighted-completion))
416 (set-window-buffer window buffer)
417 (select-window window)
418 (set-window-hscroll window 0)
419 (buffer-enable-undo buffer)
420 (message nil)
421 (if initial-contents
422 (if (consp initial-contents)
423 (progn
424 (insert (car initial-contents))
425 (goto-char (1+ (cdr initial-contents)))
426 (setq current-minibuffer-contents (car initial-contents)
427 current-minibuffer-point (cdr initial-contents)))
428 (insert initial-contents)
429 (setq current-minibuffer-contents initial-contents
430 current-minibuffer-point (point))))
431 (use-local-map (or keymap minibuffer-local-map))
432 (let ((mouse-grabbed-buffer
433 (and minibuffer-smart-completion-tracking-behavior
434 (current-buffer)))
435 (current-prefix-arg current-prefix-arg)
436 (help-form minibuffer-help-form)
437 (minibuffer-history-variable (cond ((not _history_)
438 'minibuffer-history)
439 ((consp _history_)
440 (car _history_))
441 (t
442 _history_)))
443 (minibuffer-history-position (cond ((consp _history_)
444 (cdr _history_))
445 (t
446 0)))
447 (minibuffer-scroll-window owindow))
448 (setq initial-minibuffer-history-position
449 minibuffer-history-position)
450 (if abbrev-table
451 (setq local-abbrev-table abbrev-table
452 abbrev-mode t))
453 ;; This is now run from read-minibuffer-internal
454 ;(if minibuffer-setup-hook
455 ; (run-hooks 'minibuffer-setup-hook))
456 ;(message nil)
457 (if (eq 't
458 (catch 'exit
459 (if (> (recursion-depth) (minibuffer-depth))
460 (let ((standard-output t)
461 (standard-input t))
462 (read-minibuffer-internal prompt))
463 (read-minibuffer-internal prompt))))
464 ;; Translate an "abort" (throw 'exit 't)
465 ;; into a real quit
466 (signal 'quit '())
467 ;; return value
468 (let* ((val (progn (set-buffer buffer)
469 (if minibuffer-exit-hook
470 (run-hooks 'minibuffer-exit-hook))
471 (buffer-string)))
472 (histval val)
473 (err nil))
474 (if readp
475 (condition-case e
476 (let ((v (read-from-string val)))
477 (if (< (cdr v) (length val))
478 (save-match-data
479 (or (string-match "[ \t\n]*\\'" val (cdr v))
480 (error "Trailing garbage following expression"))))
481 (setq v (car v))
482 ;; total total kludge
483 (if (stringp v) (setq v (list 'quote v)))
484 (setq val v))
485 (end-of-file
486 (setq err
487 '(input-error "End of input before end of expression")))
488 (error (setq err e))))
489 ;; Add the value to the appropriate history list unless
490 ;; it's already the most recent element, or it's only
491 ;; two characters long.
492 (if (and (symbolp minibuffer-history-variable)
493 (boundp minibuffer-history-variable))
494 (let ((list (symbol-value minibuffer-history-variable)))
495 (or (eq list t)
496 (null val)
497 (and list (equal histval (car list)))
498 (and (stringp val)
499 minibuffer-history-minimum-string-length
500 (< (length val)
501 minibuffer-history-minimum-string-length))
502 (set minibuffer-history-variable
503 (if minibuffer-history-uniquify
504 (cons histval (remove histval list))
505 (cons histval list))))))
506 (if err (signal (car err) (cdr err)))
507 val))))
508 ;; stupid display code requires this for some reason
509 (set-buffer buffer)
510 (buffer-disable-undo buffer)
511 (setq buffer-read-only nil)
512 (erase-buffer)
513
514 ;; restore frame configurations
515 (if (and mconfig (frame-live-p oframe)
516 (eq frame (selected-frame)))
517 ;; if we changed frames (due to surrogate minibuffer),
518 ;; and we're still on the new frame, go back to the old one.
519 (select-frame oframe))
520 (if mconfig (set-window-configuration mconfig))
521 (set-window-configuration oconfig))))
522
523
524 (defun minibuffer-max-depth-exceeded ()
525 ;;
526 ;; This signals an error if an Nth minibuffer is invoked while N-1 are
527 ;; already active, whether the minibuffer window is selected or not.
528 ;; Since, under X, it's easy to jump out of the minibuffer (by doing M-x,
529 ;; getting distracted, and clicking elsewhere) many many novice users have
530 ;; had the problem of having multiple minibuffers build up, even to the
531 ;; point of exceeding max-lisp-eval-depth. Since the variable
532 ;; enable-recursive-minibuffers historically/crockishly is only consulted
533 ;; when the minibuffer is currently active (like typing M-x M-x) it doesn't
534 ;; help in this situation.
535 ;;
536 ;; This routine also offers to edit .emacs for you to get rid of this
537 ;; complaint, like `disabled' commands do, since it's likely that non-novice
538 ;; users will be annoyed by this change, so we give them an easy way to get
539 ;; rid of it forever.
540 ;;
541 (beep t 'minibuffer-limit-exceeded)
542 (message
543 "Minibuffer already active: abort it with `^]', enable new one with `n': ")
544 (let ((char (let ((cursor-in-echo-area t)) ; #### doesn't always work??
545 (read-char))))
546 (cond
547 ((eq char ?n)
548 (cond
549 ((y-or-n-p "Enable recursive minibuffers for other sessions too? ")
550 ;; This is completely disgusting, but it's basically what novice.el
551 ;; does. This kind of thing should be generalized.
552 (setq minibuffer-max-depth nil)
553 (save-excursion
554 (set-buffer
555 (find-file-noselect
556 (substitute-in-file-name custom-file)))
557 (goto-char (point-min))
558 (if (re-search-forward
559 "^(setq minibuffer-max-depth \\([0-9]+\\|'?nil\\|'?()\\))\n"
560 nil t)
561 (delete-region (match-beginning 0 ) (match-end 0))
562 ;; Must have been disabled by default.
563 (goto-char (point-max)))
564 (insert"\n(setq minibuffer-max-depth nil)\n")
565 (save-buffer))
566 (message "Multiple minibuffers enabled")
567 (sit-for 1))))
568 ((eq char ?)
569 (abort-recursive-edit))
570 (t
571 (error "Minibuffer already active")))))
572
573
574 ;;;; Guts of minibuffer completion
575
576
577 ;; Used by minibuffer-do-completion
578 (defvar last-exact-completion)
579
580 (defun temp-minibuffer-message (m)
581 (let ((savemax (point-max)))
582 (save-excursion
583 (goto-char (point-max))
584 (message nil)
585 (insert m))
586 (let ((inhibit-quit t))
587 (sit-for 2)
588 (delete-region savemax (point-max))
589 ;; If the user types a ^G while we're in sit-for, then quit-flag
590 ;; gets set. In this case, we want that ^G to be interpreted
591 ;; as a normal character, and act just like typeahead.
592 (if (and quit-flag (not unread-command-event))
593 (setq unread-command-event (character-to-event (quit-char))
594 quit-flag nil)))))
595
596
597 ;; Determines whether buffer-string is an exact completion
598 (defun exact-minibuffer-completion-p (buffer-string)
599 (cond ((not minibuffer-completion-table)
600 ;; Empty alist
601 nil)
602 ((vectorp minibuffer-completion-table)
603 (let ((tem (intern-soft buffer-string
604 minibuffer-completion-table)))
605 (if (or tem
606 (and (string-equal buffer-string "nil")
607 ;; intern-soft loses for 'nil
608 (catch 'found
609 (mapatoms #'(lambda (s)
610 (if (string-equal
611 (symbol-name s)
612 buffer-string)
613 (throw 'found t)))
614 minibuffer-completion-table)
615 nil)))
616 (if minibuffer-completion-predicate
617 (funcall minibuffer-completion-predicate
618 tem)
619 t)
620 nil)))
621 ((and (consp minibuffer-completion-table)
622 ;;#### Emacs-Lisp truly sucks!
623 ;; lambda, autoload, etc
624 (not (symbolp (car minibuffer-completion-table))))
625 (if (not completion-ignore-case)
626 (assoc buffer-string minibuffer-completion-table)
627 (let ((s (upcase buffer-string))
628 (tail minibuffer-completion-table)
629 tem)
630 (while tail
631 (setq tem (car (car tail)))
632 (if (or (equal tem buffer-string)
633 (equal tem s)
634 (equal (upcase tem) s))
635 (setq s 'win
636 tail nil) ;exit
637 (setq tail (cdr tail))))
638 (eq s 'win))))
639 (t
640 (funcall minibuffer-completion-table
641 buffer-string
642 minibuffer-completion-predicate
643 'lambda)))
644 )
645
646 ;; 0 'none no possible completion
647 ;; 1 'unique was already an exact and unique completion
648 ;; 3 'exact was already an exact (but nonunique) completion
649 ;; NOT USED 'completed-exact-unique completed to an exact and completion
650 ;; 4 'completed-exact completed to an exact (but nonunique) completion
651 ;; 5 'completed some completion happened
652 ;; 6 'uncompleted no completion happened
653 (defun minibuffer-do-completion-1 (buffer-string completion)
654 (cond ((not completion)
655 'none)
656 ((eq completion t)
657 ;; exact and unique match
658 'unique)
659 (t
660 ;; It did find a match. Do we match some possibility exactly now?
661 (let ((completedp (not (string-equal completion buffer-string))))
662 (if completedp
663 (progn
664 ;; Some completion happened
665 (erase-buffer)
666 (insert completion)
667 (setq buffer-string completion)))
668 (if (exact-minibuffer-completion-p buffer-string)
669 ;; An exact completion was possible
670 (if completedp
671 ;; Since no callers need to know the difference, don't bother
672 ;; with this (potentially expensive) discrimination.
673 ;; (if (eq (try-completion completion
674 ;; minibuffer-completion-table
675 ;; minibuffer-completion-predicate)
676 ;; 't)
677 ;; 'completed-exact-unique
678 'completed-exact
679 ;; )
680 'exact)
681 ;; Not an exact match
682 (if completedp
683 'completed
684 'uncompleted))))))
685
686
687 (defun minibuffer-do-completion (buffer-string)
688 (let* ((completion (try-completion buffer-string
689 minibuffer-completion-table
690 minibuffer-completion-predicate))
691 (status (minibuffer-do-completion-1 buffer-string completion))
692 (last last-exact-completion))
693 (setq last-exact-completion nil)
694 (cond ((eq status 'none)
695 ;; No completions
696 (ding nil 'no-completion)
697 (temp-minibuffer-message " [No match]"))
698 ((eq status 'unique)
699 )
700 (t
701 ;; It did find a match. Do we match some possibility exactly now?
702 (if (not (string-equal completion buffer-string))
703 (progn
704 ;; Some completion happened
705 (erase-buffer)
706 (insert completion)
707 (setq buffer-string completion)))
708 (cond ((eq status 'exact)
709 ;; If the last exact completion and this one were
710 ;; the same, it means we've already given a
711 ;; "Complete but not unique" message and that the
712 ;; user's hit TAB again, so now we give help.
713 (setq last-exact-completion completion)
714 (if (equal buffer-string last)
715 (minibuffer-completion-help)))
716 ((eq status 'uncompleted)
717 (if completion-auto-help
718 (minibuffer-completion-help)
719 (temp-minibuffer-message " [Next char not unique]")))
720 (t
721 nil))))
722 status))
723
724
725 ;;;; completing-read
726
727 (defun completing-read (prompt table
728 &optional predicate require-match
729 initial-contents history)
730 "Read a string in the minibuffer, with completion.
731 Args: PROMPT, TABLE, PREDICATE, REQUIRE-MATCH, INITIAL-CONTENTS, HISTORY.
732 PROMPT is a string to prompt with; normally it ends in a colon and a space.
733 TABLE is an alist whose elements' cars are strings, or an obarray.
734 PREDICATE limits completion to a subset of TABLE.
735 See `try-completion' for more details on completion, TABLE, and PREDICATE.
736 If REQUIRE-MATCH is non-nil, the user is not allowed to exit unless
737 the input is (or completes to) an element of TABLE or is null.
738 If it is also not t, Return does not exit if it does non-null completion.
739 If INITIAL-CONTENTS is non-nil, insert it in the minibuffer initially.
740 If it is (STRING . POSITION), the initial input
741 is STRING, but point is placed POSITION characters into the string.
742 HISTORY, if non-nil, specifies a history list
743 and optionally the initial position in the list.
744 It can be a symbol, which is the history list variable to use,
745 or it can be a cons cell (HISTVAR . HISTPOS).
746 In that case, HISTVAR is the history list variable to use,
747 and HISTPOS is the initial position (the position in the list
748 which INITIAL-CONTENTS corresponds to).
749 If HISTORY is `t', no history will be recorded.
750 Positions are counted starting from 1 at the beginning of the list.
751 Completion ignores case if the ambient value of
752 `completion-ignore-case' is non-nil."
753 (let ((minibuffer-completion-table table)
754 (minibuffer-completion-predicate predicate)
755 (minibuffer-completion-confirm (if (eq require-match 't) nil t))
756 (last-exact-completion nil))
757 (read-from-minibuffer prompt
758 initial-contents
759 (if (not require-match)
760 minibuffer-local-completion-map
761 minibuffer-local-must-match-map)
762 nil
763 history)))
764
765
766 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
767 ;;;; Minibuffer completion commands ;;;;
768 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
769
770
771 (defun minibuffer-complete ()
772 "Complete the minibuffer contents as far as possible.
773 Return nil if there is no valid completion, else t.
774 If no characters can be completed, display a list of possible completions.
775 If you repeat this command after it displayed such a list,
776 scroll the window of possible completions."
777 (interactive)
778 ;; If the previous command was not this, then mark the completion
779 ;; buffer obsolete.
780 (or (eq last-command this-command)
781 (setq minibuffer-scroll-window nil))
782 (let ((window minibuffer-scroll-window))
783 (if (and window (windowp window) (window-buffer window)
784 (buffer-name (window-buffer window)))
785 ;; If there's a fresh completion window with a live buffer
786 ;; and this command is repeated, scroll that window.
787 (let ((obuf (current-buffer)))
788 (unwind-protect
789 (progn
790 (set-buffer (window-buffer window))
791 (if (pos-visible-in-window-p (point-max) window)
792 ;; If end is in view, scroll up to the beginning.
793 (set-window-start window (point-min))
794 ;; Else scroll down one frame.
795 (scroll-other-window)))
796 (set-buffer obuf))
797 nil)
798 (let ((status (minibuffer-do-completion (buffer-string))))
799 (if (eq status 'none)
800 nil
801 (progn
802 (cond ((eq status 'unique)
803 (temp-minibuffer-message
804 " [Sole completion]"))
805 ((eq status 'exact)
806 (temp-minibuffer-message
807 " [Complete, but not unique]")))
808 t))))))
809
810
811 (defun minibuffer-complete-and-exit ()
812 "Complete the minibuffer contents, and maybe exit.
813 Exit if the name is valid with no completion needed.
814 If name was completed to a valid match,
815 a repetition of this command will exit."
816 (interactive)
817 (if (= (point-min) (point-max))
818 ;; Crockishly allow user to specify null string
819 (throw 'exit nil))
820 (let ((buffer-string (buffer-string)))
821 ;; Short-cut -- don't call minibuffer-do-completion if we already
822 ;; have an (possibly nonunique) exact completion.
823 (if (exact-minibuffer-completion-p buffer-string)
824 (throw 'exit nil))
825 (let ((status (minibuffer-do-completion buffer-string)))
826 (if (or (eq status 'unique)
827 (eq status 'exact)
828 (if (or (eq status 'completed-exact)
829 (eq status 'completed-exact-unique))
830 (if minibuffer-completion-confirm
831 (progn (temp-minibuffer-message " [Confirm]")
832 nil)
833 t)))
834 (throw 'exit nil)))))
835
836
837 (defun self-insert-and-exit ()
838 "Terminate minibuffer input."
839 (interactive)
840 (self-insert-command 1)
841 (throw 'exit nil))
842
843 (defun exit-minibuffer ()
844 "Terminate this minibuffer argument.
845 If minibuffer-confirm-incomplete is true, and we are in a completing-read
846 of some kind, and the contents of the minibuffer is not an existing
847 completion, requires an additional RET before the minibuffer will be exited
848 \(assuming that RET was the character that invoked this command:
849 the character in question must be typed again)."
850 (interactive)
851 (if (not minibuffer-confirm-incomplete)
852 (throw 'exit nil))
853 (let ((buffer-string (buffer-string)))
854 (if (exact-minibuffer-completion-p buffer-string)
855 (throw 'exit nil))
856 (let ((completion (if (not minibuffer-completion-table)
857 t
858 (try-completion buffer-string
859 minibuffer-completion-table
860 minibuffer-completion-predicate))))
861 (if (or (eq completion 't)
862 ;; Crockishly allow user to specify null string
863 (string-equal buffer-string ""))
864 (throw 'exit nil))
865 (if completion ;; rewritten for I18N3 snarfing
866 (temp-minibuffer-message " [incomplete; confirm]")
867 (temp-minibuffer-message " [no completions; confirm]"))
868 (let ((event (let ((inhibit-quit t))
869 (prog1
870 (next-command-event)
871 (setq quit-flag nil)))))
872 (cond ((equal event last-command-event)
873 (throw 'exit nil))
874 ((equal (quit-char) (event-to-character event))
875 ;; Minibuffer abort.
876 (throw 'exit t)))
877 (dispatch-event event)))))
878
879 ;;;; minibuffer-complete-word
880
881
882 ;;;#### I think I have done this correctly; it certainly is simpler
883 ;;;#### than what the C code seemed to be trying to do.
884 (defun minibuffer-complete-word ()
885 "Complete the minibuffer contents at most a single word.
886 After one word is completed as much as possible, a space or hyphen
887 is added, provided that matches some possible completion.
888 Return nil if there is no valid completion, else t."
889 (interactive)
890 (let* ((buffer-string (buffer-string))
891 (completion (try-completion buffer-string
892 minibuffer-completion-table
893 minibuffer-completion-predicate))
894 (status (minibuffer-do-completion-1 buffer-string completion)))
895 (cond ((eq status 'none)
896 (ding nil 'no-completion)
897 (temp-minibuffer-message " [No match]")
898 nil)
899 ((eq status 'unique)
900 ;; New message, only in this new Lisp code
901 (temp-minibuffer-message " [Sole completion]")
902 t)
903 (t
904 (cond ((or (eq status 'uncompleted)
905 (eq status 'exact))
906 (let ((foo #'(lambda (s)
907 (condition-case nil
908 (if (try-completion
909 (concat buffer-string s)
910 minibuffer-completion-table
911 minibuffer-completion-predicate)
912 (progn
913 (goto-char (point-max))
914 (insert s)
915 t)
916 nil)
917 (error nil))))
918 (char last-command-char))
919 ;; Try to complete by adding a word-delimiter
920 (or (and (characterp char) (> char 0)
921 (funcall foo (char-to-string char)))
922 (and (not (eq char ?\ ))
923 (funcall foo " "))
924 (and (not (eq char ?\-))
925 (funcall foo "-"))
926 (progn
927 (if completion-auto-help
928 (minibuffer-completion-help)
929 ;; New message, only in this new Lisp code
930 ;; rewritten for I18N3 snarfing
931 (if (eq status 'exact)
932 (temp-minibuffer-message
933 " [Complete, but not unique]")
934 (temp-minibuffer-message " [Ambiguous]")))
935 nil))))
936 (t
937 (erase-buffer)
938 (insert completion)
939 ;; First word-break in stuff found by completion
940 (goto-char (point-min))
941 (let ((len (length buffer-string))
942 n)
943 (if (and (< len (length completion))
944 (catch 'match
945 (setq n 0)
946 (while (< n len)
947 (if (char-equal
948 (upcase (aref buffer-string n))
949 (upcase (aref completion n)))
950 (setq n (1+ n))
951 (throw 'match nil)))
952 t)
953 (progn
954 (goto-char (point-min))
955 (forward-char len)
956 (re-search-forward "\\W" nil t)))
957 (delete-region (point) (point-max))
958 (goto-char (point-max))))
959 t))))))
960
961
962 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
963 ;;;; "Smart minibuffer" hackery ;;;;
964 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
965
966 ;;; ("Kludgy minibuffer hackery" is perhaps a better name)
967
968 ;; This works by setting `mouse-grabbed-buffer' to the minibuffer,
969 ;; defining button2 in the minibuffer keymap to
970 ;; `minibuffer-smart-select-highlighted-completion', and setting the
971 ;; mode-motion-hook of the minibuffer to `minibuffer-mouse-tracker'.
972 ;; By setting `mouse-grabbed-buffer', the minibuffer's keymap and
973 ;; mode-motion-hook apply (for mouse motion and presses) no matter
974 ;; what buffer the mouse is over. Then, `minibuffer-mouse-tracker'
975 ;; examines the text under the mouse looking for something that looks
976 ;; like a completion, and causes it to be highlighted, and
977 ;; `minibuffer-smart-select-highlighted-completion' looks for a
978 ;; flagged completion under the mouse and inserts it. This has the
979 ;; following advantages:
980 ;;
981 ;; -- filenames and such in any buffer can be inserted by clicking,
982 ;; not just completions
983 ;;
984 ;; but the following disadvantages:
985 ;;
986 ;; -- unless you're aware of the "filename in any buffer" feature,
987 ;; the fact that strings in arbitrary buffers get highlighted appears
988 ;; as a bug
989 ;; -- mouse motion can cause ange-ftp actions -- bad bad bad.
990 ;;
991 ;; There's some hackery in minibuffer-mouse-tracker to try to avoid the
992 ;; ange-ftp stuff, but it doesn't work.
993 ;;
994
995 (defcustom minibuffer-smart-completion-tracking-behavior nil
996 "*If non-nil, look for completions under mouse in all buffers.
997 This allows you to click on something that looks like a completion
998 and have it selected, regardless of what buffer it is in.
999
1000 This is not enabled by default because
1001
1002 -- The \"mysterious\" highlighting in normal buffers is confusing to
1003 people not expecting it, and looks like a bug
1004 -- If ange-ftp is enabled, this tracking sometimes causes ange-ftp
1005 action as a result of mouse motion, which is *bad bad bad*.
1006 Hopefully this bug will be fixed at some point."
1007 :type 'boolean
1008 :group 'minibuffer)
1009
1010 (defun minibuffer-smart-mouse-tracker (event)
1011 ;; Used as the mode-motion-hook of the minibuffer window, which is the
1012 ;; value of `mouse-grabbed-buffer' while the minibuffer is active. If
1013 ;; the word under the mouse is a valid minibuffer completion, then it
1014 ;; is highlighted.
1015 ;;
1016 ;; We do some special voodoo when we're reading a pathname, because
1017 ;; the way filename completion works is funny. Possibly there's some
1018 ;; more general way this could be dealt with...
1019 ;;
1020 ;; We do some further voodoo when reading a pathname that is an
1021 ;; ange-ftp or efs path, because causing FTP activity as a result of
1022 ;; mouse motion is a really bad time.
1023 ;;
1024 (and minibuffer-smart-completion-tracking-behavior
1025 (event-point event)
1026 ;; avoid conflict with display-completion-list extents
1027 (not (extent-at (event-point event)
1028 (event-buffer event)
1029 'list-mode-item))
1030 (let ((filename-kludge-p (eq minibuffer-completion-table
1031 'read-file-name-internal)))
1032 (mode-motion-highlight-internal
1033 event
1034 #'(lambda () (default-mouse-track-beginning-of-word
1035 (if filename-kludge-p 'nonwhite t)))
1036 #'(lambda ()
1037 (let ((p (point))
1038 (string ""))
1039 (default-mouse-track-end-of-word
1040 (if filename-kludge-p 'nonwhite t))
1041 (if (and (/= p (point)) minibuffer-completion-table)
1042 (setq string (buffer-substring p (point))))
1043 (if (string-match "\\`[ \t\n]*\\'" string)
1044 (goto-char p)
1045 (if filename-kludge-p
1046 (setq string (minibuffer-smart-select-kludge-filename
1047 string)))
1048 ;; try-completion bogusly returns a string even when
1049 ;; that string is complete if that string is also a
1050 ;; prefix for other completions. This means that we
1051 ;; can't just do the obvious thing, (eq t
1052 ;; (try-completion ...)).
1053 (let (comp)
1054 (if (and filename-kludge-p
1055 ;; #### evil evil evil evil
1056 (or (and (fboundp 'ange-ftp-ftp-path)
1057 (ange-ftp-ftp-path string))
1058 (and (fboundp 'efs-ftp-path)
1059 (efs-ftp-path string))))
1060 (setq comp t)
1061 (setq comp
1062 (try-completion string
1063 minibuffer-completion-table
1064 minibuffer-completion-predicate)))
1065 (or (eq comp t)
1066 (and (equal comp string)
1067 (or (null minibuffer-completion-predicate)
1068 (stringp
1069 minibuffer-completion-predicate) ; ???
1070 (funcall minibuffer-completion-predicate
1071 (if (vectorp
1072 minibuffer-completion-table)
1073 (intern-soft
1074 string
1075 minibuffer-completion-table)
1076 string))))
1077 (goto-char p))))))))))
1078
1079 (defun minibuffer-smart-select-kludge-filename (string)
1080 (save-excursion
1081 (set-buffer mouse-grabbed-buffer) ; the minibuf
1082 (let ((kludge-string (concat (buffer-string) string)))
1083 (if (or (and (fboundp 'ange-ftp-ftp-path)
1084 (ange-ftp-ftp-path kludge-string))
1085 (and (fboundp 'efs-ftp-path) (efs-ftp-path kludge-string)))
1086 ;; #### evil evil evil, but more so.
1087 string
1088 (append-expand-filename (buffer-string) string)))))
1089
1090 (defun minibuffer-smart-select-highlighted-completion (event)
1091 "Select the highlighted text under the mouse as a minibuffer response.
1092 When the minibuffer is being used to prompt the user for a completion,
1093 any valid completions which are visible on the frame will highlight
1094 when the mouse moves over them. Clicking \\<minibuffer-local-map>\
1095 \\[minibuffer-smart-select-highlighted-completion] will select the
1096 highlighted completion under the mouse.
1097
1098 If the mouse is clicked while not over a highlighted completion,
1099 then the global binding of \\[minibuffer-smart-select-highlighted-completion] \
1100 will be executed instead. In this\nway you can get at the normal global \
1101 behavior of \\[minibuffer-smart-select-highlighted-completion] as well as
1102 the special minibuffer behavior."
1103 (interactive "e")
1104 (if minibuffer-smart-completion-tracking-behavior
1105 (minibuffer-smart-select-highlighted-completion-1 event t)
1106 (let ((command (lookup-key global-map
1107 (vector current-mouse-event))))
1108 (if command (call-interactively command)))))
1109
1110 (defun minibuffer-smart-select-highlighted-completion-1 (event global-p)
1111 (let* ((filename-kludge-p (eq minibuffer-completion-table
1112 'read-file-name-internal))
1113 completion
1114 command-p
1115 (evpoint (event-point event))
1116 (evextent (and evpoint (extent-at evpoint (event-buffer event)
1117 'list-mode-item))))
1118 (if evextent
1119 ;; avoid conflict with display-completion-list extents.
1120 ;; if we find one, do that behavior instead.
1121 (list-mode-item-selected-1 evextent event)
1122 (save-excursion
1123 (let* ((buffer (window-buffer (event-window event)))
1124 (p (event-point event))
1125 (extent (and p (extent-at p buffer 'mouse-face))))
1126 (set-buffer buffer)
1127 (if (not (and (extent-live-p extent)
1128 (eq (extent-object extent) (current-buffer))
1129 (not (extent-detached-p extent))))
1130 (setq command-p t)
1131 ;; ...else user has selected a highlighted completion.
1132 (setq completion
1133 (buffer-substring (extent-start-position extent)
1134 (extent-end-position extent)))
1135 (if filename-kludge-p
1136 (setq completion (minibuffer-smart-select-kludge-filename
1137 completion)))
1138 ;; remove the extent so that it's not hanging around in
1139 ;; *Completions*
1140 (detach-extent extent)
1141 (set-buffer mouse-grabbed-buffer)
1142 (erase-buffer)
1143 (insert completion))))
1144 ;; we need to execute the command or do the throw outside of the
1145 ;; save-excursion.
1146 (cond ((and command-p global-p)
1147 (let ((command (lookup-key global-map
1148 (vector current-mouse-event))))
1149 (if command
1150 (call-interactively command)
1151 (if minibuffer-completion-table
1152 (error
1153 "Highlighted words are valid completions. You may select one.")
1154 (error "no completions")))))
1155 ((not command-p)
1156 ;; things get confused if the minibuffer is terminated while
1157 ;; not selected.
1158 (select-window (minibuffer-window))
1159 (if (and filename-kludge-p (file-directory-p completion))
1160 ;; if the user clicked middle on a directory name, display the
1161 ;; files in that directory.
1162 (progn
1163 (goto-char (point-max))
1164 (minibuffer-completion-help))
1165 ;; otherwise, terminate input
1166 (throw 'exit nil)))))))
1167
1168 (defun minibuffer-smart-maybe-select-highlighted-completion
1169 (event &optional click-count)
1170 "Like minibuffer-smart-select-highlighted-completion but does nothing if
1171 there is no completion (as opposed to executing the global binding). Useful
1172 as the value of `mouse-track-click-hook'."
1173 (interactive "e")
1174 (minibuffer-smart-select-highlighted-completion-1 event nil))
1175
1176 (define-key minibuffer-local-map 'button2
1177 'minibuffer-smart-select-highlighted-completion)
1178
1179
1180 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1181 ;;;; Minibuffer History ;;;;
1182 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1183
1184 (defvar minibuffer-history '()
1185 "Default minibuffer history list.
1186 This is used for all minibuffer input except when an alternate history
1187 list is specified.")
1188
1189 ;; Some other history lists:
1190 ;;
1191 (defvar minibuffer-history-search-history '())
1192 (defvar function-history '())
1193 (defvar variable-history '())
1194 (defvar buffer-history '())
1195 (defvar shell-command-history '())
1196 (defvar file-name-history '())
1197
1198 (defvar read-expression-history nil)
1199
1200 (defvar minibuffer-history-sexp-flag nil ;weird FSF Emacs kludge
1201 "Non-nil when doing history operations on `command-history'.
1202 More generally, indicates that the history list being acted on
1203 contains expressions rather than strings.")
1204
1205 (defun previous-matching-history-element (regexp n)
1206 "Find the previous history element that matches REGEXP.
1207 \(Previous history elements refer to earlier actions.)
1208 With prefix argument N, search for Nth previous match.
1209 If N is negative, find the next or Nth next match."
1210 (interactive
1211 (let ((enable-recursive-minibuffers t)
1212 (minibuffer-history-sexp-flag nil))
1213 (if (eq 't (symbol-value minibuffer-history-variable))
1214 (error "History is not being recorded in this context"))
1215 (list (read-from-minibuffer "Previous element matching (regexp): "
1216 (car minibuffer-history-search-history)
1217 minibuffer-local-map
1218 nil
1219 'minibuffer-history-search-history)
1220 (prefix-numeric-value current-prefix-arg))))
1221 (let ((history (symbol-value minibuffer-history-variable))
1222 prevpos
1223 (pos minibuffer-history-position))
1224 (if (eq history t)
1225 (error "History is not being recorded in this context"))
1226 (while (/= n 0)
1227 (setq prevpos pos)
1228 (setq pos (min (max 1 (+ pos (if (< n 0) -1 1))) (length history)))
1229 (if (= pos prevpos)
1230 (if (= pos 1) ;; rewritten for I18N3 snarfing
1231 (error "No later matching history item")
1232 (error "No earlier matching history item")))
1233 (if (string-match regexp
1234 (if minibuffer-history-sexp-flag
1235 (let ((print-level nil))
1236 (prin1-to-string (nth (1- pos) history)))
1237 (nth (1- pos) history)))
1238 (setq n (+ n (if (< n 0) 1 -1)))))
1239 (setq minibuffer-history-position pos)
1240 (setq current-minibuffer-contents (buffer-string)
1241 current-minibuffer-point (point))
1242 (erase-buffer)
1243 (let ((elt (nth (1- pos) history)))
1244 (insert (if minibuffer-history-sexp-flag
1245 (let ((print-level nil))
1246 (prin1-to-string elt))
1247 elt)))
1248 (goto-char (point-min)))
1249 (if (or (eq (car (car command-history)) 'previous-matching-history-element)
1250 (eq (car (car command-history)) 'next-matching-history-element))
1251 (setq command-history (cdr command-history))))
1252
1253 (defun next-matching-history-element (regexp n)
1254 "Find the next history element that matches REGEXP.
1255 \(The next history element refers to a more recent action.)
1256 With prefix argument N, search for Nth next match.
1257 If N is negative, find the previous or Nth previous match."
1258 (interactive
1259 (let ((enable-recursive-minibuffers t)
1260 (minibuffer-history-sexp-flag nil))
1261 (if (eq t (symbol-value minibuffer-history-variable))
1262 (error "History is not being recorded in this context"))
1263 (list (read-from-minibuffer "Next element matching (regexp): "
1264 (car minibuffer-history-search-history)
1265 minibuffer-local-map
1266 nil
1267 'minibuffer-history-search-history)
1268 (prefix-numeric-value current-prefix-arg))))
1269 (previous-matching-history-element regexp (- n)))
1270
1271 (defun next-history-element (n)
1272 "Insert the next element of the minibuffer history into the minibuffer."
1273 (interactive "p")
1274 (if (eq 't (symbol-value minibuffer-history-variable))
1275 (error "History is not being recorded in this context"))
1276 (unless (zerop n)
1277 (when (eq minibuffer-history-position
1278 initial-minibuffer-history-position)
1279 (setq current-minibuffer-contents (buffer-string)
1280 current-minibuffer-point (point)))
1281 (let ((narg (- minibuffer-history-position n)))
1282 (cond ((< narg 0)
1283 (error "No following item in %s" minibuffer-history-variable))
1284 ((> narg (length (symbol-value minibuffer-history-variable)))
1285 (error "No preceding item in %s" minibuffer-history-variable)))
1286 (erase-buffer)
1287 (setq minibuffer-history-position narg)
1288 (if (eq narg initial-minibuffer-history-position)
1289 (progn
1290 (insert current-minibuffer-contents)
1291 (goto-char current-minibuffer-point))
1292 (let ((elt (nth (1- minibuffer-history-position)
1293 (symbol-value minibuffer-history-variable))))
1294 (insert
1295 (if (not (stringp elt))
1296 (let ((print-level nil))
1297 (condition-case nil
1298 (let ((print-readably t)
1299 (print-escape-newlines t))
1300 (prin1-to-string elt))
1301 (error (prin1-to-string elt))))
1302 elt)))
1303 ;; FSF has point-min here.
1304 (goto-char (point-max))))))
1305
1306 (defun previous-history-element (n)
1307 "Inserts the previous element of the minibuffer history into the minibuffer."
1308 (interactive "p")
1309 (next-history-element (- n)))
1310
1311 (defun next-complete-history-element (n)
1312 "Get next element of history which is a completion of minibuffer contents."
1313 (interactive "p")
1314 (let ((point-at-start (point)))
1315 (next-matching-history-element
1316 (concat "^" (regexp-quote (buffer-substring (point-min) (point)))) n)
1317 ;; next-matching-history-element always puts us at (point-min).
1318 ;; Move to the position we were at before changing the buffer contents.
1319 ;; This is still sensical, because the text before point has not changed.
1320 (goto-char point-at-start)))
1321
1322 (defun previous-complete-history-element (n)
1323 "Get previous element of history which is a completion of minibuffer contents."
1324 (interactive "p")
1325 (next-complete-history-element (- n)))
1326
1327
1328 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1329 ;;;; reading various things from a minibuffer ;;;;
1330 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1331
1332 (defun read-expression (prompt &optional initial-contents history)
1333 "Return a Lisp object read using the minibuffer.
1334 Prompt with PROMPT. If non-nil, optional second arg INITIAL-CONTENTS
1335 is a string to insert in the minibuffer before reading.
1336 Third arg HISTORY, if non-nil, specifies a history list."
1337 (let ((minibuffer-history-sexp-flag t)
1338 ;; Semi-kludge to get around M-x C-x o M-ESC trying to do completion.
1339 (minibuffer-completion-table nil))
1340 (read-from-minibuffer prompt
1341 initial-contents
1342 read-expression-map
1343 t
1344 (or history 'read-expression-history)
1345 lisp-mode-abbrev-table)))
1346
1347 (defun read-string (prompt &optional initial-contents history)
1348 "Return a string from the minibuffer, prompting with string PROMPT.
1349 If non-nil, optional second arg INITIAL-CONTENTS is a string to insert
1350 in the minibuffer before reading.
1351 Third arg HISTORY, if non-nil, specifies a history list."
1352 (let ((minibuffer-completion-table nil))
1353 (read-from-minibuffer prompt
1354 initial-contents
1355 minibuffer-local-map
1356 nil history)))
1357
1358 (defun eval-minibuffer (prompt &optional initial-contents history)
1359 "Return value of Lisp expression read using the minibuffer.
1360 Prompt with PROMPT. If non-nil, optional second arg INITIAL-CONTENTS
1361 is a string to insert in the minibuffer before reading.
1362 Third arg HISTORY, if non-nil, specifies a history list."
1363 (eval (read-expression prompt initial-contents history)))
1364
1365 ;;;#### Screw this crock!!
1366 ;(defun read-no-blanks-input (prompt &optional initial-contents)
1367 ; "Read a string from the terminal, not allowing blanks.
1368 ;Prompt with PROMPT. If non-nil, optional second arg INITIAL-CONTENTS
1369 ;is a string to insert in the minibuffer before reading."
1370 ; (let ((minibuffer-completion-table nil))
1371 ; (read-from-minibuffer prompt
1372 ; initial-contents
1373 ; minibuffer-local-ns-map
1374 ; nil)))
1375
1376 ;; The name `command-history' is already taken
1377 (defvar read-command-history '())
1378
1379 (defun read-command (prompt)
1380 "Read the name of a command and return as a symbol.
1381 Prompts with PROMPT."
1382 (intern (completing-read prompt obarray 'commandp t nil
1383 ;; 'command-history is not right here: that's a
1384 ;; list of evalable forms, not a history list.
1385 'read-command-history
1386 )))
1387
1388 (defun read-function (prompt)
1389 "Read the name of a function and return as a symbol.
1390 Prompts with PROMPT."
1391 (intern (completing-read prompt obarray 'fboundp t nil
1392 'function-history)))
1393
1394 (defun read-variable (prompt)
1395 "Read the name of a user variable and return it as a symbol.
1396 Prompts with PROMPT.
1397 A user variable is one whose documentation starts with a `*' character."
1398 (intern (completing-read prompt obarray 'user-variable-p t nil
1399 'variable-history)))
1400
1401 (defun read-buffer (prompt &optional default require-match)
1402 "Read the name of a buffer and return as a string.
1403 Prompts with PROMPT. Optional second arg DEFAULT is value to return if user
1404 enters an empty line. If optional third arg REQUIRE-MATCH is non-nil,
1405 only existing buffer names are allowed."
1406 (let ((prompt (if default
1407 (format "%s(default %s) "
1408 (gettext prompt) (if (bufferp default)
1409 (buffer-name default)
1410 default))
1411 prompt))
1412 (alist (mapcar #'(lambda (b) (cons (buffer-name b) b))
1413 (buffer-list)))
1414 result)
1415 (while (progn
1416 (setq result (completing-read prompt alist nil require-match
1417 nil 'buffer-history))
1418 (cond ((not (equal result ""))
1419 nil)
1420 ((not require-match)
1421 (setq result default)
1422 nil)
1423 ((not default)
1424 t)
1425 ((not (get-buffer default))
1426 t)
1427 (t
1428 (setq result default)
1429 nil))))
1430 (if (bufferp result)
1431 (buffer-name result)
1432 result)))
1433
1434 (defun read-number (prompt &optional integers-only)
1435 "Reads a number from the minibuffer."
1436 (let ((pred (if integers-only 'integerp 'numberp))
1437 num)
1438 (while (not (funcall pred num))
1439 (setq num (condition-case ()
1440 (let ((minibuffer-completion-table nil))
1441 (read-from-minibuffer
1442 prompt (if num (prin1-to-string num)) nil t
1443 t)) ;no history
1444 (invalid-read-syntax nil)
1445 (end-of-file nil)))
1446 (or (funcall pred num) (beep)))
1447 num))
1448
1449 (defun read-shell-command (prompt &optional initial-input history)
1450 "Just like read-string, but uses read-shell-command-map:
1451 \\{read-shell-command-map}"
1452 (let ((minibuffer-completion-table nil))
1453 (read-from-minibuffer prompt initial-input read-shell-command-map
1454 nil (or history 'shell-command-history))))
1455
1456
1457 ;;; This read-file-name stuff probably belongs in files.el
1458
1459 ;; Quote "$" as "$$" to get it past substitute-in-file-name
1460 (defun un-substitute-in-file-name (string)
1461 (let ((regexp "\\$")
1462 (olen (length string))
1463 new
1464 n o ch)
1465 (cond ((eq system-type 'vax-vms)
1466 string)
1467 ((not (string-match regexp string))
1468 string)
1469 (t
1470 (setq n 1)
1471 (while (string-match regexp string (match-end 0))
1472 (setq n (1+ n)))
1473 (setq new (make-string (+ olen n) ?$))
1474 (setq n 0 o 0)
1475 (while (< o olen)
1476 (setq ch (aref string o))
1477 (aset new n ch)
1478 (setq o (1+ o) n (1+ n))
1479 (if (eq ch ?$)
1480 ;; already aset by make-string initial-value
1481 (setq n (1+ n))))
1482 new))))
1483
1484 (defun read-file-name-2 (history prompt dir default
1485 must-match initial-contents
1486 completer)
1487 (if (not dir)
1488 (setq dir default-directory))
1489 (setq dir (abbreviate-file-name dir t))
1490 (let* ((insert (cond ((and (not insert-default-directory)
1491 (not initial-contents))
1492 "")
1493 (initial-contents
1494 (cons (un-substitute-in-file-name
1495 (concat dir initial-contents))
1496 (length dir)))
1497 (t
1498 (un-substitute-in-file-name dir))))
1499 (val (let ((completion-ignore-case (or completion-ignore-case
1500 (eq system-type 'vax-vms))))
1501 ;; Hateful, broken, case-sensitive un*x
1502 ;;; (completing-read prompt
1503 ;;; completer
1504 ;;; dir
1505 ;;; must-match
1506 ;;; insert
1507 ;;; history)
1508 ;; #### - this is essentially the guts of completing read.
1509 ;; There should be an elegant way to pass a pair of keymaps to
1510 ;; completing read, but this will do for now. All sins are
1511 ;; relative. --Stig
1512 (let ((minibuffer-completion-table completer)
1513 (minibuffer-completion-predicate dir)
1514 (minibuffer-completion-confirm (if (eq must-match 't)
1515 nil t))
1516 (last-exact-completion nil))
1517 (read-from-minibuffer prompt
1518 insert
1519 (if (not must-match)
1520 read-file-name-map
1521 read-file-name-must-match-map)
1522 nil
1523 history)))
1524 ))
1525 ;;; ;; Kludge! Put "/foo/bar" on history rather than "/default//foo/bar"
1526 ;;; (let ((hist (cond ((not history) 'minibuffer-history)
1527 ;;; ((consp history) (car history))
1528 ;;; (t history))))
1529 ;;; (if (and val
1530 ;;; hist
1531 ;;; (not (eq hist 't))
1532 ;;; (boundp hist)
1533 ;;; (equal (car-safe (symbol-value hist)) val))
1534 ;;; (let ((e (condition-case nil
1535 ;;; (expand-file-name val)
1536 ;;; (error nil))))
1537 ;;; (if (and e (not (equal e val)))
1538 ;;; (set hist (cons e (cdr (symbol-value hist))))))))
1539
1540 (cond ((not val)
1541 (error "No file name specified"))
1542 ((and default
1543 (equal val (if (consp insert) (car insert) insert)))
1544 default)
1545 (t
1546 (substitute-in-file-name val)))))
1547
1548 ;; #### this function should use minibuffer-completion-table
1549 ;; or something. But that is sloooooow.
1550 ;; #### all this shit needs better documentation!!!!!!!!
1551 (defun read-file-name-activate-callback (event extent dir-p)
1552 ;; used as the activate-callback of the filename list items
1553 ;; in the completion buffer, in place of default-choose-completion.
1554 ;; if a regular file was selected, we call default-choose-completion
1555 ;; (which just inserts the string in the minibuffer and calls
1556 ;; exit-minibuffer). If a directory was selected, we display
1557 ;; the contents of the directory.
1558 (let* ((file (extent-string extent))
1559 (completion-buf (extent-object extent))
1560 (minibuf (symbol-value-in-buffer 'completion-reference-buffer
1561 completion-buf))
1562 (in-dir (file-name-directory (buffer-substring nil nil minibuf)))
1563 (full (expand-file-name file in-dir)))
1564 (if (not (file-directory-p full))
1565 (default-choose-completion event extent minibuf)
1566 (erase-buffer minibuf)
1567 (insert-string (file-name-as-directory
1568 (abbreviate-file-name full t)) minibuf)
1569 (reset-buffer completion-buf)
1570 (let ((standard-output completion-buf))
1571 (display-completion-list
1572 (delete "." (directory-files full nil nil nil (if dir-p 'directory)))
1573 :user-data dir-p
1574 :reference-buffer minibuf
1575 :activate-callback 'read-file-name-activate-callback)
1576 (goto-char (point-min) completion-buf)))))
1577
1578 (defun read-file-name-1 (history prompt dir default
1579 must-match initial-contents
1580 completer)
1581 (if (should-use-dialog-box-p)
1582 ;; this calls read-file-name-2
1583 (mouse-read-file-name-1 history prompt dir default must-match
1584 initial-contents completer)
1585 (let ((rfhookfun
1586 (lambda ()
1587 (set
1588 (make-local-variable
1589 'completion-display-completion-list-function)
1590 #'(lambda (completions)
1591 (display-completion-list
1592 completions
1593 :user-data (not (eq completer 'read-file-name-internal))
1594 :activate-callback
1595 'read-file-name-activate-callback)))
1596 ;; kludge!
1597 (remove-hook 'minibuffer-setup-hook rfhookfun)
1598 )))
1599 (unwind-protect
1600 (progn
1601 (add-hook 'minibuffer-setup-hook rfhookfun)
1602 (read-file-name-2 history prompt dir default must-match
1603 initial-contents completer))
1604 (remove-hook 'minibuffer-setup-hook rfhookfun)))))
1605
1606 (defun read-file-name (prompt
1607 &optional dir default must-match initial-contents
1608 history)
1609 "Read file name, prompting with PROMPT and completing in directory DIR.
1610 This will prompt with a dialog box if appropriate, according to
1611 `should-use-dialog-box-p'.
1612 Value is not expanded---you must call `expand-file-name' yourself.
1613 Value is subject to interpreted by substitute-in-file-name however.
1614 Default name to DEFAULT if user enters a null string.
1615 (If DEFAULT is omitted, the visited file name is used,
1616 except that if INITIAL-CONTENTS is specified, that combined with DIR is
1617 used.)
1618 Fourth arg MUST-MATCH non-nil means require existing file's name.
1619 Non-nil and non-t means also require confirmation after completion.
1620 Fifth arg INITIAL-CONTENTS specifies text to start with.
1621 Sixth arg HISTORY specifies the history list to use. Default is
1622 `file-name-history'.
1623 DIR defaults to current buffer's directory default."
1624 (read-file-name-1
1625 (or history 'file-name-history)
1626 prompt dir (or default
1627 (if initial-contents (expand-file-name initial-contents dir)
1628 buffer-file-name))
1629 must-match initial-contents
1630 ;; A separate function (not an anonymous lambda-expression)
1631 ;; and passed as a symbol because of disgusting kludges in various
1632 ;; places which do stuff like (let ((filename-kludge-p (eq minibuffer-completion-table 'read-file-name-internal))) ...)
1633 'read-file-name-internal))
1634
1635 (defun read-directory-name (prompt
1636 &optional dir default must-match initial-contents)
1637 "Read directory name, prompting with PROMPT and completing in directory DIR.
1638 This will prompt with a dialog box if appropriate, according to
1639 `should-use-dialog-box-p'.
1640 Value is not expanded---you must call `expand-file-name' yourself.
1641 Value is subject to interpreted by substitute-in-file-name however.
1642 Default name to DEFAULT if user enters a null string.
1643 (If DEFAULT is omitted, the current buffer's default directory is used.)
1644 Fourth arg MUST-MATCH non-nil means require existing directory's name.
1645 Non-nil and non-t means also require confirmation after completion.
1646 Fifth arg INITIAL-CONTENTS specifies text to start with.
1647 Sixth arg HISTORY specifies the history list to use. Default is
1648 `file-name-history'.
1649 DIR defaults to current buffer's directory default."
1650 (read-file-name-1
1651 'file-name-history
1652 prompt dir (or default default-directory) must-match initial-contents
1653 'read-directory-name-internal))
1654
1655
1656 ;; Environment-variable completion hack
1657 (defun read-file-name-internal-1 (string dir action completer)
1658 (if (not (string-match
1659 "\\([^$]\\|\\`\\)\\(\\$\\$\\)*\\$\\([A-Za-z0-9_]*\\|{[^}]*\\)\\'"
1660 string))
1661 ;; Not doing environment-variable completion hack
1662 (let* ((orig (if (equal string "") nil string))
1663 (sstring (if orig (substitute-in-file-name string) string))
1664 (specdir (if orig (file-name-directory sstring) nil)))
1665 (funcall completer
1666 action
1667 orig
1668 sstring
1669 specdir
1670 (if specdir (expand-file-name specdir dir) dir)
1671 (if orig (file-name-nondirectory sstring) string)))
1672 ;; An odd number of trailing $'s
1673 (let* ((start (match-beginning 3))
1674 (env (substring string
1675 (cond ((= start (length string))
1676 ;; "...$"
1677 start)
1678 ((= (aref string start) ?{)
1679 ;; "...${..."
1680 (1+ start))
1681 (t
1682 start))))
1683 (head (substring string 0 (1- start)))
1684 (alist #'(lambda ()
1685 (mapcar #'(lambda (x)
1686 (cons (substring x 0 (string-match "=" x))
1687 'nil))
1688 process-environment))))
1689
1690 (cond ((eq action 'lambda)
1691 nil)
1692 ((eq action 't)
1693 ;; all completions
1694 (mapcar #'(lambda (p)
1695 (if (and (> (length p) 0)
1696 ;;#### Unix-specific
1697 ;;#### -- need absolute-pathname-p
1698 (/= (aref p 0) ?/))
1699 (concat "$" p)
1700 (concat head "$" p)))
1701 (all-completions env (funcall alist))))
1702 (t ;; 'nil
1703 ;; complete
1704 (let* ((e (funcall alist))
1705 (val (try-completion env e)))
1706 (cond ((stringp val)
1707 (if (string-match "[^A-Za-z0-9_]" val)
1708 (concat head
1709 "${" val
1710 ;; completed uniquely?
1711 (if (eq (try-completion val e) 't)
1712 "}" ""))
1713 (concat head "$" val)))
1714 ((eql val 't)
1715 (concat head
1716 (un-substitute-in-file-name (getenv env))))
1717 (t nil))))))))
1718
1719
1720 (defun read-file-name-internal (string dir action)
1721 (read-file-name-internal-1
1722 string dir action
1723 #'(lambda (action orig string specdir dir name)
1724 (cond ((eq action 'lambda)
1725 (if (not orig)
1726 nil
1727 (let ((sstring (condition-case nil
1728 (expand-file-name string)
1729 (error nil))))
1730 (if (not sstring)
1731 ;; Some pathname syntax error in string
1732 nil
1733 (file-exists-p sstring)))))
1734 ((eq action 't)
1735 ;; all completions
1736 (mapcar #'un-substitute-in-file-name
1737 (file-name-all-completions name dir)))
1738 (t;; 'nil
1739 ;; complete
1740 (let* ((d (or dir default-directory))
1741 (val (file-name-completion name d)))
1742 (if (and (eq val 't)
1743 (not (null completion-ignored-extensions)))
1744 ;;#### (file-name-completion "foo") returns 't
1745 ;; when both "foo" and "foo~" exist and the latter
1746 ;; is "pruned" by completion-ignored-extensions.
1747 ;; I think this is a bug in file-name-completion.
1748 (setq val (let ((completion-ignored-extensions '()))
1749 (file-name-completion name d))))
1750 (if (stringp val)
1751 (un-substitute-in-file-name (if specdir
1752 (concat specdir val)
1753 val))
1754 (let ((tem (un-substitute-in-file-name string)))
1755 (if (not (equal tem orig))
1756 ;; substitute-in-file-name did something
1757 tem
1758 val)))))))))
1759
1760 (defun read-directory-name-internal (string dir action)
1761 (read-file-name-internal-1
1762 string dir action
1763 #'(lambda (action orig string specdir dir name)
1764 (let* ((dirs #'(lambda (fn)
1765 (let ((l (if (equal name "")
1766 (directory-files
1767 dir
1768 nil
1769 ""
1770 nil
1771 'directories)
1772 (directory-files
1773 dir
1774 nil
1775 (concat "\\`" (regexp-quote name))
1776 nil
1777 'directories))))
1778 (mapcar fn
1779 (cond ((eq system-type 'vax-vms)
1780 l)
1781 (t
1782 ;; Wretched unix
1783 (delete "." l))))))))
1784 (cond ((eq action 'lambda)
1785 ;; complete?
1786 (if (not orig)
1787 nil
1788 (file-directory-p string)))
1789 ((eq action 't)
1790 ;; all completions
1791 (funcall dirs #'(lambda (n)
1792 (un-substitute-in-file-name
1793 (file-name-as-directory n)))))
1794 (t
1795 ;; complete
1796 (let ((val (try-completion
1797 name
1798 (funcall dirs
1799 #'(lambda (n)
1800 (list (file-name-as-directory
1801 n)))))))
1802 (if (stringp val)
1803 (un-substitute-in-file-name (if specdir
1804 (concat specdir val)
1805 val))
1806 (let ((tem (un-substitute-in-file-name string)))
1807 (if (not (equal tem orig))
1808 ;; substitute-in-file-name did something
1809 tem
1810 val))))))))))
1811
1812 (defun append-expand-filename (file-string string)
1813 "Append STRING to FILE-STRING differently depending on whether STRING
1814 is a username (~string), an environment variable ($string),
1815 or a filename (/string). The resultant string is returned with the
1816 environment variable or username expanded and resolved to indicate
1817 whether it is a file(/result) or a directory (/result/)."
1818 (let ((file
1819 (cond ((string-match "\\([~$]\\)\\([^~$/]*\\)$" file-string)
1820 (cond ((string= (substring file-string
1821 (match-beginning 1)
1822 (match-end 1)) "~")
1823 (concat (substring file-string 0 (match-end 1))
1824 string))
1825 (t (substitute-in-file-name
1826 (concat (substring file-string 0 (match-end 1))
1827 string)))))
1828 (t (concat (file-name-directory
1829 (substitute-in-file-name file-string)) string))))
1830 result)
1831
1832 (cond ((stringp (setq result (and (file-exists-p (expand-file-name file))
1833 (read-file-name-internal
1834 (condition-case nil
1835 (expand-file-name file)
1836 (error file))
1837 "" nil))))
1838 result)
1839 (t file))))
1840
1841 (defun mouse-file-display-completion-list (window dir minibuf user-data)
1842 (let ((standard-output (window-buffer window)))
1843 (condition-case nil
1844 (display-completion-list
1845 (directory-files dir nil nil nil t)
1846 :window-width (* 2 (window-width window))
1847 :activate-callback
1848 'mouse-read-file-name-activate-callback
1849 :user-data user-data
1850 :reference-buffer minibuf
1851 :help-string "")
1852 (t nil))))
1853
1854 (defun mouse-directory-display-completion-list (window dir minibuf user-data)
1855 (let ((standard-output (window-buffer window)))
1856 (condition-case nil
1857 (display-completion-list
1858 (delete "." (directory-files dir nil nil nil 1))
1859 :window-width (window-width window)
1860 :activate-callback
1861 'mouse-read-file-name-activate-callback
1862 :user-data user-data
1863 :reference-buffer minibuf
1864 :help-string "")
1865 (t nil))))
1866
1867 (defun mouse-read-file-name-activate-callback (event extent user-data)
1868 (let* ((file (extent-string extent))
1869 (minibuf (symbol-value-in-buffer 'completion-reference-buffer
1870 (extent-object extent)))
1871 (in-dir (buffer-substring nil nil minibuf))
1872 (full (expand-file-name file in-dir))
1873 (filebuf (nth 0 user-data))
1874 (dirbuff (nth 1 user-data))
1875 (filewin (nth 2 user-data))
1876 (dirwin (nth 3 user-data)))
1877 (if (file-regular-p full)
1878 (default-choose-completion event extent minibuf)
1879 (erase-buffer minibuf)
1880 (insert-string (file-name-as-directory
1881 (abbreviate-file-name full t)) minibuf)
1882 (reset-buffer filebuf)
1883 (if (not dirbuff)
1884 (mouse-directory-display-completion-list filewin full minibuf
1885 user-data)
1886 (mouse-file-display-completion-list filewin full minibuf user-data)
1887 (reset-buffer dirbuff)
1888 (mouse-directory-display-completion-list dirwin full minibuf
1889 user-data)))))
1890
1891 ;; this is rather cheesified but gets the job done.
1892 (defun mouse-read-file-name-1 (history prompt dir default
1893 must-match initial-contents
1894 completer)
1895 (let* ((file-p (eq 'read-file-name-internal completer))
1896 (filebuf (get-buffer-create "*Completions*"))
1897 (dirbuff (and file-p (generate-new-buffer " *mouse-read-file*")))
1898 (butbuff (generate-new-buffer " *mouse-read-file*"))
1899 (frame (make-dialog-frame))
1900 filewin dirwin
1901 user-data)
1902 (unwind-protect
1903 (progn
1904 (reset-buffer filebuf)
1905 (select-frame frame)
1906 (let ((window-min-height 1))
1907 ;; #### should be 2 not 3, but that causes
1908 ;; "window too small to split" errors for some
1909 ;; people (but not for me ...) There's a more
1910 ;; fundamental bug somewhere.
1911 (split-window nil (- (frame-height frame) 3)))
1912 (if file-p
1913 (progn
1914 (split-window-horizontally 16)
1915 (setq filewin (frame-rightmost-window frame)
1916 dirwin (frame-leftmost-window frame))
1917 (set-window-buffer filewin filebuf)
1918 (set-window-buffer dirwin dirbuff))
1919 (setq filewin (frame-highest-window frame))
1920 (set-window-buffer filewin filebuf))
1921 (setq user-data (list filebuf dirbuff filewin dirwin))
1922 (set-window-buffer (frame-lowest-window frame) butbuff)
1923 (set-buffer butbuff)
1924 (when (featurep 'scrollbar)
1925 (set-specifier scrollbar-width 0 butbuff))
1926 (insert " ")
1927 (insert-gui-button (make-gui-button "OK"
1928 (lambda (foo)
1929 (exit-minibuffer))))
1930 (insert " ")
1931 (insert-gui-button (make-gui-button "Cancel"
1932 (lambda (foo)
1933 (abort-recursive-edit))))
1934 (let ((rfhookfun
1935 (lambda ()
1936 (if (not file-p)
1937 (mouse-directory-display-completion-list
1938 filewin dir (current-buffer) user-data)
1939 (mouse-file-display-completion-list filewin dir
1940 (current-buffer)
1941 user-data)
1942 (mouse-directory-display-completion-list dirwin dir
1943 (current-buffer)
1944 user-data))
1945 (set
1946 (make-local-variable
1947 'completion-display-completion-list-function)
1948 #'(lambda (completions)
1949 (display-completion-list
1950 completions
1951 :help-string ""
1952 :activate-callback
1953 'mouse-read-file-name-activate-callback
1954 :user-data user-data)))
1955 ;; kludge!
1956 (remove-hook 'minibuffer-setup-hook rfhookfun)
1957 ))
1958 (rfcshookfun
1959 ;; kludge!
1960 ;; #### I really need to flesh out the object
1961 ;; hierarchy better to avoid these kludges.
1962 (lambda ()
1963 (save-excursion
1964 (set-buffer standard-output)
1965 (setq truncate-lines t)))))
1966 (unwind-protect
1967 (progn
1968 (add-hook 'minibuffer-setup-hook rfhookfun)
1969 (add-hook 'completion-setup-hook rfcshookfun)
1970 (read-file-name-2 history prompt dir default
1971 must-match initial-contents
1972 completer))
1973 (remove-hook 'minibuffer-setup-hook rfhookfun)
1974 (remove-hook 'completion-setup-hook rfcshookfun))))
1975 (delete-frame frame)
1976 (kill-buffer filebuf)
1977 (kill-buffer butbuff)
1978 (and dirbuff (kill-buffer dirbuff)))))
1979
1980 (defun read-face (prompt &optional must-match)
1981 "Read the name of a face from the minibuffer and return it as a symbol."
1982 (intern (completing-read prompt obarray 'find-face must-match)))
1983
1984 ;; #### - wrong place for this variable? Exactly. We probably want
1985 ;; `color-list' to be a console method, so `tty-color-list' becomes
1986 ;; obsolete, and `read-color-completion-table' conses (mapcar #'list
1987 ;; (color-list)), optionally caching the results.
1988
1989 ;; Ben wanted all of the possibilities from the `configure' script used
1990 ;; here, but I think this is way too many. I already trimmed the R4 variants
1991 ;; and a few obvious losers from the list. --Stig
1992 (defvar x-library-search-path '("/usr/X11R6/lib/X11/"
1993 "/usr/X11R5/lib/X11/"
1994 "/usr/lib/X11R6/X11/"
1995 "/usr/lib/X11R5/X11/"
1996 "/usr/local/X11R6/lib/X11/"
1997 "/usr/local/X11R5/lib/X11/"
1998 "/usr/local/lib/X11R6/X11/"
1999 "/usr/local/lib/X11R5/X11/"
2000 "/usr/X11/lib/X11/"
2001 "/usr/lib/X11/"
2002 "/usr/local/lib/X11/"
2003 "/usr/X386/lib/X11/"
2004 "/usr/x386/lib/X11/"
2005 "/usr/XFree86/lib/X11/"
2006 "/usr/unsupported/lib/X11/"
2007 "/usr/athena/lib/X11/"
2008 "/usr/local/x11r5/lib/X11/"
2009 "/usr/lpp/Xamples/lib/X11/"
2010 "/usr/openwin/lib/X11/"
2011 "/usr/openwin/share/lib/X11/")
2012 "Search path used by `read-color' to find rgb.txt.")
2013
2014 (defvar x-read-color-completion-table)
2015
2016 (defun read-color-completion-table ()
2017 (case (device-type)
2018 ;; #### Evil device-type dependency
2019 (x
2020 (if (boundp 'x-read-color-completion-table)
2021 x-read-color-completion-table
2022 (let ((rgb-file (locate-file "rgb.txt" x-library-search-path))
2023 clist color p)
2024 (if (not rgb-file)
2025 ;; prevents multiple searches for rgb.txt if we can't find it
2026 (setq x-read-color-completion-table nil)
2027 (with-current-buffer (get-buffer-create " *colors*")
2028 (reset-buffer (current-buffer))
2029 (insert-file-contents rgb-file)
2030 (while (not (eobp))
2031 ;; skip over comments
2032 (while (looking-at "^!")
2033 (end-of-line)
2034 (forward-char 1))
2035 (skip-chars-forward "0-9 \t")
2036 (setq p (point))
2037 (end-of-line)
2038 (setq color (buffer-substring p (point))
2039 clist (cons (list color) clist))
2040 ;; Ugh. If we want to be able to complete the lowercase form
2041 ;; of the color name, we need to add it twice! Yuck.
2042 (let ((dcase (downcase color)))
2043 (or (string= dcase color)
2044 (push (list dcase) clist)))
2045 (forward-char 1))
2046 (kill-buffer (current-buffer))))
2047 (setq x-read-color-completion-table clist)
2048 x-read-color-completion-table)))
2049 (tty
2050 (mapcar #'list (tty-color-list)))))
2051
2052 (defun read-color (prompt &optional must-match initial-contents)
2053 "Read the name of a color from the minibuffer.
2054 On X devices, this uses `x-library-search-path' to find rgb.txt in order
2055 to build a completion table.
2056 On TTY devices, this uses `tty-color-list'."
2057 (let ((table (read-color-completion-table)))
2058 (completing-read prompt table nil (and table must-match)
2059 initial-contents)))
2060
2061
2062 ;; #### The doc string for read-non-nil-coding system gets lost if we
2063 ;; only include these if the mule feature is present. Strangely,
2064 ;; read-coding-system doesn't.
2065
2066 ;;(if (featurep 'mule)
2067
2068 (defun read-coding-system (prompt)
2069 "Read a coding-system (or nil) from the minibuffer.
2070 Prompting with string PROMPT."
2071 (intern (completing-read prompt obarray 'find-coding-system t)))
2072
2073 (defun read-non-nil-coding-system (prompt)
2074 "Read a non-nil coding-system from the minibuffer.
2075 Prompt with string PROMPT."
2076 (let ((retval (intern "")))
2077 (while (= 0 (length (symbol-name retval)))
2078 (setq retval (intern (completing-read prompt obarray
2079 'find-coding-system
2080 t))))
2081 retval))
2082
2083 ;;) ;; end of (featurep 'mule)
2084
2085
2086
2087 (defcustom force-dialog-box-use nil
2088 "*If non-nil, always use a dialog box for asking questions, if possible.
2089 You should *bind* this, not set it. This is useful if you're doing
2090 something mousy but which wasn't actually invoked using the mouse."
2091 :type 'boolean
2092 :group 'minibuffer)
2093
2094 ;; We include this here rather than dialog.el so it is defined
2095 ;; even when dialog boxes are not present.
2096 (defun should-use-dialog-box-p ()
2097 "If non-nil, questions should be asked with a dialog box instead of the
2098 minibuffer. This looks at `last-command-event' to see if it was a mouse
2099 event, and checks whether dialog-support exists and the current device
2100 supports dialog boxes.
2101
2102 The dialog box is totally disabled if the variable `use-dialog-box'
2103 is set to nil."
2104 (and (featurep 'dialog)
2105 (device-on-window-system-p)
2106 use-dialog-box
2107 (or force-dialog-box-use
2108 (button-press-event-p last-command-event)
2109 (button-release-event-p last-command-event)
2110 (misc-user-event-p last-command-event))))
2111
2112 ;;; minibuf.el ends here