1;;; icomplete.el --- minibuffer completion incremental feedback 2 3;; Copyright (C) 1992, 1993, 1994, 1997, 1999, 2001, 2002, 2003, 4;; 2004, 2005, 2006, 2007 Free Software Foundation, Inc. 5 6;; Author: Ken Manheimer <klm@i.am> 7;; Maintainer: Ken Manheimer <klm@i.am> 8;; Created: Mar 1993 Ken Manheimer, klm@nist.gov - first release to usenet 9;; Last update: Ken Manheimer <klm@i.am>, 11/18/1999. 10;; Keywords: help, abbrev 11 12;; This file is part of GNU Emacs. 13 14;; GNU Emacs is free software; you can redistribute it and/or modify 15;; it 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;; GNU Emacs is distributed in the hope that it will be useful, 20;; but WITHOUT ANY WARRANTY; without even the implied warranty of 21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22;; GNU General Public License for more details. 23 24;; You should have received a copy of the GNU General Public License 25;; along with GNU Emacs; see the file COPYING. If not, write to the 26;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 27;; Boston, MA 02110-1301, USA. 28 29;;; Commentary: 30 31;; Loading this package implements a more fine-grained minibuffer 32;; completion feedback scheme. Prospective completions are concisely 33;; indicated within the minibuffer itself, with each successive 34;; keystroke. 35 36;; See `icomplete-completions' docstring for a description of the 37;; icomplete display format. 38 39;; See the `icomplete-minibuffer-setup-hook' docstring for a means to 40;; customize icomplete setup for interoperation with other 41;; minibuffer-oriented packages. 42 43;; To activate icomplete mode, load the package and use the 44;; `icomplete-mode' function. You can subsequently deactivate it by 45;; invoking the function icomplete-mode with a negative prefix-arg 46;; (C-U -1 ESC-x icomplete-mode). Also, you can prevent activation of 47;; the mode during package load by first setting the variable 48;; `icomplete-mode' to nil. Icompletion can be enabled any time after 49;; the package is loaded by invoking icomplete-mode without a prefix 50;; arg. 51 52;; Thanks to everyone for their suggestions for refinements of this 53;; package. I particularly have to credit Michael Cook, who 54;; implemented an incremental completion style in his 'iswitch' 55;; functions that served as a model for icomplete. Some other 56;; contributors: Noah Friedman (restructuring as minor mode), Colin 57;; Rafferty (lemacs reconciliation), Lars Lindberg, RMS, and others. 58 59;; klm. 60 61;;; Code: 62 63;;;_* Provide 64(provide 'icomplete) 65 66 67(defgroup icomplete nil 68 "Show completions dynamically in minibuffer." 69 :prefix "icomplete-" 70 :group 'minibuffer) 71 72;;;_* User Customization variables 73(defcustom icomplete-prospects-length 80 74 "*Length of string displaying the prospects." 75 :type 'integer 76 :group 'icomplete) 77 78(defcustom icomplete-compute-delay .3 79 "*Completions-computation stall, used only with large-number 80completions - see `icomplete-delay-completions-threshold'." 81 :type 'number 82 :group 'icomplete) 83 84(defcustom icomplete-delay-completions-threshold 400 85 "*Pending-completions number over which to apply icomplete-compute-delay." 86 :type 'integer 87 :group 'icomplete) 88 89(defcustom icomplete-max-delay-chars 3 90 "*Maximum number of initial chars to apply icomplete compute delay." 91 :type 'integer 92 :group 'icomplete) 93 94(defcustom icomplete-show-key-bindings t 95 "*If non-nil, show key bindings as well as completion for sole matches." 96 :type 'boolean 97 :group 'icomplete) 98 99(defcustom icomplete-minibuffer-setup-hook nil 100 "*Icomplete-specific customization of minibuffer setup. 101 102This hook is run during minibuffer setup iff icomplete will be active. 103It is intended for use in customizing icomplete for interoperation 104with other features and packages. For instance: 105 106 \(add-hook 'icomplete-minibuffer-setup-hook 107 \(function 108 \(lambda () 109 \(make-local-variable 'max-mini-window-height) 110 \(setq max-mini-window-height 3)))) 111 112will constrain Emacs to a maximum minibuffer height of 3 lines when 113icompletion is occurring." 114 :type 'hook 115 :group 'icomplete) 116 117 118;;;_* Initialization 119 120;;;_ + Internal Variables 121;;;_ = icomplete-eoinput nil 122(defvar icomplete-eoinput nil 123 "Point where minibuffer input ends and completion info begins.") 124(make-variable-buffer-local 'icomplete-eoinput) 125;;;_ = icomplete-pre-command-hook 126(defvar icomplete-pre-command-hook nil 127 "Incremental-minibuffer-completion pre-command-hook. 128 129Is run in minibuffer before user input when `icomplete-mode' is non-nil. 130Use `icomplete-mode' function to set it up properly for incremental 131minibuffer completion.") 132(add-hook 'icomplete-pre-command-hook 'icomplete-tidy) 133;;;_ = icomplete-post-command-hook 134(defvar icomplete-post-command-hook nil 135 "Incremental-minibuffer-completion post-command-hook. 136 137Is run in minibuffer after user input when `icomplete-mode' is non-nil. 138Use `icomplete-mode' function to set it up properly for incremental 139minibuffer completion.") 140(add-hook 'icomplete-post-command-hook 'icomplete-exhibit) 141 142(defun icomplete-get-keys (func-name) 143 "Return strings naming keys bound to `func-name', or nil if none. 144Examines the prior, not current, buffer, presuming that current buffer 145is minibuffer." 146 (if (commandp func-name) 147 (save-excursion 148 (let* ((sym (intern func-name)) 149 (buf (other-buffer nil t)) 150 (map (save-excursion (set-buffer buf) (current-local-map))) 151 (keys (where-is-internal sym map))) 152 (if keys 153 (concat "<" 154 (mapconcat 'key-description 155 (sort keys 156 #'(lambda (x y) 157 (< (length x) (length y)))) 158 ", ") 159 ">")))))) 160;;;_ = icomplete-with-completion-tables 161(defvar icomplete-with-completion-tables '(internal-complete-buffer) 162 "Specialized completion tables with which icomplete should operate. 163 164Icomplete does not operate with any specialized completion tables 165except those on this list.") 166 167;;;_ > icomplete-mode (&optional prefix) 168;;;###autoload 169(define-minor-mode icomplete-mode 170 "Toggle incremental minibuffer completion for this Emacs session. 171With a numeric argument, turn Icomplete mode on iff ARG is positive." 172 :global t :group 'icomplete 173 (if icomplete-mode 174 ;; The following is not really necessary after first time - 175 ;; no great loss. 176 (add-hook 'minibuffer-setup-hook 'icomplete-minibuffer-setup) 177 (remove-hook 'minibuffer-setup-hook 'icomplete-minibuffer-setup))) 178 179;;;_ > icomplete-simple-completing-p () 180(defun icomplete-simple-completing-p () 181 "Non-nil if current window is minibuffer that's doing simple completion. 182 183Conditions are: 184 the selected window is a minibuffer, 185 and not in the middle of macro execution, 186 and `minibuffer-completion-table' is not a symbol (which would 187 indicate some non-standard, non-simple completion mechanism, 188 like file-name and other custom-func completions)." 189 190 (and (window-minibuffer-p (selected-window)) 191 (not executing-kbd-macro) 192 minibuffer-completion-table 193 (or (not (functionp minibuffer-completion-table)) 194 (member minibuffer-completion-table 195 icomplete-with-completion-tables)))) 196 197;;;_ > icomplete-minibuffer-setup () 198(defun icomplete-minibuffer-setup () 199 "Run in minibuffer on activation to establish incremental completion. 200Usually run by inclusion in `minibuffer-setup-hook'." 201 (when (and icomplete-mode (icomplete-simple-completing-p)) 202 (add-hook 'pre-command-hook 203 (lambda () (run-hooks 'icomplete-pre-command-hook)) 204 nil t) 205 (add-hook 'post-command-hook 206 (lambda () (run-hooks 'icomplete-post-command-hook)) 207 nil t) 208 (run-hooks 'icomplete-minibuffer-setup-hook))) 209; 210 211 212;;;_* Completion 213 214;;;_ > icomplete-tidy () 215(defun icomplete-tidy () 216 "Remove completions display \(if any) prior to new user input. 217Should be run in on the minibuffer `pre-command-hook'. See `icomplete-mode' 218and `minibuffer-setup-hook'." 219 (when (and icomplete-mode icomplete-eoinput) 220 221 (unless (>= icomplete-eoinput (point-max)) 222 (let ((buffer-undo-list t) ; prevent entry 223 deactivate-mark) 224 (delete-region icomplete-eoinput (point-max)))) 225 226 ;; Reestablish the safe value. 227 (setq icomplete-eoinput nil))) 228 229;;;_ > icomplete-exhibit () 230(defun icomplete-exhibit () 231 "Insert icomplete completions display. 232Should be run via minibuffer `post-command-hook'. See `icomplete-mode' 233and `minibuffer-setup-hook'." 234 (when (and icomplete-mode (icomplete-simple-completing-p)) 235 (save-excursion 236 (goto-char (point-max)) 237 ;; Register the end of input, so we know where the extra stuff 238 ;; (match-status info) begins: 239 (setq icomplete-eoinput (point)) 240 ; Insert the match-status information: 241 (if (and (> (point-max) (minibuffer-prompt-end)) 242 buffer-undo-list ; Wait for some user input. 243 (or 244 ;; Don't bother with delay after certain number of chars: 245 (> (- (point) (field-beginning)) icomplete-max-delay-chars) 246 ;; Don't delay if alternatives number is small enough: 247 (and (sequencep minibuffer-completion-table) 248 (< (length minibuffer-completion-table) 249 icomplete-delay-completions-threshold)) 250 ;; Delay - give some grace time for next keystroke, before 251 ;; embarking on computing completions: 252 (sit-for icomplete-compute-delay))) 253 (let ((text (while-no-input 254 (list 255 (icomplete-completions 256 (field-string) 257 minibuffer-completion-table 258 minibuffer-completion-predicate 259 (not minibuffer-completion-confirm))))) 260 (buffer-undo-list t) 261 deactivate-mark) 262 ;; Do nothing if while-no-input was aborted. 263 (if (consp text) (insert (car text)))))))) 264 265;;;_ > icomplete-completions (name candidates predicate require-match) 266(defun icomplete-completions (name candidates predicate require-match) 267 "Identify prospective candidates for minibuffer completion. 268 269The display is updated with each minibuffer keystroke during 270minibuffer completion. 271 272Prospective completion suffixes (if any) are displayed, bracketed by 273one of \(), \[], or \{} pairs. The choice of brackets is as follows: 274 275 \(...) - a single prospect is identified and matching is enforced, 276 \[...] - a single prospect is identified but matching is optional, or 277 \{...} - multiple prospects, separated by commas, are indicated, and 278 further input is required to distinguish a single one. 279 280The displays for unambiguous matches have ` [Matched]' appended 281\(whether complete or not), or ` \[No matches]', if no eligible 282matches exist. \(Keybindings for uniquely matched commands 283are exhibited within the square braces.)" 284 285 ;; 'all-completions' doesn't like empty 286 ;; minibuffer-completion-table's (ie: (nil)) 287 (if (and (listp candidates) (null (car candidates))) 288 (setq candidates nil)) 289 290 (let ((comps (all-completions name candidates predicate)) 291 ; "-determined" - only one candidate 292 (open-bracket-determined (if require-match "(" "[")) 293 (close-bracket-determined (if require-match ")" "]"))) 294 ;; `concat'/`mapconcat' is the slow part. With the introduction of 295 ;; `icomplete-prospects-length', there is no need for `catch'/`throw'. 296 (if (null comps) (format " %sNo matches%s" 297 open-bracket-determined 298 close-bracket-determined) 299 (let* ((most-try (try-completion name (mapcar (function list) comps))) 300 (most (if (stringp most-try) most-try (car comps))) 301 (most-len (length most)) 302 (determ (and (> most-len (length name)) 303 (concat open-bracket-determined 304 (substring most (length name)) 305 close-bracket-determined))) 306 ;;"-prospects" - more than one candidate 307 (prospects-len 0) 308 prospects most-is-exact comp) 309 (if (eq most-try t) 310 (setq prospects nil) 311 (while (and comps (< prospects-len icomplete-prospects-length)) 312 (setq comp (substring (car comps) most-len) 313 comps (cdr comps)) 314 (cond ((string-equal comp "") (setq most-is-exact t)) 315 ((member comp prospects)) 316 (t (setq prospects (cons comp prospects) 317 prospects-len (+ (length comp) 1 prospects-len)))))) 318 (if prospects 319 (concat determ 320 "{" 321 (and most-is-exact ",") 322 (mapconcat 'identity 323 (sort prospects (function string-lessp)) 324 ",") 325 (and comps ",...") 326 "}") 327 (concat determ 328 " [Matched" 329 (let ((keys (and icomplete-show-key-bindings 330 (commandp (intern-soft most)) 331 (icomplete-get-keys most)))) 332 (if keys (concat "; " keys) "")) 333 "]")))))) 334 335;;;_* Local emacs vars. 336;;;Local variables: 337;;;allout-layout: (-2 :) 338;;;End: 339 340;; arch-tag: 339ec25a-0741-4eb6-be63-997532e89b0f 341;;; icomplete.el ends here 342