diff options
| -rw-r--r-- | lisp/icomplete.el | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/lisp/icomplete.el b/lisp/icomplete.el new file mode 100644 index 00000000000..cad24952a26 --- /dev/null +++ b/lisp/icomplete.el | |||
| @@ -0,0 +1,244 @@ | |||
| 1 | ;;; icomplete.el - minibuffer completion incremental feedback | ||
| 2 | ;;; This package is in the publid domain. | ||
| 3 | |||
| 4 | ;;; Author: Ken Manheimer <klm@nist.gov> | ||
| 5 | ;;; Maintainer: Ken Manheimer <klm@nist.gov> | ||
| 6 | ;;; Version: icomplete.el,v 3.2 1993/11/19 18:42:52 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 | ;;; This will not work on Emacs 18 versions - there may be a version | ||
| 19 | ;;; for v18 in the elisp archives, at archive.cis.ohio-state.edu, in | ||
| 20 | ;;; /pub/gnu/emacs/elisp-archive. | ||
| 21 | |||
| 22 | ;;; Code: | ||
| 23 | |||
| 24 | ;;;_ + Provide | ||
| 25 | (provide 'icomplete) | ||
| 26 | |||
| 27 | ;;;_ + User Customization variables | ||
| 28 | ;;;_ = icomplete-inhibit | ||
| 29 | (defvar icomplete-inhibit nil | ||
| 30 | "*Set this variable to t at any time to inhibit icomplete.") | ||
| 31 | |||
| 32 | ;;;_ + Setup | ||
| 33 | ;;;_ - Internal Variables | ||
| 34 | ;;;_ = icomplete-eoinput 1 | ||
| 35 | (defvar icomplete-eoinput 1 | ||
| 36 | "Point where minibuffer input ends and completion info begins.") | ||
| 37 | (make-variable-buffer-local 'icomplete-eoinput) | ||
| 38 | ;;;_ > icomplete-prime-session () | ||
| 39 | (defun icomplete-prime-session () | ||
| 40 | |||
| 41 | "Prep emacs v 19 for icompletion. For emacs v19.18 and later revs, | ||
| 42 | icomplete is installed in 'minibuffer-setup-hook'. Global pre- and | ||
| 43 | post-command-hook functions are used in v19.17 and earlier revs." | ||
| 44 | |||
| 45 | (let* ((v19-rev (and (string-match "^19\\.\\([0-9]+\\)" emacs-version) | ||
| 46 | (string-to-int (substring emacs-version | ||
| 47 | (match-beginning 1) | ||
| 48 | (match-end 1)))))) | ||
| 49 | |||
| 50 | (cond ((and v19-rev ; emacs v 19, some rev, | ||
| 51 | (> v19-rev 17)) | ||
| 52 | ;; Post v19rev17, has minibuffer-setup-hook, use it: | ||
| 53 | (add-hook 'minibuffer-setup-hook 'icomplete-prime-minibuffer)) | ||
| 54 | (v19-rev | ||
| 55 | ;; v19rev17 and prior (including lucid): use global | ||
| 56 | ;; pre- and post-command-hooks, instead: | ||
| 57 | (add-hook 'pre-command-hook 'icomplete-pre-command-hook 'append) | ||
| 58 | (add-hook 'post-command-hook | ||
| 59 | 'icomplete-post-command-hook 'append)) | ||
| 60 | ((format "icomplete: non v19 emacs, %s - %s" | ||
| 61 | emacs-version "try elisp-archive icomplete"))))) | ||
| 62 | ;;;_ > icomplete-prime-minibuffer () | ||
| 63 | (defun icomplete-prime-minibuffer () | ||
| 64 | |||
| 65 | "Prep emacs, v 19.18 or later, for icomplete. \(icomplete-prime- | ||
| 66 | session establishes global hooks, instead, in emacs 19 versions 19.17 | ||
| 67 | and prior.\) Run via minibuffer-setup-hook \(emacs 19.18 or later\), | ||
| 68 | adds icomplete pre- and post-command hooks to do icomplete display | ||
| 69 | management." | ||
| 70 | |||
| 71 | ;; We append the hooks because preliminary version of blink-paren | ||
| 72 | ;; post-command-hook i have interferes with proper operation of | ||
| 73 | ;; minibuffer quit. | ||
| 74 | (make-local-variable 'pre-command-hook) | ||
| 75 | (make-local-variable 'post-command-hook) | ||
| 76 | (add-hook 'pre-command-hook 'icomplete-pre-command-hook) | ||
| 77 | (add-hook 'post-command-hook 'icomplete-post-command-hook)) | ||
| 78 | ;;;_ > icomplete-window-minibuffer-p () | ||
| 79 | (defmacro icomplete-window-minibuffer-p () | ||
| 80 | |||
| 81 | "Returns non-nil if current window is a minibuffer window. | ||
| 82 | Trivially equates to '(window-minibuffer-p nil)', with the nil | ||
| 83 | provided in case the argument is not optional in Lucid emacs (which | ||
| 84 | some net correspondance seems to indicate)." | ||
| 85 | |||
| 86 | '(window-minibuffer-p nil)) | ||
| 87 | |||
| 88 | ;;;_ + Completion | ||
| 89 | ;;;_ - Completion feedback hooks | ||
| 90 | ;;;_ > icomplete-pre-command-hook () | ||
| 91 | (defun icomplete-pre-command-hook () | ||
| 92 | "Cleanup completions exhibit before user's new input (or whatever) is dealt | ||
| 93 | with." | ||
| 94 | (if (and (icomplete-window-minibuffer-p) | ||
| 95 | (not (symbolp minibuffer-completion-table)) | ||
| 96 | (not icomplete-inhibit)) | ||
| 97 | (if (and (boundp 'icomplete-eoinput) | ||
| 98 | icomplete-eoinput) | ||
| 99 | (if (> icomplete-eoinput (point-max)) | ||
| 100 | ;; Oops, got rug pulled out from under us - reinit: | ||
| 101 | (setq icomplete-eoinput (point-max)) | ||
| 102 | (let ((buffer-undo-list buffer-undo-list )) ; prevent entry | ||
| 103 | (delete-region icomplete-eoinput (point-max)))) | ||
| 104 | (make-local-variable 'icomplete-eoinput) | ||
| 105 | (setq icomplete-eoinput 1)))) | ||
| 106 | ;;;_ > icomplete-post-command-hook () | ||
| 107 | (defun icomplete-post-command-hook () | ||
| 108 | "Exhibit completions, leaving icomplete-eoinput with position where user | ||
| 109 | input leaves off and exhibit begins, so icomplete-pre-command-hook can | ||
| 110 | subsequently cleanup." | ||
| 111 | (if (and (icomplete-window-minibuffer-p) ; ... in a minibuffer. | ||
| 112 | (not icomplete-inhibit) ; ... not specifically inhibited. | ||
| 113 | ;(sit-for 0) ; ... redisplay and if there's input | ||
| 114 | ; waiting, then don't icomplete | ||
| 115 | ; (stigs suggestion) (too jumpy!) | ||
| 116 | ;; Inhibit for file-name and other custom-func completions: | ||
| 117 | (not (symbolp minibuffer-completion-table)) | ||
| 118 | ) | ||
| 119 | (let ((buffer-undo-list buffer-undo-list )) ; prevent entry | ||
| 120 | (icomplete-exhibit)))) | ||
| 121 | ;;;_ > icomplete-window-setup-hook () | ||
| 122 | (defun icomplete-window-setup-hook () | ||
| 123 | "Exhibit completions, leaving icomplete-eoinput with position where user | ||
| 124 | input leaves off and exhibit begins, so icomplete-pre-command-hook can | ||
| 125 | subsequently cleanup." | ||
| 126 | (if (and (icomplete-window-minibuffer-p) ; ... in a minibuffer. | ||
| 127 | ) | ||
| 128 | (message "ic ws doing")(sit-for 1))) | ||
| 129 | ;;;_ > icomplete-exhibit () | ||
| 130 | (defun icomplete-exhibit () | ||
| 131 | "Exhibit completions, leaving icomplete-eoinput with position where user | ||
| 132 | input leaves off and exhibit begins, so icomplete-pre-command-hook can | ||
| 133 | subsequently cleanup." | ||
| 134 | (if (not (symbolp minibuffer-completion-table)) | ||
| 135 | (let ((contents (buffer-substring (point-min)(point-max))) | ||
| 136 | (buffer-undo-list t)) | ||
| 137 | (save-excursion | ||
| 138 | (goto-char (point-max)) | ||
| 139 | ; Register the end of input, so we | ||
| 140 | ; know where the extra stuff | ||
| 141 | ; (match-status info) begins: | ||
| 142 | (if (not (boundp 'icomplete-eoinput)) | ||
| 143 | ;; In case it got wiped out by major mode business: | ||
| 144 | (make-local-variable 'icomplete-eoinput)) | ||
| 145 | (setq icomplete-eoinput (point)) | ||
| 146 | ; Insert the match-status information: | ||
| 147 | (if (> (point-max) 1) | ||
| 148 | (insert-string | ||
| 149 | (icomplete-prompt contents | ||
| 150 | minibuffer-completion-table | ||
| 151 | minibuffer-completion-predicate | ||
| 152 | (not | ||
| 153 | minibuffer-completion-confirm)))))))) | ||
| 154 | |||
| 155 | ;;;_ - Completion feedback producer | ||
| 156 | ;;;_ > icomplete-prompt (name candidates predicate require-match) | ||
| 157 | (defun icomplete-prompt (name candidates predicate require-match) | ||
| 158 | "Identify prospective candidates for minibuffer completion. | ||
| 159 | |||
| 160 | The display is updated with each minibuffer keystroke when icomplete | ||
| 161 | is enabled \(by loading the 'icomplete' elisp package\) and doing | ||
| 162 | minibuffer completion. | ||
| 163 | |||
| 164 | Prospective completion suffixes (if any) are displayed, bracketed by | ||
| 165 | one of \(), \[], or \{} pairs. The choice of brackets is as follows: | ||
| 166 | |||
| 167 | \(...) - a single prospect is identified and matching is enforced, | ||
| 168 | \[...] - a single prospect is identified but matching is optional, or | ||
| 169 | \{...} - multiple prospects, separated by commas, are indicated, and | ||
| 170 | further input is required to distingish a single one. | ||
| 171 | |||
| 172 | The displays for disambiguous matches have \" [Matched]\" appended | ||
| 173 | \(whether complete or not), or \" \[No matches]\", if no eligible | ||
| 174 | matches exist." | ||
| 175 | |||
| 176 | (let ((comps (all-completions name candidates predicate)) | ||
| 177 | ; "-determined" - only one candidate | ||
| 178 | (open-bracket-determined (if require-match "(" "[")) | ||
| 179 | (close-bracket-determined (if require-match ")" "]")) | ||
| 180 | ;"-prospects" - more than one candidate | ||
| 181 | (open-bracket-prospects "{") | ||
| 182 | (close-bracket-prospects "}") | ||
| 183 | ) | ||
| 184 | (cond ((null comps) (format " %sNo matches%s" | ||
| 185 | open-bracket-determined | ||
| 186 | close-bracket-determined)) | ||
| 187 | ((null (cdr comps)) ;one match | ||
| 188 | (concat (if (and (> (length (car comps)) | ||
| 189 | (length name))) | ||
| 190 | (concat open-bracket-determined | ||
| 191 | (substring (car comps) (length name)) | ||
| 192 | close-bracket-determined) | ||
| 193 | "") | ||
| 194 | " [Matched]")) | ||
| 195 | (t ;multiple matches | ||
| 196 | (let* ((most (try-completion name candidates predicate)) | ||
| 197 | (most-len (length most)) | ||
| 198 | most-is-exact | ||
| 199 | (alternatives | ||
| 200 | (apply | ||
| 201 | 'concat | ||
| 202 | (cdr (apply 'append | ||
| 203 | (mapcar '(lambda (com) | ||
| 204 | (if (= (length com) most-len) | ||
| 205 | ;; Most is one exact match, | ||
| 206 | ;; note that and leave out | ||
| 207 | ;; for later indication: | ||
| 208 | (progn | ||
| 209 | (setq most-is-exact t) | ||
| 210 | ()) | ||
| 211 | (list "," | ||
| 212 | (substring com | ||
| 213 | most-len)))) | ||
| 214 | comps)))))) | ||
| 215 | (concat (and (> most-len (length name)) | ||
| 216 | (concat open-bracket-determined | ||
| 217 | (substring most (length name)) | ||
| 218 | close-bracket-determined)) | ||
| 219 | open-bracket-prospects | ||
| 220 | (if most-is-exact | ||
| 221 | (concat "," alternatives) | ||
| 222 | alternatives) | ||
| 223 | close-bracket-prospects)))))) | ||
| 224 | |||
| 225 | ;;;_ + Initialization | ||
| 226 | (icomplete-prime-session) | ||
| 227 | |||
| 228 | ;;;_* Local emacs vars. | ||
| 229 | '( | ||
| 230 | Local variables: | ||
| 231 | eval: (save-excursion | ||
| 232 | (if (not (condition-case err (outline-mode t) | ||
| 233 | (wrong-number-of-arguments nil))) | ||
| 234 | (progn | ||
| 235 | (message | ||
| 236 | "Allout outline-mode not loaded, not adjusting buffer exposure") | ||
| 237 | (sit-for 1)) | ||
| 238 | (message "Adjusting '%s' visibility" (buffer-name)) | ||
| 239 | (outline-lead-with-comment-string ";;;_") | ||
| 240 | (goto-char 0) | ||
| 241 | (outline-exposure -1 0))) | ||
| 242 | End:) | ||
| 243 | |||
| 244 | ;;; icomplete.el ends here | ||