aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/icomplete.el
blob: a58229588b28b4c44c849d5c8da30492b4d93294 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
;;; icomplete.el - minibuffer completion incremental feedback
;;; This package is in the public domain.

;;; Author: Ken Manheimer <[email protected]>
;;; Maintainer: Ken Manheimer <[email protected]>
;;; Version: icomplete.el,v 3.3 1993/12/11 11:27:35 klm Exp klm
;;; Created: Mar 1993 [email protected] - first release to usenet
;;; Keywords: help, abbrev

;;; Commentary:

;;; Loading this package implements a more finely-grained completion
;;; feedback scheme, indicating, within the minibuffer, the
;;; prospective minibuffer completion candidates, as you type.  See
;;; the documentation string for 'icomplete-prompt' for a specific
;;; description of icompletion.

;;; It should run on most version of Emacs 19 (including Lucid emacs
;;; 19 - thanks to the efforts of Colin Rafferty ([email protected])
;;; - thanks, Colin!)  This version of icomplete will *not* work on
;;; Emacs 18 versions - the elisp archives, at
;;; archive.cis.ohio-state.edu:/pub/gnu/emacs/elisp-archive, probably
;;; still has a version that works in GNU Emacs v18.

;;; Thanks to Colin Rafferty for assistance reconciling for lemacs,
;;; and to Michael Cook, who implemented an incremental completion
;;; style in his 'iswitch' functions that served as the basis for
;;; icomplete.

;;; Code:

;;;_* (Allout outline root topic.  Please leave this in.)

