comparison lisp/vm/vm-minibuf.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 859a2309aef8
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; Minibuffer read functions for VM
2 ;;; Copyright (C) 1993, 1994 Kyle E. Jones
3 ;;;
4 ;;; This program is free software; you can redistribute it and/or modify
5 ;;; it under the terms of the GNU General Public License as published by
6 ;;; the Free Software Foundation; either version 1, or (at your option)
7 ;;; any later version.
8 ;;;
9 ;;; This program is distributed in the hope that it will be useful,
10 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ;;; GNU General Public License for more details.
13 ;;;
14 ;;; You should have received a copy of the GNU General Public License
15 ;;; along with this program; if not, write to the Free Software
16 ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 (provide 'vm-minibuf)
19
20 (defun vm-minibuffer-complete-word (&optional exiting)
21 (interactive)
22 (let ((opoint (point))
23 trimmed-c-list c-list beg end diff word word-prefix-regexp completion)
24 ;; find the beginning and end of the word we're trying to complete
25 (if (or (eobp) (memq (following-char) '(?\t ?\n ?\ )))
26 (progn
27 (skip-chars-backward " \t\n")
28 (and (not (eobp)) (forward-char))
29 (setq end (point)))
30 (skip-chars-forward "^ \t\n")
31 (setq end (point)))
32 (skip-chars-backward "^ \t\n")
33 (setq beg (point))
34 (goto-char opoint)
35 ;; copy the word into a string
36 (setq word (buffer-substring beg end))
37 ;; trim the completion list down to just likely candidates
38 ;; then convert it to an alist.
39 (setq word-prefix-regexp (concat "^" (regexp-quote word))
40 trimmed-c-list (vm-delete-non-matching-strings
41 word-prefix-regexp
42 vm-minibuffer-completion-table)
43 trimmed-c-list (mapcar 'list trimmed-c-list)
44 c-list (mapcar 'list vm-minibuffer-completion-table))
45 ;; Try the word against the completion list.
46 (and trimmed-c-list
47 (setq completion (try-completion word trimmed-c-list)))
48 ;; If completion is nil, figure out what prefix of the word would prefix
49 ;; something in the completion list... but only if the user is interested.
50 (if (and (null completion) vm-completion-auto-correct c-list)
51 (let ((i -1))
52 (while (null (setq completion
53 (try-completion (substring word 0 i) c-list)))
54 (vm-decrement i))
55 (setq completion (substring word 0 i))))
56 ;; If completion is t, we had a perfect match already.
57 (if (eq completion t)
58 (cond ((and (cdr trimmed-c-list)
59 (not (eq last-command 'vm-minibuffer-complete-word)))
60 (and (not exiting)
61 (vm-minibuffer-completion-message
62 "[Complete, but not unique]")))
63 (vm-completion-auto-space
64 (goto-char end)
65 (insert " "))
66 (t
67 (and (not exiting)
68 (vm-minibuffer-completion-message "[Sole completion]"))))
69 ;; Compute the difference in length between the completion and the
70 ;; word. A negative difference means no match and the magnitude
71 ;; indicates the number of chars that need to be shaved off the end
72 ;; before a match will occur. A positive difference means a match
73 ;; occurred and the magnitude specifies the number of new chars that
74 ;; can be appended to the word as a completion.
75 ;;
76 ;; `completion' can be nil here, but the code works anyway because
77 ;; (length nil) still equals 0!
78 (setq diff (- (length completion) (length word)))
79 (cond
80 ;; We have some completion chars. Insert them.
81 ((> diff 0)
82 (goto-char end)
83 (insert (substring completion (- diff)))
84 (if (and vm-completion-auto-space
85 (null (cdr trimmed-c-list)))
86 (insert " ")))
87 ;; The word prefixed more than one string, but we can't complete
88 ;; any further. Either give help or say "Ambiguous".
89 ((zerop diff)
90 (and (not exiting)
91 (if (null completion-auto-help)
92 (vm-minibuffer-completion-message "[Ambiguous]")
93 (vm-minibuffer-show-completions (sort
94 (mapcar 'car trimmed-c-list)
95 'string-lessp)))))
96 ;; The word didn't prefix anything... if vm-completion-auto-correct is
97 ;; non-nil strip the offending characters and try again.
98 (vm-completion-auto-correct
99 (goto-char end)
100 (delete-char diff)
101 (vm-minibuffer-complete-word exiting))
102 ;; if we're not auto-correcting and we're doing
103 ;; multi-word, just let the user insert a space.
104 (vm-completion-auto-space
105 (insert " "))
106 ;; completion utterly failed, tell the user so.
107 (t
108 (and (not exiting)
109 (vm-minibuffer-completion-message "[No match]")))))))
110
111 (defun vm-minibuffer-complete-word-and-exit ()
112 (interactive)
113 (vm-minibuffer-complete-word t)
114 (exit-minibuffer))
115
116 (defun vm-minibuffer-completion-message (string &optional seconds)
117 "Briefly display STRING to the right of the current minibuffer input.
118 Optional second arg SECONDS specifies how long to keep the message visible;
119 the default is 2 seconds.
120
121 A keypress causes the immediate erasure of the STRING, and return of control
122 to the calling program."
123 (let (omax (inhibit-quit t))
124 (save-excursion
125 (goto-char (point-max))
126 (setq omax (point))
127 (insert " " string))
128 (sit-for (or seconds 2))
129 (delete-region omax (point-max))))
130
131 (defun vm-minibuffer-replace-word (word)
132 (goto-char (point-max))
133 (skip-chars-backward "^ \t\n")
134 (delete-region (point) (point-max))
135 (insert word))
136
137 (defun vm-minibuffer-show-completions (list)
138 "Display LIST in a multi-column listing in the \" *Completions*\" buffer.
139 LIST should be a list of strings."
140 (save-excursion
141 (set-buffer (get-buffer-create " *Completions*"))
142 (setq buffer-read-only nil)
143 (use-local-map (make-sparse-keymap))
144 ;; ignore vm-mutable-* here. the user shouldn't mind
145 ;; because when they exit the minibuffer the windows will be
146 ;; set right again.
147 (display-buffer (current-buffer))
148 (erase-buffer)
149 (insert "Possible completions are:\n")
150 (setq buffer-read-only t)
151 (vm-show-list list 'vm-minibuffer-replace-word
152 (list (current-local-map) minibuffer-local-map))
153 (goto-char (point-min))))
154
155 (defun vm-show-list (list &optional function keymaps)
156 "Display LIST in a multi-column listing in the current buffer at point.
157 The current buffer must be displayed in some window at the time
158 this function is called.
159
160 LIST should be a list of strings.
161
162 Optional second argument FUNCTION will be called if the mouse is
163 clicked on one of the strings in the current buffer. The string
164 clicked upon will be passed to FUNCTION as its sole argument.
165
166 Optional third argument KEYMAPS specifies a lists of keymaps
167 where the FUNCTION should be bound to the mouse clicks. By
168 default the local keymap of the current buffer is used."
169 (or keymaps (setq keymaps (and (current-local-map)
170 (list (current-local-map)))))
171 (save-excursion
172 (let ((buffer-read-only nil)
173 tab-stops longest rows columns list-length q i w start command
174 keymap)
175 (cond ((and function keymaps (vm-mouse-support-possible-p))
176 (setq command
177 (list 'lambda '(e) '(interactive "e")
178 (list 'let
179 '((string (vm-mouse-get-mouse-track-string e)))
180 (list 'and 'string (list function 'string)))))
181 (while keymaps
182 (setq keymap (car keymaps))
183 (cond ((vm-mouse-xemacs-mouse-p)
184 (define-key keymap 'button1 command)
185 (define-key keymap 'button2 command)
186 (define-key keymap 'button3 command))
187 ((vm-mouse-fsfemacs-mouse-p)
188 (define-key keymap [down-mouse-1] 'ignore)
189 (define-key keymap [drag-mouse-1] 'ignore)
190 (define-key keymap [mouse-1] command)
191 (define-key keymap [drag-mouse-2] 'ignore)
192 (define-key keymap [down-mouse-2] 'ignore)
193 (define-key keymap [mouse-2] command)
194 (define-key keymap [drag-mouse-3] 'ignore)
195 (define-key keymap [down-mouse-3] 'ignore)
196 (define-key keymap [mouse-3] command)))
197 (setq keymaps (cdr keymaps)))))
198 (setq w (vm-get-buffer-window (current-buffer)))
199 (setq q list
200 list-length 0
201 longest 0)
202 (while q
203 (setq longest (max longest (length (car q)))
204 list-length (1+ list-length)
205 q (cdr q)))
206 ;; provide for separation between columns
207 (setq longest (+ 3 longest))
208 (setq columns (max 1 (/ (- (window-width w) 2) longest))
209 rows (/ list-length columns)
210 rows
211 (+ (if (zerop (% list-length columns)) 0 1)
212 rows))
213 (setq i columns
214 tab-stops nil)
215 (while (not (zerop i))
216 (setq tab-stops (cons (* longest i) tab-stops)
217 i (1- i)))
218 (setq q list
219 i 0)
220 (while q
221 (setq start (point))
222 (insert (car q))
223 (and function (vm-mouse-set-mouse-track-highlight start (point)))
224 (setq i (1+ i)
225 q (cdr q))
226 (if (zerop (% i columns))
227 (insert "\n")
228 (let ((tab-stop-list tab-stops))
229 (tab-to-tab-stop)))))))
230
231 (defun vm-minibuffer-completion-help ()
232 (interactive)
233 (let ((opoint (point))
234 c-list beg end word word-prefix-regexp)
235 ;; find the beginning and end of the word we're trying to complete
236 (if (or (eobp) (memq (following-char) '(?\t ?\n ?\ )))
237 (progn
238 (skip-chars-backward " \t\n")
239 (and (not (eobp)) (forward-char))
240 (setq end (point)))
241 (skip-chars-forward "^ \t\n")
242 (setq end (point)))
243 (skip-chars-backward "^ \t\n")
244 (setq beg (point))
245 (goto-char opoint)
246 ;; copy the word into a string
247 (setq word (buffer-substring beg end))
248 ;; trim the completion list down to just likely candidates
249 ;; then convert it to an alist.
250 (setq word-prefix-regexp (concat "^" (regexp-quote word))
251 c-list (vm-delete-non-matching-strings
252 word-prefix-regexp
253 vm-minibuffer-completion-table)
254 c-list (sort c-list (function string-lessp)))
255 (if c-list
256 (vm-minibuffer-show-completions c-list)
257 (vm-minibuffer-completion-message " [No match]"))))
258
259 (defun vm-keyboard-read-string (prompt completion-list &optional multi-word)
260 (let ((minibuffer-local-map (copy-keymap minibuffer-local-map))
261 (vm-completion-auto-space multi-word)
262 (vm-minibuffer-completion-table completion-list))
263 (define-key minibuffer-local-map "\t" 'vm-minibuffer-complete-word)
264 (define-key minibuffer-local-map " " 'vm-minibuffer-complete-word)
265 (define-key minibuffer-local-map "?" 'vm-minibuffer-completion-help)
266 (if (not multi-word)
267 (define-key minibuffer-local-map "\r"
268 'vm-minibuffer-complete-word-and-exit))
269 (read-string prompt)))
270
271 (defvar last-nonmenu-event)
272
273 (defun vm-read-string (prompt completion-list &optional multi-word)
274 ;; handle alist
275 (if (consp (car completion-list))
276 (setq completion-list (nreverse (mapcar 'car completion-list))))
277 (if (and completion-list (vm-mouse-support-possible-p))
278 (cond ((and (vm-mouse-xemacs-mouse-p)
279 (or (button-press-event-p last-command-event)
280 (button-release-event-p last-command-event)
281 (menu-event-p last-command-event)))
282 (vm-mouse-read-string prompt completion-list multi-word))
283 ((and (vm-mouse-fsfemacs-mouse-p)
284 (listp last-nonmenu-event))
285 (vm-mouse-read-string prompt completion-list multi-word))
286 (t
287 (vm-keyboard-read-string prompt completion-list multi-word)))
288 (vm-keyboard-read-string prompt completion-list multi-word)))
289
290 (defun vm-read-number (prompt)
291 (let (result)
292 (while
293 (null
294 (string-match "^[ \t]*-?[0-9]+" (setq result (read-string prompt)))))
295 (string-to-int result)))
296
297 (defun vm-read-password (prompt &optional confirm)
298 "Read and return a password from the minibuffer, prompting with PROMPT.
299 Optional second argument CONFIRM non-nil means that the user will be asked
300 to type the password a second time for confirmation and if there is a
301 mismatch, the process is repeated.
302
303 Line editing keys are:
304 C-h, DEL rubout
305 C-u, C-x line kill
306 C-q, C-v literal next"
307 (catch 'return-value
308 (save-excursion
309 (let ((cursor-in-echo-area t)
310 (echo-keystrokes 0)
311 (input-buffer nil)
312 (help-form nil)
313 (xxx "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
314 (string nil)
315 char done form)
316 (unwind-protect
317 (save-excursion
318 (setq input-buffer (get-buffer-create " *password*"))
319 (set-buffer input-buffer)
320 (while t
321 (erase-buffer)
322 (vm-unsaved-message "%s%s" prompt
323 (vm-truncate-string xxx (buffer-size)))
324 (while (not (memq (setq char (read-char)) '(?\C-m ?\C-j)))
325 (if (setq form
326 (cdr
327 (assq char
328 '((?\C-h . (delete-char -1))
329 (?\C-? . (delete-char -1))
330 (?\C-u . (delete-region 1 (point)))
331 (?\C-x . (delete-region 1 (point)))
332 (?\C-q . (quoted-insert 1))
333 (?\C-v . (quoted-insert 1))))))
334 (condition-case error-data
335 (eval form)
336 (error t))
337 (insert char))
338 (vm-unsaved-message "%s%s" prompt
339 (vm-truncate-string xxx (buffer-size))))
340 (cond ((and confirm string)
341 (cond ((not (string= string (buffer-string)))
342 (vm-unsaved-message
343 (concat prompt
344 (vm-truncate-string xxx (buffer-size))
345 " [Mismatch... try again.]"))
346 (ding)
347 (sit-for 2)
348 (setq string nil))
349 (t (throw 'return-value string))))
350 (confirm
351 (setq string (buffer-string))
352 (vm-unsaved-message
353 (concat prompt
354 (vm-truncate-string xxx (buffer-size))
355 " [Retype to confirm...]"))
356 (sit-for 2))
357 (t
358 (vm-unsaved-message "")
359 (throw 'return-value (buffer-string))))))
360 (and input-buffer (kill-buffer input-buffer)))))))
361
362 (defun vm-keyboard-read-file-name (prompt &optional dir default
363 must-match initial history)
364 "Like read-file-name, except HISTORY's value is unaltered."
365 (let ((oldvalue (symbol-value history)))
366 (unwind-protect
367 (condition-case nil
368 (read-file-name prompt dir default must-match initial history)
369 (wrong-number-of-arguments
370 (if history
371 (let ((file-name-history (symbol-value history))
372 file)
373 (setq file
374 (read-file-name prompt dir default must-match initial))
375 file )
376 (read-file-name prompt dir default must-match initial))))
377 (and history (set history oldvalue)))))
378
379 (defun vm-read-file-name (prompt &optional dir default
380 must-match initial history)
381 "Like read-file-name, except a mouse interface is used if a mouse
382 click mouse triggered the current command."
383 (if (vm-mouse-support-possible-p)
384 (cond ((and (vm-mouse-xemacs-mouse-p)
385 (or (button-press-event-p last-command-event)
386 (button-release-event-p last-command-event)
387 (menu-event-p last-command-event)))
388 (vm-mouse-read-file-name prompt dir default
389 must-match initial history))
390 ((and (vm-mouse-fsfemacs-mouse-p)
391 (listp last-nonmenu-event))
392 (vm-mouse-read-file-name prompt dir default
393 must-match initial history))
394 (t
395 (vm-keyboard-read-file-name prompt dir default
396 must-match initial history)))
397 (vm-keyboard-read-file-name prompt dir default
398 must-match initial history)))
399
400