]> code.delx.au - gnu-emacs/blob - lisp/icomplete.el
(icomplete-pre-command-hook): Reconciled with keyboard macro operation.
[gnu-emacs] / lisp / icomplete.el
1 ;;; icomplete.el - minibuffer completion incremental feedback
2 ;;; This package is in the public domain.
3
4 ;;; Author: Ken Manheimer <klm@nist.gov>
5 ;;; Maintainer: Ken Manheimer <klm@nist.gov>
6 ;;; Version: icomplete.el,v 3.3 1993/12/11 11:27:35 klm Exp klm
7 ;;; Created: Mar 1993 klm@nist.gov - first release to usenet
8 ;;; Keywords: help, abbrev
9
10 ;;; Commentary:
11
12 ;;; Loading this package implements a more finely-grained completion
13 ;;; feedback scheme, indicating, within the minibuffer, the
14 ;;; prospective minibuffer completion candidates, as you type. See
15 ;;; the documentation string for 'icomplete-prompt' for a specific
16 ;;; description of icompletion.
17
18 ;;; It should run on most version of Emacs 19 (including Lucid emacs
19 ;;; 19 - thanks to the efforts of Colin Rafferty (craffert@lehman.com)
20 ;;; - thanks, Colin!) This version of icomplete will *not* work on
21 ;;; Emacs 18 versions - the elisp archives, at
22 ;;; archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive, probably
23 ;;; still has a version that works in GNU Emacs v18.
24
25 ;;; Thanks to Colin Rafferty for assistance reconciling for lemacs,
26 ;;; and to Michael Cook, who implemented an incremental completion
27 ;;; style in his 'iswitch' functions that served as the basis for
28 ;;; icomplete.
29
30 ;;; Code:
31
32 ;;;_* (Allout outline root topic. Please leave this in.)
33
34 ;;;_ + Provide
35 (provide 'icomplete)
36
37 ;;;_ + User Customization variables
38 ;;;_ = icomplete-inhibit
39 (defvar icomplete-inhibit nil
40 "*Set this variable to t at any time to inhibit icomplete.")
41
42 ;;;_ + Internal Variables
43 ;;;_ = icomplete-eoinput 1
44 (defvar icomplete-eoinput 1
45 "Point where minibuffer input ends and completion info begins.")
46 (make-variable-buffer-local 'icomplete-eoinput)
47
48 ;;;_ > icomplete-prime-session ()
49 ;;;###autoload
50 (defun icomplete-prime-session ()
51
52 "Prep emacs v 19 for more finely-grained minibuffer completion-feedback.
53
54 You can inhibit icomplete after loading by setting icomplete-inhibit
55 non-nil. Set the var back to nil to re-enable icomplete."
56
57 ;; For emacs v19.18 and later revs, the icomplete key function is
58 ;; installed in 'minibuffer-setup-hook'. Global pre- and post-
59 ;; command-hook functions are used in v19.17 and earlier v19 revs."
60
61 (let* ((v19-rev (and (string-match "^19\\.\\([0-9]+\\)" emacs-version)
62 (string-to-int (substring emacs-version
63 (match-beginning 1)
64 (match-end 1))))))
65
66 (cond ((and v19-rev ; emacs v 19, some rev,
67 (> v19-rev 17))
68 ;; Post v19rev17, has minibuffer-setup-hook, use it:
69 (add-hook 'minibuffer-setup-hook 'icomplete-prime-minibuffer))
70 (v19-rev
71 ;; v19rev17 and prior (including lucid): use global
72 ;; pre- and post-command-hooks, instead:
73 (add-hook 'pre-command-hook 'icomplete-pre-command-hook 'append)
74 (add-hook 'post-command-hook
75 'icomplete-post-command-hook 'append))
76 ((format "icomplete: non v19 emacs, %s - %s"
77 emacs-version "try elisp-archive icomplete")))))
78 ;;;_ > icomplete-prime-minibuffer ()
79 (defun icomplete-prime-minibuffer ()
80
81 "Prep emacs, v 19.18 or later, for icomplete.
82
83 \(In emacs v19.17 and earlier, and in lemacs, icomplete-prime-session
84 is used, instead to establish global hooks.\)
85
86 Run via minibuffer-setup-hook, adds icomplete pre- and post-command
87 hooks at the start of each minibuffer."
88
89 ;; Append the hooks to avoid as much as posssible interference from
90 ;; other hooks that foul up minibuffer quit.
91 (make-local-variable 'pre-command-hook)
92 (make-local-variable 'post-command-hook)
93 (add-hook 'pre-command-hook 'icomplete-pre-command-hook)
94 (add-hook 'post-command-hook 'icomplete-post-command-hook))
95 ;;;_ > icomplete-window-minibuffer-p ()
96 (defmacro icomplete-window-minibuffer-p ()
97
98 "Returns non-nil if current window is a minibuffer window.
99
100 Trivially equates to '(window-minibuffer-p (selected-window))', with
101 the argument definitely provided for emacsen that require it, eg Lucid."
102
103 '(window-minibuffer-p (selected-window)))
104
105 ;;;_ + Completion
106
107 ;;;_ - Completion feedback hooks
108 ;;;_ > icomplete-pre-command-hook ()
109 (defun icomplete-pre-command-hook ()
110 "Cleanup completions display before user's new command is dealt with."
111 (if (and (icomplete-window-minibuffer-p)
112 (not executing-macro)
113 (not (symbolp minibuffer-completion-table))
114 (not icomplete-inhibit))
115 (if (and (boundp 'icomplete-eoinput)
116 icomplete-eoinput)
117 (if (> icomplete-eoinput (point-max))
118 ;; Oops, got rug pulled out from under us - reinit:
119 (setq icomplete-eoinput (point-max))
120 (let ((buffer-undo-list buffer-undo-list )) ; prevent entry
121 (delete-region icomplete-eoinput (point-max))))
122 ;; Reestablish the local variable 'cause minibuffer-setup is weird:
123 (make-local-variable 'icomplete-eoinput)
124 (setq icomplete-eoinput 1))))
125 ;;;_ > icomplete-post-command-hook ()
126 (defun icomplete-post-command-hook ()
127 "Exhibit completions, leaving bookkeeping so pre- hook can tidy up."
128
129 (if (and (icomplete-window-minibuffer-p) ; ... in a minibuffer.
130 (not executing-macro)
131 (not icomplete-inhibit) ; ... not specifically inhibited.
132 ;(sit-for 0) ; ... redisplay and if there's input
133 ; waiting, then don't icomplete
134 ; (stigs suggestion) (too jumpy!)
135 ;; Inhibit for file-name and other custom-func completions:
136 (not (symbolp minibuffer-completion-table))
137 )
138 (let ((buffer-undo-list buffer-undo-list )) ; prevent entry
139 (icomplete-exhibit))))
140 ;;;_ > icomplete-window-setup-hook ()
141 (defun icomplete-window-setup-hook ()
142 "Exhibit completions, leaving bookkeeping so pre- hook can tidy up."
143
144 (if (and (icomplete-window-minibuffer-p) ; ... in a minibuffer.
145 )
146 (message "ic ws doing")(sit-for 1)))
147 ;;;_ > icomplete-exhibit ()
148 (defun icomplete-exhibit ()
149 "Insert icomplete completions display."
150 (if (not (symbolp minibuffer-completion-table))
151 (let ((contents (buffer-substring (point-min)(point-max)))
152 (buffer-undo-list t))
153 (save-excursion
154 (goto-char (point-max))
155 ; Register the end of input, so we
156 ; know where the extra stuff
157 ; (match-status info) begins:
158 (if (not (boundp 'icomplete-eoinput))
159 ;; In case it got wiped out by major mode business:
160 (make-local-variable 'icomplete-eoinput))
161 (setq icomplete-eoinput (point))
162 ; Insert the match-status information:
163 (if (> (point-max) 1)
164 (insert-string
165 (icomplete-prompt contents
166 minibuffer-completion-table
167 minibuffer-completion-predicate
168 (not
169 minibuffer-completion-confirm))))))))
170
171 ;;;_ - Completion feedback producer
172 ;;;_ > icomplete-prompt (name candidates predicate require-match)
173 (defun icomplete-prompt (name candidates predicate require-match)
174 "Identify prospective candidates for minibuffer completion.
175
176 The display is updated with each minibuffer keystroke during
177 minibuffer completion.
178
179 Prospective completion suffixes (if any) are displayed, bracketed by
180 one of \(), \[], or \{} pairs. The choice of brackets is as follows:
181
182 \(...) - a single prospect is identified and matching is enforced,
183 \[...] - a single prospect is identified but matching is optional, or
184 \{...} - multiple prospects, separated by commas, are indicated, and
185 further input is required to distingish a single one.
186
187 The displays for disambiguous matches have \" [Matched]\" appended
188 \(whether complete or not), or \" \[No matches]\", if no eligible
189 matches exist."
190
191 (let ((comps (all-completions name candidates predicate))
192 ; "-determined" - only one candidate
193 (open-bracket-determined (if require-match "(" "["))
194 (close-bracket-determined (if require-match ")" "]"))
195 ;"-prospects" - more than one candidate
196 (open-bracket-prospects "{")
197 (close-bracket-prospects "}")
198 )
199 (cond ((null comps) (format " %sNo matches%s"
200 open-bracket-determined
201 close-bracket-determined))
202 ((null (cdr comps)) ;one match
203 (concat (if (and (> (length (car comps))
204 (length name)))
205 (concat open-bracket-determined
206 (substring (car comps) (length name))
207 close-bracket-determined)
208 "")
209 " [Matched]"))
210 (t ;multiple matches
211 (let* ((most (try-completion name candidates predicate))
212 (most-len (length most))
213 most-is-exact
214 (alternatives
215 (apply
216 'concat
217 (cdr (apply 'append
218 (mapcar '(lambda (com)
219 (if (= (length com) most-len)
220 ;; Most is one exact match,
221 ;; note that and leave out
222 ;; for later indication:
223 (progn
224 (setq most-is-exact t)
225 ())
226 (list ","
227 (substring com
228 most-len))))
229 comps))))))
230 (concat (and (> most-len (length name))
231 (concat open-bracket-determined
232 (substring most (length name))
233 close-bracket-determined))
234 open-bracket-prospects
235 (if most-is-exact
236 (concat "," alternatives)
237 alternatives)
238 close-bracket-prospects))))))
239
240 ;;;_ - Initialization
241 (icomplete-prime-session)
242
243
244 ;;;_ + Local emacs vars.
245 '(
246 Local variables:
247 eval: (save-excursion
248 (if (not (condition-case err (outline-mode t)
249 (wrong-number-of-arguments nil)))
250 (progn
251 (message
252 "Allout outline-mode not loaded, not adjusting buffer exposure")
253 (sit-for 1))
254 (message "Adjusting '%s' visibility" (buffer-name))
255 (outline-lead-with-comment-string ";;;_")
256 (goto-char 0)
257 (outline-exposure -1 0)))
258 End:)
259
260 ;;; icomplete.el ends here
261