;;;_ + Provide
(provide 'icomplete)

;;;_ + User Customization variables
;;;_  = icomplete-inhibit
(defvar icomplete-inhibit nil
  "*Set this variable to t at any time to inhibit icomplete.")

;;;_ + Internal Variables
;;;_  = icomplete-eoinput 1
(defvar icomplete-eoinput 1
  "Point where minibuffer input ends and completion info begins.")
(make-variable-buffer-local 'icomplete-eoinput)

;;;_ > icomplete-prime-session ()
;;;###autoload
(defun icomplete-prime-session ()

  "Prep emacs v 19 for more finely-grained minibuffer completion-feedback.

You can inhibit icomplete after loading by setting icomplete-inhibit
non-nil.  Set the var back to nil to re-enable icomplete."

  ;; For emacs v19.18 and later revs, the icomplete key function is
  ;; installed in 'minibuffer-setup-hook'.  Global pre- and post-
  ;; command-hook functions are used in v19.17 and earlier v19 revs."

  (let* ((v19-rev (and (string-match "^19\\.\\([0-9]+\\)" emacs-version)
		       (string-to-int (substring emacs-version
						 (match-beginning 1)
						 (match-end 1))))))

    (cond ((and v19-rev			; emacs v 19, some rev,
		(> v19-rev 17))
	   ;; Post v19rev17, has minibuffer-setup-hook, use it:
	   (add-hook 'minibuffer-setup-hook 'icomplete-prime-minibuffer))
	  (v19-rev
	   ;; v19rev17 and prior (including lucid): use global
	   ;; pre- and post-command-hooks, instead:
	   (add-hook 'pre-command-hook 'icomplete-pre-command-hook 'append)
	   (add-hook 'post-command-hook
		     'icomplete-post-command-hook 'append))
	  ((format "icomplete: non v19 emacs, %s - %s"
		   emacs-version "try elisp-archive icomplete")))))
;;;_ > icomplete-prime-minibuffer ()
(defun icomplete-prime-minibuffer ()

  "Prep emacs, v 19.18 or later, for icomplete.

\(In emacs v19.17 and earlier, and in lemacs, icomplete-prime-session
is used, instead to establish global hooks.\)

Run via minibuffer-setup-hook, adds icomplete pre- and post-command
hooks at the start of each minibuffer."

  ;; Append the hooks to avoid as much as posssible interference from
  ;; other hooks that foul up minibuffer quit.
  (make-local-variable 'pre-command-hook)
  (make-local-variable 'post-command-hook)
  (add-hook 'pre-command-hook 'icomplete-pre-command-hook)
  (add-hook 'post-command-hook 'icomplete-post-command-hook))
;;;_ > icomplete-window-minibuffer-p ()
(defmacro icomplete-window-minibuffer-p ()

  "Returns non-nil if current window is a minibuffer window.

Trivially equates to '(window-minibuffer-p (selected-window))', with
the argument definitely provided for emacsen that require it, eg Lucid."

  '(window-minibuffer-p (selected-window)))

;;;_ + Completion

;;;_  - Completion feedback hooks
;;;_   > icomplete-pre-command-hook ()
(defun icomplete-pre-command-hook ()
  "Cleanup completions display before user's new command is dealt with."
  (if (and (icomplete-window-minibuffer-p)
	   (not executing-macro)
	   (not (symbolp minibuffer-completion-table))
	   (not icomplete-inhibit))
      (if (and (boundp 'icomplete-eoinput)
	       icomplete-eoinput)
	  (if (> icomplete-eoinput (point-max))
	      ;; Oops, got rug pulled out from under us - reinit:
	      (setq icomplete-eoinput (point-max))
	    (let ((buffer-undo-list buffer-undo-list )) ; prevent entry
	      (delete-region icomplete-eoinput (point-max))))
	;; Reestablish the local variable 'cause minibuffer-setup is weird:
	(make-local-variable 'icomplete-eoinput)
	(setq icomplete-eoinput 1))))
;;;_   > icomplete-post-command-hook ()
(defun icomplete-post-command-hook ()
  "Exhibit completions, leaving bookkeeping so pre- hook can tidy up."

  (if (and (icomplete-window-minibuffer-p)	; ... in a minibuffer.
	   (not executing-macro)
	   (not icomplete-inhibit)	; ... not specifically inhibited.
	   ;(sit-for 0)			; ... redisplay and if there's input
					; waiting, then don't icomplete
					; (stigs suggestion) (too jumpy!)
	   ;; Inhibit for file-name and other custom-func completions:
	   (not (symbolp minibuffer-completion-table))
	   )
      (let ((buffer-undo-list buffer-undo-list ))	; prevent entry
	(icomplete-exhibit))))
;;;_   > icomplete-window-setup-hook ()
(defun icomplete-window-setup-hook ()
  "Exhibit completions, leaving bookkeeping so pre- hook can tidy up."

  (if (and (icomplete-window-minibuffer-p)	; ... in a minibuffer.
	   )
      (message "ic ws doing")(sit-for 1)))
;;;_   > icomplete-exhibit ()
(defun icomplete-exhibit ()
  "Insert icomplete completions display."
  (if (not (symbolp minibuffer-completion-table))
      (let ((contents (buffer-substring (point-min)(point-max)))
	    (buffer-undo-list t))
	(save-excursion
	  (goto-char (point-max))
                                        ; Register the end of input, so we
                                        ; know where the extra stuff
                                        ; (match-status info) begins:
	  (if (not (boundp 'icomplete-eoinput))
	      ;; In case it got wiped out by major mode business:
	      (make-local-variable 'icomplete-eoinput))
	  (setq icomplete-eoinput (point))
                                        ; Insert the match-status information:
	  (if (> (point-max) 1)
	      (insert-string
		(icomplete-prompt contents
				  minibuffer-completion-table
				  minibuffer-completion-predicate
				  (not
				   minibuffer-completion-confirm))))))))

;;;_  - Completion feedback producer
;;;_   > icomplete-prompt (name candidates predicate require-match)
(defun icomplete-prompt (name candidates predicate require-match)
  "Identify prospective candidates for minibuffer completion.

The display is updated with each minibuffer keystroke during
minibuffer completion.

Prospective completion suffixes (if any) are displayed, bracketed by
one of \(), \[], or \{} pairs.  The choice of brackets is as follows:

  \(...) - a single prospect is identified and matching is enforced,
  \[...] - a single prospect is identified but matching is optional, or
  \{...} - multiple prospects, separated by commas, are indicated, and
          further input is required to distingish a single one.

The displays for disambiguous matches have \" [Matched]\" appended
\(whether complete or not), or \" \[No matches]\", if no eligible
matches exist."

  (let ((comps (all-completions name candidates predicate))
                                        ; "-determined" - only one candidate
        (open-bracket-determined (if require-match "(" "["))
        (close-bracket-determined (if require-match ")" "]"))
                                        ;"-prospects" - more than one candidate
        (open-bracket-prospects "{")
        (close-bracket-prospects "}")
        )
    (cond ((null comps) (format " %sNo matches%s"
                                open-bracket-determined
                                close-bracket-determined))
          ((null (cdr comps))           ;one match
           (concat (if (and (> (length (car comps))
                               (length name)))
                       (concat open-bracket-determined
                               (substring (car comps) (length name))
                               close-bracket-determined)
                     "")
                   " [Matched]"))
          (t                            ;multiple matches
           (let* ((most (try-completion name candidates predicate))
                  (most-len (length most))
                  most-is-exact
                  (alternatives
                   (apply
                    'concat
                    (cdr (apply 'append
                                (mapcar '(lambda (com)
                                           (if (= (length com) most-len)
                                               ;; Most is one exact match,
                                               ;; note that and leave out
                                               ;; for later indication:
                                               (progn
                                                 (setq most-is-exact t)
                                                 ())
                                             (list ","
                                                   (substring com
                                                              most-len))))
                                        comps))))))
             (concat (and (> most-len (length name))
                          (concat open-bracket-determined
                                  (substring most (length name))
                                  close-bracket-determined))
                     open-bracket-prospects
                     (if most-is-exact
                         (concat "," alternatives)
                       alternatives)
                     close-bracket-prospects))))))

;;;_  - Initialization
(icomplete-prime-session)


;;;_ + Local emacs vars.
'(
Local variables:
eval: (save-excursion
        (if (not (condition-case err (outline-mode t)
                   (wrong-number-of-arguments nil)))
            (progn
              (message
               "Allout outline-mode not loaded, not adjusting buffer exposure")
              (sit-for 1))
          (message "Adjusting '%s' visibility" (buffer-name))
          (outline-lead-with-comment-string ";;;_")
          (goto-char 0)
          (outline-exposure -1 0)))
End:)

;;; icomplete.el ends here