(complete): Use sit-for, not cmpl19-sit-for.
[emacs.git] / lisp / completion.el
blobae4c0a362579fdc57bb64cc2e0effa2911fb9d6c
1 ;;; completion.el --- dynamic word-completion code
3 ;; Maintainer: FSF
4 ;; Keywords: abbrev
6 ;;; Commentary:
8 ;;; This is a Completion system for GNU Emacs
9 ;;;
10 ;;; E-Mail:
11 ;;; Internet: completion@think.com, bug-completion@think.com
12 ;;; UUCP: {rutgers,harvard,mit-eddie}!think!completion
13 ;;;
14 ;;; If you are a new user, we'd appreciate knowing your site name and
15 ;;; any comments you have.
16 ;;;
17 ;;;
18 ;;; NO WARRANTY
19 ;;;
20 ;;; This software is distributed free of charge and is in the public domain.
21 ;;; Anyone may use, duplicate or modify this program. Thinking Machines
22 ;;; Corporation does not restrict in any way the use of this software by
23 ;;; anyone.
24 ;;;
25 ;;; Thinking Machines Corporation provides absolutely no warranty of any kind.
26 ;;; The entire risk as to the quality and performance of this program is with
27 ;;; you. In no event will Thinking Machines Corporation be liable to you for
28 ;;; damages, including any lost profits, lost monies, or other special,
29 ;;; incidental or consequential damages arising out of the use of this program.
30 ;;;
31 ;;; You must not restrict the distribution of this software.
32 ;;;
33 ;;; Please keep this notice and author information in any copies you make.
34 ;;;
35 ;;; 4/90
36 ;;;
37 ;;;
38 ;;; Advertisement
39 ;;;---------------
40 ;;; Try using this. If you are like most you will be happy you did.
41 ;;;
42 ;;; What to put in .emacs
43 ;;;-----------------------
44 ;;; (load "completion") ;; If it's not part of the standard band.
45 ;;; (initialize-completions)
46 ;;;
47 ;;; For best results, be sure to byte-compile the file first.
48 ;;;
50 ;;; Authors
51 ;;;---------
52 ;;; Jim Salem {salem@think.com}
53 ;;; Brewster Kahle {brewster@think.com}
54 ;;; Thinking Machines Corporation
55 ;;; 245 First St., Cambridge MA 02142 (617) 876-1111
56 ;;;
57 ;;; Mailing Lists
58 ;;;---------------
59 ;;;
60 ;;; Bugs to bug-completion@think.com
61 ;;; Comments to completion@think.com
62 ;;; Requests to be added completion-request@think.com
63 ;;;
64 ;;; Availability
65 ;;;--------------
66 ;;; Anonymous FTP from think.com
67 ;;;
69 ;;;---------------------------------------------------------------------------
70 ;;; Documentation [Slightly out of date]
71 ;;;---------------------------------------------------------------------------
72 ;;; (also check the documentation string of the functions)
73 ;;;
74 ;;; Introduction
75 ;;;---------------
76 ;;;
77 ;;; After you type a few characters, pressing the "complete" key inserts
78 ;;; the rest of the word you are likely to type.
79 ;;;
80 ;;; This watches all the words that you type and remembers them. When
81 ;;; typing a new word, pressing "complete" (meta-return) "completes" the
82 ;;; word by inserting the most recently used word that begins with the
83 ;;; same characters. If you press meta-return repeatedly, it cycles
84 ;;; through all the words it knows about.
85 ;;;
86 ;;; If you like the completion then just continue typing, it is as if you
87 ;;; entered the text by hand. If you want the inserted extra characters
88 ;;; to go away, type control-w or delete. More options are described below.
89 ;;;
90 ;;; The guesses are made in the order of the most recently "used". Typing
91 ;;; in a word and then typing a separator character (such as a space) "uses"
92 ;;; the word. So does moving a cursor over the word. If no words are found,
93 ;;; it uses an extended version of the dabbrev style completion.
94 ;;;
95 ;;; You automatically save the completions you use to a file between
96 ;;; sessions.
97 ;;;
98 ;;; Completion enables programmers to enter longer, more descriptive
99 ;;; variable names while typing fewer keystrokes than they normally would.
102 ;;; Full documentation
103 ;;;---------------------
105 ;;; A "word" is any string containing characters with either word or symbol
106 ;;; syntax. [E.G. Any alphanumeric string with hyphens, underscores, etc.]
107 ;;; Unless you change the constants, you must type at least three characters
108 ;;; for the word to be recognized. Only words longer than 6 characters are
109 ;;; saved.
111 ;;; When you load this file, completion will be on. I suggest you use the
112 ;;; compiled version (because it is noticeably faster).
114 ;;; M-X completion-mode toggles whether or not new words are added to the
115 ;;; database by changing the value of enable-completion.
117 ;;; SAVING/LOADING COMPLETIONS
118 ;;; Completions are automatically saved from one session to another
119 ;;; (unless save-completions-flag or enable-completion is nil).
120 ;;; Loading this file (or calling initialize-completions) causes EMACS
121 ;;; to load a completions database for a saved completions file
122 ;;; (default: ~/.completions). When you exit, EMACS saves a copy of the
123 ;;; completions that you
124 ;;; often use. When you next start, EMACS loads in the saved completion file.
126 ;;; The number of completions saved depends loosely on
127 ;;; *saved-completions-decay-factor*. Completions that have never been
128 ;;; inserted via "complete" are not saved. You are encouraged to experiment
129 ;;; with different functions (see compute-completion-min-num-uses).
131 ;;; Some completions are permanent and are always saved out. These
132 ;;; completions have their num-uses slot set to T. Use
133 ;;; add-permanent-completion to do this
135 ;;; Completions are saved only if enable-completion is T. The number of old
136 ;;; versions kept of the saved completions file is controlled by
137 ;;; completions-file-versions-kept.
139 ;;; COMPLETE KEY OPTIONS
140 ;;; The complete function takes a numeric arguments.
141 ;;; control-u :: leave the point at the beginning of the completion rather
142 ;;; than the middle.
143 ;;; a number :: rotate through the possible completions by that amount
144 ;;; `-' :: same as -1 (insert previous completion)
146 ;;; HOW THE DATABASE IS MAINTAINED
147 ;;; <write>
149 ;;; UPDATING THE DATABASE MANUALLY
150 ;;; m-x kill-completion
151 ;;; kills the completion at point.
152 ;;; m-x add-completion
153 ;;; m-x add-permanent-completion
154 ;;;
155 ;;; UPDATING THE DATABASE FROM A SOURCE CODE FILE
156 ;;; m-x add-completions-from-buffer
157 ;;; Parses all the definition names from a C or LISP mode buffer and
158 ;;; adds them to the completion database.
160 ;;; m-x add-completions-from-lisp-file
161 ;;; Parses all the definition names from a C or Lisp mode file and
162 ;;; adds them to the completion database.
164 ;;; UPDATING THE DATABASE FROM A TAGS TABLE
165 ;;; m-x add-completions-from-tags-table
166 ;;; Adds completions from the current tags-table-buffer.
168 ;;; HOW A COMPLETION IS FOUND
169 ;;; <write>
171 ;;; STRING CASING
172 ;;; Completion is string case independent if case-fold-search has its
173 ;;; normal default of T. Also when the completion is inserted the case of the
174 ;;; entry is coerced appropriately.
175 ;;; [E.G. APP --> APPROPRIATELY app --> appropriately
176 ;;; App --> Appropriately]
178 ;;; INITIALIZATION
179 ;;; The form `(initialize-completions)' initializes the completion system by
180 ;;; trying to load in the user's completions. After the first cal, further
181 ;;; calls have no effect so one should be careful not to put the form in a
182 ;;; site's standard site-init file.
184 ;;;---------------------------------------------------------------------------
188 ;;;---------------------------------------------------------------------------
189 ;;; Functions you might like to call
190 ;;;---------------------------------------------------------------------------
192 ;;; add-completion string &optional num-uses
193 ;;; Adds a new string to the database
195 ;;; add-permanent-completion string
196 ;;; Adds a new string to the database with num-uses = T
199 ;;; kill-completion string
200 ;;; Kills the completion from the database.
202 ;;; clear-all-completions
203 ;;; Clears the database
205 ;;; list-all-completions
206 ;;; Returns a list of all completions.
209 ;;; next-completion string &optional index
210 ;;; Returns a completion entry that starts with string.
212 ;;; find-exact-completion string
213 ;;; Returns a completion entry that exactly matches string.
215 ;;; complete
216 ;;; Inserts a completion at point
218 ;;; initialize-completions
219 ;;; Loads the completions file and sets up so that exiting emacs will
220 ;;; save them.
222 ;;; save-completions-to-file &optional filename
223 ;;; load-completions-from-file &optional filename
225 ;;;-----------------------------------------------
226 ;;; Other functions
227 ;;;-----------------------------------------------
229 ;;; get-completion-list string
231 ;;; These things are for manipulating the structure
232 ;;; make-completion string num-uses
233 ;;; completion-num-uses completion
234 ;;; completion-string completion
235 ;;; set-completion-num-uses completion num-uses
236 ;;; set-completion-string completion string
237 ;;;
240 ;;;-----------------------------------------------
241 ;;; To Do :: (anybody ?)
242 ;;;-----------------------------------------------
244 ;;; Implement Lookup and keyboard interface in C
245 ;;; Add package prefix smarts (for Common Lisp)
246 ;;; Add autoprompting of possible completions after every keystroke (fast
247 ;;; terminals only !)
248 ;;; Add doc. to texinfo
251 ;;;-----------------------------------------------
252 ;;; Change Log:
253 ;;;-----------------------------------------------
254 ;;; Sometime in '84 Brewster implemented a somewhat buggy version for
255 ;;; Symbolics LISPMs.
256 ;;; Jan. '85 Jim became enamored of the idea and implemented a faster,
257 ;;; more robust version.
258 ;;; With input from many users at TMC, (rose, craig, and gls come to mind),
259 ;;; the current style of interface was developed.
260 ;;; 9/87, Jim and Brewster took terminals home. Yuck. After
261 ;;; complaining for a while Brewester implemented a subset of the current
262 ;;; LISPM version for GNU Emacs.
263 ;;; 8/88 After complaining for a while (and with sufficient
264 ;;; promised rewards), Jim reimplemented a version of GNU completion
265 ;;; superior to that of the LISPM version.
267 ;;;-----------------------------------------------
268 ;;; Acknowledgements
269 ;;;-----------------------------------------------
270 ;;; Cliff Lasser (cal@think.com), Kevin Herbert (kph@cisco.com),
271 ;;; eero@media-lab, kgk@cs.brown.edu, jla@ai.mit.edu,
273 ;;;-----------------------------------------------
274 ;;; Change Log
275 ;;;-----------------------------------------------
276 ;;; From version 9 to 10
277 ;;; - Allowance for non-integral *completion-version* nos.
278 ;;; - Fix cmpl-apply-as-top-level for keyboard macros
279 ;;; - Fix broken completion merging (in save-completions-to-file)
280 ;;; - More misc. fixes for version 19.0 of emacs
282 ;;; From Version 8 to 9
283 ;;; - Ported to version 19.0 of emacs (backcompatible with version 18)
284 ;;; - Added add-completions-from-tags-table (with thanks to eero@media-lab)
286 ;;; From Version 7 to 8
287 ;;; - Misc. changes to comments
288 ;;; - new completion key bindings: c-x o, M->, M-<, c-a, c-e
289 ;;; - cdabbrev now checks all the visible window buffers and the "other buffer"
290 ;;; - `%' is now a symbol character rather than a separator (except in C mode)
292 ;;; From Version 6 to 7
293 ;;; - Fixed bug with saving out .completion file the first time
295 ;;; From Version 5 to 6
296 ;;; - removed statistics recording
297 ;;; - reworked advise to handle autoloads
298 ;;; - Fixed fortran mode support
299 ;;; - Added new cursor motion triggers
301 ;;; From Version 4 to 5
302 ;;; - doesn't bother saving if nothing has changed
303 ;;; - auto-save if haven't used for a 1/2 hour
304 ;;; - save period extended to two weeks
305 ;;; - minor fix to capitalization code
306 ;;; - added *completion-auto-save-period* to variables recorded.
307 ;;; - added reenter protection to cmpl-record-statistics-filter
308 ;;; - added backup protection to save-completions-to-file (prevents
309 ;;; problems with disk full errors)
311 ;;; Code:
313 ;;;---------------------------------------------------------------------------
314 ;;; User changeable parameters
315 ;;;---------------------------------------------------------------------------
317 (defvar enable-completion t
318 "*Non-nil means enable recording and saving of completions.
319 If nil, no new words added to the database or saved to the init file.")
321 (defvar save-completions-flag t
322 "*Non-nil means save most-used completions when exiting Emacs.
323 See also `saved-completions-retention-time'.")
325 (defvar save-completions-file-name "~/.completions"
326 "*The filename to save completions to.")
328 (defvar save-completions-retention-time 336
329 "*Discard a completion if unused for this many hours.
330 \(1 day = 24, 1 week = 168). If this is 0, non-permanent completions
331 will not be saved unless these are used. Default is two weeks.")
333 (defvar completion-on-separator-character nil
334 "*Non-nil means separator characters mark previous word as used.
335 This means the word will be saved as a completion.")
337 (defvar completions-file-versions-kept kept-new-versions
338 "*Number of versions to keep for the saved completions file.")
340 (defvar completion-prompt-speed-threshold 4800
341 "*Minimum output speed at which to display next potential completion.")
343 (defvar completion-cdabbrev-prompt-flag nil
344 "*If non-nil, the next completion prompt does a cdabbrev search.
345 This can be time consuming.")
347 (defvar completion-search-distance 15000
348 "*How far to search in the buffer when looking for completions.
349 In number of characters. If nil, search the whole buffer.")
351 (defvar completions-merging-modes '(lisp c)
352 "*List of modes {`c' or `lisp'} for automatic completions merging.
353 Definitions from visited files which have these modes
354 are automatically added to the completion database.")
356 ;;;(defvar *record-cmpl-statistics-p* nil
357 ;;; "*If non-nil, record completion statistics.")
359 ;;;(defvar *completion-auto-save-period* 1800
360 ;;; "*The period in seconds to wait for emacs to be idle before autosaving
361 ;;;the completions. Default is a 1/2 hour.")
363 (defconst completion-min-length nil ;; defined below in eval-when
364 "*The minimum length of a stored completion.
365 DON'T CHANGE WITHOUT RECOMPILING ! This is used by macros.")
367 (defconst completion-max-length nil ;; defined below in eval-when
368 "*The maximum length of a stored completion.
369 DON'T CHANGE WITHOUT RECOMPILING ! This is used by macros.")
371 (defconst completion-prefix-min-length nil ;; defined below in eval-when
372 "The minimum length of a completion search string.
373 DON'T CHANGE WITHOUT RECOMPILING ! This is used by macros.")
375 (defmacro eval-when-compile-load-eval (&rest body)
376 ;; eval everything before expanding
377 (mapcar 'eval body)
378 (cons 'progn body))
380 (defun completion-eval-when ()
381 (eval-when-compile-load-eval
382 ;; These vars. are defined at both compile and load time.
383 (setq completion-min-length 6)
384 (setq completion-max-length 200)
385 (setq completion-prefix-min-length 3)))
387 (completion-eval-when)
389 ;; Need this file around too
390 (require 'cl)
392 ;;;---------------------------------------------------------------------------
393 ;;; Internal Variables
394 ;;;---------------------------------------------------------------------------
396 (defvar cmpl-initialized-p nil
397 "Set to t when the completion system is initialized.
398 Indicates that the old completion file has been read in.")
400 (defvar cmpl-completions-accepted-p nil
401 "Set to t as soon as the first completion has been accepted.
402 Used to decide whether to save completions.")
405 ;;;---------------------------------------------------------------------------
406 ;;; Low level tools
407 ;;;---------------------------------------------------------------------------
409 ;;;-----------------------------------------------
410 ;;; Misc.
411 ;;;-----------------------------------------------
413 (defun minibuffer-window-selected-p ()
414 "True iff the current window is the minibuffer."
415 (window-minibuffer-p (selected-window)))
417 (defmacro cmpl-read-time-eval (form)
418 ;; Like the #. reader macro
419 (eval form))
422 ;;;-----------------------------------------------
423 ;;; String case coercion
424 ;;;-----------------------------------------------
426 (defun cmpl-string-case-type (string)
427 "Returns :capitalized, :up, :down, :mixed, or :neither."
428 (let ((case-fold-search nil))
429 (cond ((string-match "[a-z]" string)
430 (cond ((string-match "[A-Z]" string)
431 (cond ((and (> (length string) 1)
432 (null (string-match "[A-Z]" string 1)))
433 ':capitalized)
435 ':mixed)))
436 (t ':down)))
438 (cond ((string-match "[A-Z]" string)
439 ':up)
440 (t ':neither))))
443 ;;; Tests -
444 ;;; (cmpl-string-case-type "123ABCDEF456") --> :up
445 ;;; (cmpl-string-case-type "123abcdef456") --> :down
446 ;;; (cmpl-string-case-type "123aBcDeF456") --> :mixed
447 ;;; (cmpl-string-case-type "123456") --> :neither
448 ;;; (cmpl-string-case-type "Abcde123") --> :capitalized
450 (defun cmpl-coerce-string-case (string case-type)
451 (cond ((eq case-type ':down) (downcase string))
452 ((eq case-type ':up) (upcase string))
453 ((eq case-type ':capitalized)
454 (setq string (downcase string))
455 (aset string 0 (logand ?\337 (aref string 0)))
456 string)
457 (t string)
460 (defun cmpl-merge-string-cases (string-to-coerce given-string)
461 (let ((string-case-type (cmpl-string-case-type string-to-coerce))
463 (cond ((memq string-case-type '(:down :up :capitalized))
464 ;; Found string is in a standard case. Coerce to a type based on
465 ;; the given string
466 (cmpl-coerce-string-case string-to-coerce
467 (cmpl-string-case-type given-string))
470 ;; If the found string is in some unusual case, just insert it
471 ;; as is
472 string-to-coerce)
475 ;;; Tests -
476 ;;; (cmpl-merge-string-cases "AbCdEf456" "abc") --> AbCdEf456
477 ;;; (cmpl-merge-string-cases "abcdef456" "ABC") --> ABCDEF456
478 ;;; (cmpl-merge-string-cases "ABCDEF456" "Abc") --> Abcdef456
479 ;;; (cmpl-merge-string-cases "ABCDEF456" "abc") --> abcdef456
482 (defun cmpl-hours-since-origin ()
483 (let ((time (current-time)))
484 (+ (* (/ (car time) 3600.0) (lsh 1 16))
485 (/ (nth 2 time) 3600.0))))
487 ;;;---------------------------------------------------------------------------
488 ;;; "Symbol" parsing functions
489 ;;;---------------------------------------------------------------------------
490 ;;; The functions symbol-before-point, symbol-under-point, etc. quickly return
491 ;;; an appropriate symbol string. The strategy is to temporarily change
492 ;;; the syntax table to enable fast symbol searching. There are three classes
493 ;;; of syntax in these "symbol" syntax tables ::
495 ;;; syntax (?_) - "symbol" chars (e.g. alphanumerics)
496 ;;; syntax (?w) - symbol chars to ignore at end of words (e.g. period).
497 ;;; syntax (? ) - everything else
499 ;;; Thus by judicious use of scan-sexps and forward-word, we can get
500 ;;; the word we want relatively fast and without consing.
502 ;;; Why do we need a separate category for "symbol chars to ignore at ends" ?
503 ;;; For example, in LISP we want starting :'s trimmed
504 ;;; so keyword argument specifiers also define the keyword completion. And,
505 ;;; for example, in C we want `.' appearing in a structure ref. to
506 ;;; be kept intact in order to store the whole structure ref.; however, if
507 ;;; it appears at the end of a symbol it should be discarded because it is
508 ;;; probably used as a period.
510 ;;; Here is the default completion syntax ::
511 ;;; Symbol chars :: A-Z a-z 0-9 @ / \ * + ~ $ < > %
512 ;;; Symbol chars to ignore at ends :: _ : . -
513 ;;; Separator chars. :: <tab> <space> ! ^ & ( ) = ` | { } [ ] ; " ' #
514 ;;; , ? <Everything else>
516 ;;; Mode specific differences and notes ::
517 ;;; LISP diffs ->
518 ;;; Symbol chars :: ! & ? = ^
520 ;;; C diffs ->
521 ;;; Separator chars :: + * / : %
522 ;;; A note on the hyphen (`-'). Perhaps the hyphen should also be a separator
523 ;;; char., however, we wanted to have completion symbols include pointer
524 ;;; references. For example, "foo->bar" is a symbol as far as completion is
525 ;;; concerned.
527 ;;; FORTRAN diffs ->
528 ;;; Separator chars :: + - * / :
530 ;;; Pathname diffs ->
531 ;;; Symbol chars :: .
532 ;;; Of course there is no pathname "mode" and in fact we have not implemented
533 ;;; this table. However, if there was such a mode, this is what it would look
534 ;;; like.
536 ;;;-----------------------------------------------
537 ;;; Table definitions
538 ;;;-----------------------------------------------
540 (defun cmpl-make-standard-completion-syntax-table ()
541 (let ((table (make-vector 256 0)) ;; default syntax is whitespace
543 ;; alpha chars
544 (dotimes (i 26)
545 (modify-syntax-entry (+ ?a i) "_" table)
546 (modify-syntax-entry (+ ?A i) "_" table))
547 ;; digit chars.
548 (dotimes (i 10)
549 (modify-syntax-entry (+ ?0 i) "_" table))
550 ;; Other ones
551 (let ((symbol-chars '(?@ ?/ ?\\ ?* ?+ ?~ ?$ ?< ?> ?%))
552 (symbol-chars-ignore '(?_ ?- ?: ?.))
554 (dolist (char symbol-chars)
555 (modify-syntax-entry char "_" table))
556 (dolist (char symbol-chars-ignore)
557 (modify-syntax-entry char "w" table)
560 table))
562 (defconst cmpl-standard-syntax-table (cmpl-make-standard-completion-syntax-table))
564 (defun cmpl-make-lisp-completion-syntax-table ()
565 (let ((table (copy-syntax-table cmpl-standard-syntax-table))
566 (symbol-chars '(?! ?& ?? ?= ?^))
568 (dolist (char symbol-chars)
569 (modify-syntax-entry char "_" table))
570 table))
572 (defun cmpl-make-c-completion-syntax-table ()
573 (let ((table (copy-syntax-table cmpl-standard-syntax-table))
574 (separator-chars '(?+ ?* ?/ ?: ?%))
576 (dolist (char separator-chars)
577 (modify-syntax-entry char " " table))
578 table))
580 (defun cmpl-make-fortran-completion-syntax-table ()
581 (let ((table (copy-syntax-table cmpl-standard-syntax-table))
582 (separator-chars '(?+ ?- ?* ?/ ?:))
584 (dolist (char separator-chars)
585 (modify-syntax-entry char " " table))
586 table))
588 (defconst cmpl-lisp-syntax-table (cmpl-make-lisp-completion-syntax-table))
589 (defconst cmpl-c-syntax-table (cmpl-make-c-completion-syntax-table))
590 (defconst cmpl-fortran-syntax-table (cmpl-make-fortran-completion-syntax-table))
592 (defvar cmpl-syntax-table cmpl-standard-syntax-table
593 "This variable holds the current completion syntax table.")
594 (make-variable-buffer-local 'cmpl-syntax-table)
596 ;;;-----------------------------------------------
597 ;;; Installing the appropriate mode tables
598 ;;;-----------------------------------------------
600 (add-hook 'lisp-mode-hook
601 '(lambda ()
602 (setq cmpl-syntax-table cmpl-lisp-syntax-table)))
604 (add-hook 'c-mode-hook
605 '(lambda ()
606 (setq cmpl-syntax-table cmpl-c-syntax-table)))
608 (add-hook 'fortran-mode-hook
609 '(lambda ()
610 (setq cmpl-syntax-table cmpl-fortran-syntax-table)
611 (completion-setup-fortran-mode)))
613 ;;;-----------------------------------------------
614 ;;; Symbol functions
615 ;;;-----------------------------------------------
616 (defvar cmpl-symbol-start nil
617 "Holds first character of symbol, after any completion symbol function.")
618 (defvar cmpl-symbol-end nil
619 "Holds last character of symbol, after any completion symbol function.")
620 ;;; These are temp. vars. we use to avoid using let.
621 ;;; Why ? Small speed improvement.
622 (defvar cmpl-saved-syntax nil)
623 (defvar cmpl-saved-point nil)
625 (defun symbol-under-point ()
626 "Returns the symbol that the point is currently on.
627 But only if it is longer than `completion-min-length'."
628 (setq cmpl-saved-syntax (syntax-table))
629 (set-syntax-table cmpl-syntax-table)
630 (cond
631 ;; Cursor is on following-char and after preceding-char
632 ((memq (char-syntax (following-char)) '(?w ?_))
633 (setq cmpl-saved-point (point)
634 cmpl-symbol-start (scan-sexps (1+ cmpl-saved-point) -1)
635 cmpl-symbol-end (scan-sexps cmpl-saved-point 1))
636 ;; remove chars to ignore at the start
637 (cond ((= (char-syntax (char-after cmpl-symbol-start)) ?w)
638 (goto-char cmpl-symbol-start)
639 (forward-word 1)
640 (setq cmpl-symbol-start (point))
641 (goto-char cmpl-saved-point)
643 ;; remove chars to ignore at the end
644 (cond ((= (char-syntax (char-after (1- cmpl-symbol-end))) ?w)
645 (goto-char cmpl-symbol-end)
646 (forward-word -1)
647 (setq cmpl-symbol-end (point))
648 (goto-char cmpl-saved-point)
650 ;; restore state
651 (set-syntax-table cmpl-saved-syntax)
652 ;; Return completion if the length is reasonable
653 (if (and (<= (cmpl-read-time-eval completion-min-length)
654 (- cmpl-symbol-end cmpl-symbol-start))
655 (<= (- cmpl-symbol-end cmpl-symbol-start)
656 (cmpl-read-time-eval completion-max-length)))
657 (buffer-substring cmpl-symbol-start cmpl-symbol-end))
660 ;; restore table if no symbol
661 (set-syntax-table cmpl-saved-syntax)
662 nil)
665 ;;; tests for symbol-under-point
666 ;;; `^' indicates cursor pos. where value is returned
667 ;;; simple-word-test
668 ;;; ^^^^^^^^^^^^^^^^ --> simple-word-test
669 ;;; _harder_word_test_
670 ;;; ^^^^^^^^^^^^^^^^^^ --> harder_word_test
671 ;;; .___.______.
672 ;;; --> nil
673 ;;; /foo/bar/quux.hello
674 ;;; ^^^^^^^^^^^^^^^^^^^ --> /foo/bar/quux.hello
677 (defun symbol-before-point ()
678 "Returns a string of the symbol immediately before point.
679 Returns nil if there isn't one longer than `completion-min-length'."
680 ;; This is called when a word separator is typed so it must be FAST !
681 (setq cmpl-saved-syntax (syntax-table))
682 (set-syntax-table cmpl-syntax-table)
683 ;; Cursor is on following-char and after preceding-char
684 (cond ((= (setq cmpl-preceding-syntax (char-syntax (preceding-char))) ?_)
685 ;; No chars. to ignore at end
686 (setq cmpl-symbol-end (point)
687 cmpl-symbol-start (scan-sexps (1+ cmpl-symbol-end) -1)
689 ;; remove chars to ignore at the start
690 (cond ((= (char-syntax (char-after cmpl-symbol-start)) ?w)
691 (goto-char cmpl-symbol-start)
692 (forward-word 1)
693 (setq cmpl-symbol-start (point))
694 (goto-char cmpl-symbol-end)
696 ;; restore state
697 (set-syntax-table cmpl-saved-syntax)
698 ;; return value if long enough
699 (if (>= cmpl-symbol-end
700 (+ cmpl-symbol-start
701 (cmpl-read-time-eval completion-min-length)))
702 (buffer-substring cmpl-symbol-start cmpl-symbol-end))
704 ((= cmpl-preceding-syntax ?w)
705 ;; chars to ignore at end
706 (setq cmpl-saved-point (point)
707 cmpl-symbol-start (scan-sexps (1+ cmpl-saved-point) -1))
708 ;; take off chars. from end
709 (forward-word -1)
710 (setq cmpl-symbol-end (point))
711 ;; remove chars to ignore at the start
712 (cond ((= (char-syntax (char-after cmpl-symbol-start)) ?w)
713 (goto-char cmpl-symbol-start)
714 (forward-word 1)
715 (setq cmpl-symbol-start (point))
717 ;; restore state
718 (goto-char cmpl-saved-point)
719 (set-syntax-table cmpl-saved-syntax)
720 ;; Return completion if the length is reasonable
721 (if (and (<= (cmpl-read-time-eval completion-min-length)
722 (- cmpl-symbol-end cmpl-symbol-start))
723 (<= (- cmpl-symbol-end cmpl-symbol-start)
724 (cmpl-read-time-eval completion-max-length)))
725 (buffer-substring cmpl-symbol-start cmpl-symbol-end))
728 ;; restore table if no symbol
729 (set-syntax-table cmpl-saved-syntax)
730 nil)
733 ;;; tests for symbol-before-point
734 ;;; `^' indicates cursor pos. where value is returned
735 ;;; simple-word-test
736 ;;; ^ --> nil
737 ;;; ^ --> nil
738 ;;; ^ --> simple-w
739 ;;; ^ --> simple-word-test
740 ;;; _harder_word_test_
741 ;;; ^ --> harder_word_test
742 ;;; ^ --> harder_word_test
743 ;;; ^ --> harder
744 ;;; .___....
745 ;;; --> nil
747 (defun symbol-under-or-before-point ()
748 ;;; This could be made slightly faster but it is better to avoid
749 ;;; copying all the code.
750 ;;; However, it is only used by the completion string prompter.
751 ;;; If it comes into common use, it could be rewritten.
752 (setq cmpl-saved-syntax (syntax-table))
753 (set-syntax-table cmpl-syntax-table)
754 (cond ((memq (char-syntax (following-char)) '(?w ?_))
755 (set-syntax-table cmpl-saved-syntax)
756 (symbol-under-point))
758 (set-syntax-table cmpl-saved-syntax)
759 (symbol-before-point))
763 (defun symbol-before-point-for-complete ()
764 ;; "Returns a string of the symbol immediately before point
765 ;; or nil if there isn't one. Like symbol-before-point but doesn't trim the
766 ;; end chars."
767 ;; Cursor is on following-char and after preceding-char
768 (setq cmpl-saved-syntax (syntax-table))
769 (set-syntax-table cmpl-syntax-table)
770 (cond ((memq (setq cmpl-preceding-syntax (char-syntax (preceding-char)))
771 '(?_ ?w))
772 (setq cmpl-symbol-end (point)
773 cmpl-symbol-start (scan-sexps (1+ cmpl-symbol-end) -1)
775 ;; remove chars to ignore at the start
776 (cond ((= (char-syntax (char-after cmpl-symbol-start)) ?w)
777 (goto-char cmpl-symbol-start)
778 (forward-word 1)
779 (setq cmpl-symbol-start (point))
780 (goto-char cmpl-symbol-end)
782 ;; restore state
783 (set-syntax-table cmpl-saved-syntax)
784 ;; Return completion if the length is reasonable
785 (if (and (<= (cmpl-read-time-eval
786 completion-prefix-min-length)
787 (- cmpl-symbol-end cmpl-symbol-start))
788 (<= (- cmpl-symbol-end cmpl-symbol-start)
789 (cmpl-read-time-eval completion-max-length)))
790 (buffer-substring cmpl-symbol-start cmpl-symbol-end))
793 ;; restore table if no symbol
794 (set-syntax-table cmpl-saved-syntax)
795 nil)
798 ;;; tests for symbol-before-point-for-complete
799 ;;; `^' indicates cursor pos. where value is returned
800 ;;; simple-word-test
801 ;;; ^ --> nil
802 ;;; ^ --> nil
803 ;;; ^ --> simple-w
804 ;;; ^ --> simple-word-test
805 ;;; _harder_word_test_
806 ;;; ^ --> harder_word_test
807 ;;; ^ --> harder_word_test_
808 ;;; ^ --> harder_
809 ;;; .___....
810 ;;; --> nil
814 ;;;---------------------------------------------------------------------------
815 ;;; Statistics Recording
816 ;;;---------------------------------------------------------------------------
818 ;;; Note that the guts of this has been turned off. The guts
819 ;;; are in completion-stats.el.
821 ;;;-----------------------------------------------
822 ;;; Conditionalizing code on *record-cmpl-statistics-p*
823 ;;;-----------------------------------------------
824 ;;; All statistics code outside this block should use this
825 (defmacro cmpl-statistics-block (&rest body))
826 ;;; "Only executes body if we are recording statistics."
827 ;;; (list 'cond
828 ;;; (list* '*record-cmpl-statistics-p* body)
829 ;;; ))
831 ;;;-----------------------------------------------
832 ;;; Completion Sources
833 ;;;-----------------------------------------------
835 ;; ID numbers
836 (defconst cmpl-source-unknown 0)
837 (defconst cmpl-source-init-file 1)
838 (defconst cmpl-source-file-parsing 2)
839 (defconst cmpl-source-separator 3)
840 (defconst cmpl-source-cursor-moves 4)
841 (defconst cmpl-source-interactive 5)
842 (defconst cmpl-source-cdabbrev 6)
843 (defconst num-cmpl-sources 7)
844 (defvar current-completion-source cmpl-source-unknown)
848 ;;;---------------------------------------------------------------------------
849 ;;; Completion Method #2: dabbrev-expand style
850 ;;;---------------------------------------------------------------------------
852 ;;; This method is used if there are no useful stored completions. It is
853 ;;; based on dabbrev-expand with these differences :
854 ;;; 1) Faster (we don't use regexps)
855 ;;; 2) case coercion handled correctly
856 ;;; This is called cdabbrev to differentiate it.
857 ;;; We simply search backwards through the file looking for words which
858 ;;; start with the same letters we are trying to complete.
861 (defvar cdabbrev-completions-tried nil)
862 ;;; "A list of all the cdabbrev completions since the last reset.")
864 (defvar cdabbrev-current-point 0)
865 ;;; "The current point position the cdabbrev search is at.")
867 (defvar cdabbrev-current-window nil)
868 ;;; "The current window we are looking for cdabbrevs in. T if looking in
869 ;;; (other-buffer), NIL if no more cdabbrevs.")
871 (defvar cdabbrev-wrapped-p nil)
872 ;;; "T if the cdabbrev search has wrapped around the file.")
874 (defvar cdabbrev-abbrev-string "")
875 (defvar cdabbrev-start-point 0)
877 ;;; Test strings for cdabbrev
878 ;;; cdat-upcase ;;same namestring
879 ;;; CDAT-UPCASE ;;ok
880 ;;; cdat2 ;;too short
881 ;;; cdat-1-2-3-4 ;;ok
882 ;;; a-cdat-1 ;;doesn't start correctly
883 ;;; cdat-simple ;;ok
886 (defun reset-cdabbrev (abbrev-string &optional initial-completions-tried)
887 "Resets the cdabbrev search to search for abbrev-string.
888 INITIAL-COMPLETIONS-TRIED is a list of downcased strings to ignore
889 during the search."
890 (setq cdabbrev-abbrev-string abbrev-string
891 cdabbrev-completions-tried
892 (cons (downcase abbrev-string) initial-completions-tried)
894 (reset-cdabbrev-window t)
897 (defun set-cdabbrev-buffer ()
898 ;; cdabbrev-current-window must not be NIL
899 (set-buffer (if (eq cdabbrev-current-window t)
900 (other-buffer)
901 (window-buffer cdabbrev-current-window)))
905 (defun reset-cdabbrev-window (&optional initializep)
906 "Resets the cdabbrev search to search for abbrev-string."
907 ;; Set the window
908 (cond (initializep
909 (setq cdabbrev-current-window (selected-window))
911 ((eq cdabbrev-current-window t)
912 ;; Everything has failed
913 (setq cdabbrev-current-window nil))
914 (cdabbrev-current-window
915 (setq cdabbrev-current-window (next-window cdabbrev-current-window))
916 (if (eq cdabbrev-current-window (selected-window))
917 ;; No more windows, try other buffer.
918 (setq cdabbrev-current-window t)))
920 (when cdabbrev-current-window
921 (save-excursion
922 (set-cdabbrev-buffer)
923 (setq cdabbrev-current-point (point)
924 cdabbrev-start-point cdabbrev-current-point
925 cdabbrev-stop-point
926 (if completion-search-distance
927 (max (point-min)
928 (- cdabbrev-start-point completion-search-distance))
929 (point-min))
930 cdabbrev-wrapped-p nil)
933 (defun next-cdabbrev ()
934 "Return the next possible cdabbrev expansion or nil if there isn't one.
935 `reset-cdabbrev' must've been called already.
936 This is sensitive to `case-fold-search'."
937 ;; note that case-fold-search affects the behavior of this function
938 ;; Bug: won't pick up an expansion that starts at the top of buffer
939 (when cdabbrev-current-window
940 (let (saved-point
941 saved-syntax
942 (expansion nil)
943 downcase-expansion tried-list syntax saved-point-2)
944 (save-excursion
945 (unwind-protect
946 (progn
947 ;; Switch to current completion buffer
948 (set-cdabbrev-buffer)
949 ;; Save current buffer state
950 (setq saved-point (point)
951 saved-syntax (syntax-table))
952 ;; Restore completion state
953 (set-syntax-table cmpl-syntax-table)
954 (goto-char cdabbrev-current-point)
955 ;; Loop looking for completions
956 (while
957 ;; This code returns t if it should loop again
958 (cond
959 (;; search for the string
960 (search-backward cdabbrev-abbrev-string cdabbrev-stop-point t)
961 ;; return nil if the completion is valid
962 (not
963 (and
964 ;; does it start with a separator char ?
965 (or (= (setq syntax (char-syntax (preceding-char))) ? )
966 (and (= syntax ?w)
967 ;; symbol char to ignore at end. Are we at end ?
968 (progn
969 (setq saved-point-2 (point))
970 (forward-word -1)
971 (prog1
972 (= (char-syntax (preceding-char)) ? )
973 (goto-char saved-point-2)
974 ))))
975 ;; is the symbol long enough ?
976 (setq expansion (symbol-under-point))
977 ;; have we not tried this one before
978 (progn
979 ;; See if we've already used it
980 (setq tried-list cdabbrev-completions-tried
981 downcase-expansion (downcase expansion))
982 (while (and tried-list
983 (not (string-equal downcase-expansion
984 (car tried-list))))
985 ;; Already tried, don't choose this one
986 (setq tried-list (cdr tried-list))
988 ;; at this point tried-list will be nil if this
989 ;; expansion has not yet been tried
990 (if tried-list
991 (setq expansion nil)
993 ))))
994 ;; search failed
995 (cdabbrev-wrapped-p
996 ;; If already wrapped, then we've failed completely
997 nil)
999 ;; need to wrap
1000 (goto-char (setq cdabbrev-current-point
1001 (if completion-search-distance
1002 (min (point-max) (+ cdabbrev-start-point completion-search-distance))
1003 (point-max))))
1005 (setq cdabbrev-wrapped-p t))
1007 ;; end of while loop
1008 (cond (expansion
1009 ;; successful
1010 (setq cdabbrev-completions-tried
1011 (cons downcase-expansion cdabbrev-completions-tried)
1012 cdabbrev-current-point (point))))
1014 (set-syntax-table saved-syntax)
1015 (goto-char saved-point)
1017 ;; If no expansion, go to next window
1018 (cond (expansion)
1019 (t (reset-cdabbrev-window)
1020 (next-cdabbrev)))
1023 ;;; The following must be eval'd in the minibuffer ::
1024 ;;; (reset-cdabbrev "cdat")
1025 ;;; (next-cdabbrev) --> "cdat-simple"
1026 ;;; (next-cdabbrev) --> "cdat-1-2-3-4"
1027 ;;; (next-cdabbrev) --> "CDAT-UPCASE"
1028 ;;; (next-cdabbrev) --> "cdat-wrapping"
1029 ;;; (next-cdabbrev) --> "cdat_start_sym"
1030 ;;; (next-cdabbrev) --> nil
1031 ;;; (next-cdabbrev) --> nil
1032 ;;; (next-cdabbrev) --> nil
1034 ;;; _cdat_start_sym
1035 ;;; cdat-wrapping
1038 ;;;---------------------------------------------------------------------------
1039 ;;; Completion Database
1040 ;;;---------------------------------------------------------------------------
1042 ;;; We use two storage modes for the two search types ::
1043 ;;; 1) Prefix {cmpl-prefix-obarray} for looking up possible completions
1044 ;;; Used by search-completion-next
1045 ;;; the value of the symbol is nil or a cons of head and tail pointers
1046 ;;; 2) Interning {cmpl-obarray} to see if it's in the database
1047 ;;; Used by find-exact-completion, completion-in-database-p
1048 ;;; The value of the symbol is the completion entry
1050 ;;; bad things may happen if this length is changed due to the way
1051 ;;; GNU implements obarrays
1052 (defconst cmpl-obarray-length 511)
1054 (defvar cmpl-prefix-obarray (make-vector cmpl-obarray-length 0)
1055 "An obarray used to store the downcased completion prefixes.
1056 Each symbol is bound to a list of completion entries.")
1058 (defvar cmpl-obarray (make-vector cmpl-obarray-length 0)
1059 "An obarray used to store the downcased completions.
1060 Each symbol is bound to a single completion entry.")
1062 ;;;-----------------------------------------------
1063 ;;; Completion Entry Structure Definition
1064 ;;;-----------------------------------------------
1066 ;;; A completion entry is a LIST of string, prefix-symbol num-uses, and
1067 ;;; last-use-time (the time the completion was last used)
1068 ;;; last-use-time is T if the string should be kept permanently
1069 ;;; num-uses is incremented everytime the completion is used.
1071 ;;; We chose lists because (car foo) is faster than (aref foo 0) and the
1072 ;;; creation time is about the same.
1074 ;;; READER MACROS
1076 (defmacro completion-string (completion-entry)
1077 (list 'car completion-entry))
1079 (defmacro completion-num-uses (completion-entry)
1080 ;; "The number of times it has used. Used to decide whether to save
1081 ;; it."
1082 (list 'car (list 'cdr completion-entry)))
1084 (defmacro completion-last-use-time (completion-entry)
1085 ;; "The time it was last used. In hours since origin. Used to decide
1086 ;; whether to save it. T if one should always save it."
1087 (list 'nth 2 completion-entry))
1089 (defmacro completion-source (completion-entry)
1090 (list 'nth 3 completion-entry))
1092 ;;; WRITER MACROS
1093 (defmacro set-completion-string (completion-entry string)
1094 (list 'setcar completion-entry string))
1096 (defmacro set-completion-num-uses (completion-entry num-uses)
1097 (list 'setcar (list 'cdr completion-entry) num-uses))
1099 (defmacro set-completion-last-use-time (completion-entry last-use-time)
1100 (list 'setcar (list 'cdr (list 'cdr completion-entry)) last-use-time))
1102 ;;; CONSTRUCTOR
1103 (defun make-completion (string)
1104 "Returns a list of a completion entry."
1105 (list (list string 0 nil current-completion-source)))
1107 ;; Obsolete
1108 ;;(defmacro cmpl-prefix-entry-symbol (completion-entry)
1109 ;; (list 'car (list 'cdr completion-entry)))
1113 ;;;-----------------------------------------------
1114 ;;; Prefix symbol entry definition
1115 ;;;-----------------------------------------------
1116 ;;; A cons of (head . tail)
1118 ;;; READER Macros
1120 (defmacro cmpl-prefix-entry-head (prefix-entry)
1121 (list 'car prefix-entry))
1123 (defmacro cmpl-prefix-entry-tail (prefix-entry)
1124 (list 'cdr prefix-entry))
1126 ;;; WRITER Macros
1128 (defmacro set-cmpl-prefix-entry-head (prefix-entry new-head)
1129 (list 'setcar prefix-entry new-head))
1131 (defmacro set-cmpl-prefix-entry-tail (prefix-entry new-tail)
1132 (list 'setcdr prefix-entry new-tail))
1134 ;;; Constructor
1136 (defun make-cmpl-prefix-entry (completion-entry-list)
1137 "Makes a new prefix entry containing only completion-entry."
1138 (cons completion-entry-list completion-entry-list))
1140 ;;;-----------------------------------------------
1141 ;;; Completion Database - Utilities
1142 ;;;-----------------------------------------------
1144 (defun clear-all-completions ()
1145 "Initializes the completion storage. All existing completions are lost."
1146 (interactive)
1147 (setq cmpl-prefix-obarray (make-vector cmpl-obarray-length 0))
1148 (setq cmpl-obarray (make-vector cmpl-obarray-length 0))
1149 (cmpl-statistics-block
1150 (record-clear-all-completions))
1153 (defun list-all-completions ()
1154 "Returns a list of all the known completion entries."
1155 (let ((return-completions nil))
1156 (mapatoms 'list-all-completions-1 cmpl-prefix-obarray)
1157 return-completions))
1159 (defun list-all-completions-1 (prefix-symbol)
1160 (if (boundp prefix-symbol)
1161 (setq return-completions
1162 (append (cmpl-prefix-entry-head (symbol-value prefix-symbol))
1163 return-completions))))
1165 (defun list-all-completions-by-hash-bucket ()
1166 "Return list of lists of known completion entries, organized by hash bucket."
1167 (let ((return-completions nil))
1168 (mapatoms 'list-all-completions-by-hash-bucket-1 cmpl-prefix-obarray)
1169 return-completions))
1171 (defun list-all-completions-by-hash-bucket-1 (prefix-symbol)
1172 (if (boundp prefix-symbol)
1173 (setq return-completions
1174 (cons (cmpl-prefix-entry-head (symbol-value prefix-symbol))
1175 return-completions))))
1178 ;;;-----------------------------------------------
1179 ;;; Updating the database
1180 ;;;-----------------------------------------------
1182 ;;; These are the internal functions used to update the datebase
1185 (defvar completion-to-accept nil)
1186 ;;"Set to a string that is pending its acceptance."
1187 ;; this checked by the top level reading functions
1189 (defvar cmpl-db-downcase-string nil)
1190 ;; "Setup by find-exact-completion, etc. The given string, downcased."
1191 (defvar cmpl-db-symbol nil)
1192 ;; "The interned symbol corresponding to cmpl-db-downcase-string.
1193 ;; Set up by cmpl-db-symbol."
1194 (defvar cmpl-db-prefix-symbol nil)
1195 ;; "The interned prefix symbol corresponding to cmpl-db-downcase-string."
1196 (defvar cmpl-db-entry nil)
1197 (defvar cmpl-db-debug-p nil
1198 "Set to T if you want to debug the database.")
1200 ;;; READS
1201 (defun find-exact-completion (string)
1202 "Returns the completion entry for string or nil.
1203 Sets up `cmpl-db-downcase-string' and `cmpl-db-symbol'."
1204 (and (boundp (setq cmpl-db-symbol
1205 (intern (setq cmpl-db-downcase-string (downcase string))
1206 cmpl-obarray)))
1207 (symbol-value cmpl-db-symbol)
1210 (defun find-cmpl-prefix-entry (prefix-string)
1211 "Returns the prefix entry for string.
1212 Sets `cmpl-db-prefix-symbol'.
1213 Prefix-string must be exactly `completion-prefix-min-length' long
1214 and downcased. Sets up `cmpl-db-prefix-symbol'."
1215 (and (boundp (setq cmpl-db-prefix-symbol
1216 (intern prefix-string cmpl-prefix-obarray)))
1217 (symbol-value cmpl-db-prefix-symbol)))
1219 (defvar inside-locate-completion-entry nil)
1220 ;; used to trap lossage in silent error correction
1222 (defun locate-completion-entry (completion-entry prefix-entry)
1223 "Locates the completion entry.
1224 Returns a pointer to the element before the completion entry or nil if
1225 the completion entry is at the head.
1226 Must be called after `find-exact-completion'."
1227 (let ((prefix-list (cmpl-prefix-entry-head prefix-entry))
1228 next-prefix-list
1230 (cond
1231 ((not (eq (car prefix-list) completion-entry))
1232 ;; not already at head
1233 (while (and prefix-list
1234 (not (eq completion-entry
1235 (car (setq next-prefix-list (cdr prefix-list)))
1237 (setq prefix-list next-prefix-list))
1238 (cond (;; found
1239 prefix-list)
1240 ;; Didn't find it. Database is messed up.
1241 (cmpl-db-debug-p
1242 ;; not found, error if debug mode
1243 (error "Completion entry exists but not on prefix list - %s"
1244 string))
1245 (inside-locate-completion-entry
1246 ;; recursive error: really scrod
1247 (locate-completion-db-error))
1249 ;; Patch out
1250 (set cmpl-db-symbol nil)
1251 ;; Retry
1252 (locate-completion-entry-retry completion-entry)
1253 ))))))
1255 (defun locate-completion-entry-retry (old-entry)
1256 (let ((inside-locate-completion-entry t))
1257 (add-completion (completion-string old-entry)
1258 (completion-num-uses old-entry)
1259 (completion-last-use-time old-entry))
1260 (let ((cmpl-entry (find-exact-completion (completion-string old-entry)))
1261 (pref-entry
1262 (if cmpl-entry
1263 (find-cmpl-prefix-entry
1264 (substring cmpl-db-downcase-string
1265 0 completion-prefix-min-length))))
1267 (if (and cmpl-entry pref-entry)
1268 ;; try again
1269 (locate-completion-entry cmpl-entry pref-entry)
1270 ;; still losing
1271 (locate-completion-db-error))
1274 (defun locate-completion-db-error ()
1275 ;; recursive error: really scrod
1276 (error "Completion database corrupted. Try M-x clear-all-completions. Send bug report.")
1279 ;;; WRITES
1280 (defun add-completion-to-tail-if-new (string)
1281 "If STRING is not in the database add it to appropriate prefix list.
1282 STRING is added to the end of the appropriate prefix list with
1283 num-uses = 0. The database is unchanged if it is there. STRING must be
1284 longer than `completion-prefix-min-length'.
1285 This must be very fast.
1286 Returns the completion entry."
1287 (or (find-exact-completion string)
1288 ;; not there
1289 (let (;; create an entry
1290 (entry (make-completion string))
1291 ;; setup the prefix
1292 (prefix-entry (find-cmpl-prefix-entry
1293 (substring cmpl-db-downcase-string 0
1294 (cmpl-read-time-eval
1295 completion-prefix-min-length))))
1297 ;; The next two forms should happen as a unit (atomically) but
1298 ;; no fatal errors should result if that is not the case.
1299 (cond (prefix-entry
1300 ;; These two should be atomic, but nothing fatal will happen
1301 ;; if they're not.
1302 (setcdr (cmpl-prefix-entry-tail prefix-entry) entry)
1303 (set-cmpl-prefix-entry-tail prefix-entry entry))
1305 (set cmpl-db-prefix-symbol (make-cmpl-prefix-entry entry))
1307 ;; statistics
1308 (cmpl-statistics-block
1309 (note-added-completion))
1310 ;; set symbol
1311 (set cmpl-db-symbol (car entry))
1314 (defun add-completion-to-head (string)
1315 "If STRING is not in the database, add it to prefix list.
1316 STRING is added to the head of the appropriate prefix list. Otherwise
1317 it is moved to the head of the list.
1318 STRING must be longer than `completion-prefix-min-length'.
1319 Updates the saved string with the supplied string.
1320 This must be very fast.
1321 Returns the completion entry."
1322 ;; Handle pending acceptance
1323 (if completion-to-accept (accept-completion))
1324 ;; test if already in database
1325 (if (setq cmpl-db-entry (find-exact-completion string))
1326 ;; found
1327 (let* ((prefix-entry (find-cmpl-prefix-entry
1328 (substring cmpl-db-downcase-string 0
1329 (cmpl-read-time-eval
1330 completion-prefix-min-length))))
1331 (splice-ptr (locate-completion-entry cmpl-db-entry prefix-entry))
1332 (cmpl-ptr (cdr splice-ptr))
1334 ;; update entry
1335 (set-completion-string cmpl-db-entry string)
1336 ;; move to head (if necessary)
1337 (cond (splice-ptr
1338 ;; These should all execute atomically but it is not fatal if
1339 ;; they don't.
1340 ;; splice it out
1341 (or (setcdr splice-ptr (cdr cmpl-ptr))
1342 ;; fix up tail if necessary
1343 (set-cmpl-prefix-entry-tail prefix-entry splice-ptr))
1344 ;; splice in at head
1345 (setcdr cmpl-ptr (cmpl-prefix-entry-head prefix-entry))
1346 (set-cmpl-prefix-entry-head prefix-entry cmpl-ptr)
1348 cmpl-db-entry)
1349 ;; not there
1350 (let (;; create an entry
1351 (entry (make-completion string))
1352 ;; setup the prefix
1353 (prefix-entry (find-cmpl-prefix-entry
1354 (substring cmpl-db-downcase-string 0
1355 (cmpl-read-time-eval
1356 completion-prefix-min-length))))
1358 (cond (prefix-entry
1359 ;; Splice in at head
1360 (setcdr entry (cmpl-prefix-entry-head prefix-entry))
1361 (set-cmpl-prefix-entry-head prefix-entry entry))
1363 ;; Start new prefix entry
1364 (set cmpl-db-prefix-symbol (make-cmpl-prefix-entry entry))
1366 ;; statistics
1367 (cmpl-statistics-block
1368 (note-added-completion))
1369 ;; Add it to the symbol
1370 (set cmpl-db-symbol (car entry))
1373 (defun delete-completion (string)
1374 "Deletes the completion from the database.
1375 String must be longer than `completion-prefix-min-length'."
1376 ;; Handle pending acceptance
1377 (if completion-to-accept (accept-completion))
1378 (if (setq cmpl-db-entry (find-exact-completion string))
1379 ;; found
1380 (let* ((prefix-entry (find-cmpl-prefix-entry
1381 (substring cmpl-db-downcase-string 0
1382 (cmpl-read-time-eval
1383 completion-prefix-min-length))))
1384 (splice-ptr (locate-completion-entry cmpl-db-entry prefix-entry))
1386 ;; delete symbol reference
1387 (set cmpl-db-symbol nil)
1388 ;; remove from prefix list
1389 (cond (splice-ptr
1390 ;; not at head
1391 (or (setcdr splice-ptr (cdr (cdr splice-ptr)))
1392 ;; fix up tail if necessary
1393 (set-cmpl-prefix-entry-tail prefix-entry splice-ptr))
1396 ;; at head
1397 (or (set-cmpl-prefix-entry-head
1398 prefix-entry (cdr (cmpl-prefix-entry-head prefix-entry)))
1399 ;; List is now empty
1400 (set cmpl-db-prefix-symbol nil))
1402 (cmpl-statistics-block
1403 (note-completion-deleted))
1405 (error "Unknown completion: %s. Couldn't delete it." string)
1408 ;;; Tests --
1409 ;;; - Add and Find -
1410 ;;; (add-completion-to-head "banana") --> ("banana" 0 nil 0)
1411 ;;; (find-exact-completion "banana") --> ("banana" 0 nil 0)
1412 ;;; (find-exact-completion "bana") --> nil
1413 ;;; (car (find-cmpl-prefix-entry "ban")) --> (("banana" ...))
1414 ;;; (cdr (find-cmpl-prefix-entry "ban")) --> (("banana" ...))
1415 ;;; (add-completion-to-head "banish") --> ("banish" 0 nil 0)
1416 ;;; (find-exact-completion "banish") --> ("banish" 0 nil 0)
1417 ;;; (car (find-cmpl-prefix-entry "ban")) --> (("banish" ...) ("banana" ...))
1418 ;;; (cdr (find-cmpl-prefix-entry "ban")) --> (("banana" ...))
1419 ;;; (add-completion-to-head "banana") --> ("banana" 0 nil 0)
1420 ;;; (car (find-cmpl-prefix-entry "ban")) --> (("banana" ...) ("banish" ...))
1421 ;;; (cdr (find-cmpl-prefix-entry "ban")) --> (("banish" ...))
1423 ;;; - Deleting -
1424 ;;; (add-completion-to-head "banner") --> ("banner" 0 nil 0)
1425 ;;; (delete-completion "banner")
1426 ;;; (find-exact-completion "banner") --> nil
1427 ;;; (car (find-cmpl-prefix-entry "ban")) --> (("banana" ...) ("banish" ...))
1428 ;;; (cdr (find-cmpl-prefix-entry "ban")) --> (("banish" ...))
1429 ;;; (add-completion-to-head "banner") --> ("banner" 0 nil 0)
1430 ;;; (delete-completion "banana")
1431 ;;; (car (find-cmpl-prefix-entry "ban")) --> (("banner" ...) ("banish" ...))
1432 ;;; (cdr (find-cmpl-prefix-entry "ban")) --> (("banish" ...))
1433 ;;; (delete-completion "banner")
1434 ;;; (delete-completion "banish")
1435 ;;; (find-cmpl-prefix-entry "ban") --> nil
1436 ;;; (delete-completion "banner") --> error
1438 ;;; - Tail -
1439 ;;; (add-completion-to-tail-if-new "banana") --> ("banana" 0 nil 0)
1440 ;;; (car (find-cmpl-prefix-entry "ban")) --> (("banana" ...))
1441 ;;; (cdr (find-cmpl-prefix-entry "ban")) --> (("banana" ...))
1442 ;;; (add-completion-to-tail-if-new "banish") --> ("banish" 0 nil 0)
1443 ;;; (car (find-cmpl-prefix-entry "ban")) -->(("banana" ...) ("banish" ...))
1444 ;;; (cdr (find-cmpl-prefix-entry "ban")) -->(("banish" ...))
1448 ;;;---------------------------------------------------------------------------
1449 ;;; Database Update :: Interface level routines
1450 ;;;---------------------------------------------------------------------------
1451 ;;;
1452 ;;; These lie on top of the database ref. functions but below the standard
1453 ;;; user interface level
1456 (defun interactive-completion-string-reader (prompt)
1457 (let* ((default (symbol-under-or-before-point))
1458 (new-prompt
1459 (if default
1460 (format "%s: (default: %s) " prompt default)
1461 (format "%s: " prompt))
1463 (read (completing-read new-prompt cmpl-obarray))
1465 (if (zerop (length read)) (setq read (or default "")))
1466 (list read)
1469 (defun check-completion-length (string)
1470 (if (< (length string) completion-min-length)
1471 (error "The string \"%s\" is too short to be saved as a completion."
1472 string)
1473 (list string)))
1475 (defun add-completion (string &optional num-uses last-use-time)
1476 "Add STRING to completion list, or move it to head of list.
1477 The completion is altered appropriately if num-uses and/or last-use-time is
1478 specified."
1479 (interactive (interactive-completion-string-reader "Completion to add"))
1480 (check-completion-length string)
1481 (let* ((current-completion-source (if (interactive-p)
1482 cmpl-source-interactive
1483 current-completion-source))
1484 (entry (add-completion-to-head string)))
1486 (if num-uses (set-completion-num-uses entry num-uses))
1487 (if last-use-time
1488 (set-completion-last-use-time entry last-use-time))
1491 (defun add-permanent-completion (string)
1492 "Add STRING if it isn't already listed, and mark it permanent."
1493 (interactive
1494 (interactive-completion-string-reader "Completion to add permanently"))
1495 (let ((current-completion-source (if (interactive-p)
1496 cmpl-source-interactive
1497 current-completion-source))
1499 (add-completion string nil t)
1502 (defun kill-completion (string)
1503 (interactive (interactive-completion-string-reader "Completion to kill"))
1504 (check-completion-length string)
1505 (delete-completion string)
1508 (defun accept-completion ()
1509 "Accepts the pending completion in `completion-to-accept'.
1510 This bumps num-uses. Called by `add-completion-to-head' and
1511 `completion-search-reset'."
1512 (let ((string completion-to-accept)
1513 ;; if this is added afresh here, then it must be a cdabbrev
1514 (current-completion-source cmpl-source-cdabbrev)
1515 entry
1517 (setq completion-to-accept nil)
1518 (setq entry (add-completion-to-head string))
1519 (set-completion-num-uses entry (1+ (completion-num-uses entry)))
1520 (setq cmpl-completions-accepted-p t)
1523 (defun use-completion-under-point ()
1524 "Add the completion symbol underneath the point into the completion buffer."
1525 (let ((string (and enable-completion (symbol-under-point)))
1526 (current-completion-source cmpl-source-cursor-moves))
1527 (if string (add-completion-to-head string))))
1529 (defun use-completion-before-point ()
1530 "Add the completion symbol before point into the completion buffer."
1531 (let ((string (and enable-completion (symbol-before-point)))
1532 (current-completion-source cmpl-source-cursor-moves))
1533 (if string (add-completion-to-head string))))
1535 (defun use-completion-under-or-before-point ()
1536 "Add the completion symbol before point into the completion buffer."
1537 (let ((string (and enable-completion (symbol-under-or-before-point)))
1538 (current-completion-source cmpl-source-cursor-moves))
1539 (if string (add-completion-to-head string))))
1541 (defun use-completion-before-separator ()
1542 "Add the completion symbol before point into the completion buffer.
1543 Completions added this way will automatically be saved if
1544 `completion-on-separator-character' is non-nil."
1545 (let ((string (and enable-completion (symbol-before-point)))
1546 (current-completion-source cmpl-source-separator)
1547 entry)
1548 (cmpl-statistics-block
1549 (note-separator-character string)
1551 (cond (string
1552 (setq entry (add-completion-to-head string))
1553 (when (and completion-on-separator-character
1554 (zerop (completion-num-uses entry)))
1555 (set-completion-num-uses entry 1)
1556 (setq cmpl-completions-accepted-p t)
1560 ;;; Tests --
1561 ;;; - Add and Find -
1562 ;;; (add-completion "banana" 5 10)
1563 ;;; (find-exact-completion "banana") --> ("banana" 5 10 0)
1564 ;;; (add-completion "banana" 6)
1565 ;;; (find-exact-completion "banana") --> ("banana" 6 10 0)
1566 ;;; (add-completion "banish")
1567 ;;; (car (find-cmpl-prefix-entry "ban")) --> (("banish" ...) ("banana" ...))
1569 ;;; - Accepting -
1570 ;;; (setq completion-to-accept "banana")
1571 ;;; (accept-completion)
1572 ;;; (find-exact-completion "banana") --> ("banana" 7 10)
1573 ;;; (car (find-cmpl-prefix-entry "ban")) --> (("banana" ...) ("banish" ...))
1574 ;;; (setq completion-to-accept "banish")
1575 ;;; (add-completion "banner")
1576 ;;; (car (find-cmpl-prefix-entry "ban"))
1577 ;;; --> (("banner" ...) ("banish" 1 ...) ("banana" 7 ...))
1579 ;;; - Deleting -
1580 ;;; (kill-completion "banish")
1581 ;;; (car (find-cmpl-prefix-entry "ban")) --> (("banner" ...) ("banana" ...))
1584 ;;;---------------------------------------------------------------------------
1585 ;;; Searching the database
1586 ;;;---------------------------------------------------------------------------
1587 ;;; Functions outside this block must call completion-search-reset followed
1588 ;;; by calls to completion-search-next or completion-search-peek
1591 ;;; Status variables
1592 ;; Commented out to improve loading speed
1593 (defvar cmpl-test-string "")
1594 ;; "The current string used by completion-search-next."
1595 (defvar cmpl-test-regexp "")
1596 ;; "The current regexp used by completion-search-next.
1597 ;; (derived from cmpl-test-string)"
1598 (defvar cmpl-last-index 0)
1599 ;; "The last index that completion-search-next was called with."
1600 (defvar cmpl-cdabbrev-reset-p nil)
1601 ;; "Set to t when cdabbrevs have been reset."
1602 (defvar cmpl-next-possibilities nil)
1603 ;; "A pointer to the element BEFORE the next set of possible completions.
1604 ;; cadr of this is the cmpl-next-possibility"
1605 (defvar cmpl-starting-possibilities nil)
1606 ;; "The initial list of starting possibilities."
1607 (defvar cmpl-next-possibility nil)
1608 ;; "The cached next possibility."
1609 (defvar cmpl-tried-list nil)
1610 ;; "A downcased list of all the completions we have tried."
1613 (defun completion-search-reset (string)
1614 "Set up the for completion searching for STRING.
1615 STRING must be longer than `completion-prefix-min-length'."
1616 (if completion-to-accept (accept-completion))
1617 (setq cmpl-starting-possibilities
1618 (cmpl-prefix-entry-head
1619 (find-cmpl-prefix-entry (downcase (substring string 0 3))))
1620 cmpl-test-string string
1621 cmpl-test-regexp (concat (regexp-quote string) "."))
1622 (completion-search-reset-1)
1625 (defun completion-search-reset-1 ()
1626 (setq cmpl-next-possibilities cmpl-starting-possibilities
1627 cmpl-next-possibility nil
1628 cmpl-cdabbrev-reset-p nil
1629 cmpl-last-index -1
1630 cmpl-tried-list nil
1633 (defun completion-search-next (index)
1634 "Return the next completion entry.
1635 If INDEX is out of sequence, reset and start from the top.
1636 If there are no more entries, try cdabbrev and returns only a string."
1637 (cond
1638 ((= index (setq cmpl-last-index (1+ cmpl-last-index)))
1639 (completion-search-peek t))
1640 ((minusp index)
1641 (completion-search-reset-1)
1642 (setq cmpl-last-index index)
1643 ;; reverse the possibilities list
1644 (setq cmpl-next-possibilities (reverse cmpl-starting-possibilities))
1645 ;; do a "normal" search
1646 (while (and (completion-search-peek nil)
1647 (minusp (setq index (1+ index))))
1648 (setq cmpl-next-possibility nil)
1650 (cond ((not cmpl-next-possibilities))
1651 ;; If no more possibilities, leave it that way
1652 ((= -1 cmpl-last-index)
1653 ;; next completion is at index 0. reset next-possibility list
1654 ;; to start at beginning
1655 (setq cmpl-next-possibilities cmpl-starting-possibilities))
1657 ;; otherwise point to one before current
1658 (setq cmpl-next-possibilities
1659 (nthcdr (- (length cmpl-starting-possibilities)
1660 (length cmpl-next-possibilities))
1661 cmpl-starting-possibilities))
1664 ;; non-negative index, reset and search
1665 ;;(prin1 'reset)
1666 (completion-search-reset-1)
1667 (setq cmpl-last-index index)
1668 (while (and (completion-search-peek t)
1669 (not (minusp (setq index (1- index)))))
1670 (setq cmpl-next-possibility nil)
1673 (prog1
1674 cmpl-next-possibility
1675 (setq cmpl-next-possibility nil)
1679 (defun completion-search-peek (use-cdabbrev)
1680 "Returns the next completion entry without actually moving the pointers.
1681 Calling this again or calling `completion-search-next' results in the same
1682 string being returned. Depends on `case-fold-search'.
1683 If there are no more entries, try cdabbrev and then return only a string."
1684 (cond
1685 ;; return the cached value if we have it
1686 (cmpl-next-possibility)
1687 ((and cmpl-next-possibilities
1688 ;; still a few possibilities left
1689 (progn
1690 (while
1691 (and (not (eq 0 (string-match cmpl-test-regexp
1692 (completion-string (car cmpl-next-possibilities)))))
1693 (setq cmpl-next-possibilities (cdr cmpl-next-possibilities))
1695 cmpl-next-possibilities
1697 ;; successful match
1698 (setq cmpl-next-possibility (car cmpl-next-possibilities)
1699 cmpl-tried-list (cons (downcase (completion-string cmpl-next-possibility))
1700 cmpl-tried-list)
1701 cmpl-next-possibilities (cdr cmpl-next-possibilities)
1703 cmpl-next-possibility)
1704 (use-cdabbrev
1705 ;; unsuccessful, use cdabbrev
1706 (cond ((not cmpl-cdabbrev-reset-p)
1707 (reset-cdabbrev cmpl-test-string cmpl-tried-list)
1708 (setq cmpl-cdabbrev-reset-p t)
1710 (setq cmpl-next-possibility (next-cdabbrev))
1712 ;; Completely unsuccessful, return nil
1715 ;;; Tests --
1716 ;;; - Add and Find -
1717 ;;; (add-completion "banana")
1718 ;;; (completion-search-reset "ban")
1719 ;;; (completion-search-next 0) --> "banana"
1721 ;;; - Discrimination -
1722 ;;; (add-completion "cumberland")
1723 ;;; (add-completion "cumberbund")
1724 ;;; cumbering
1725 ;;; (completion-search-reset "cumb")
1726 ;;; (completion-search-peek t) --> "cumberbund"
1727 ;;; (completion-search-next 0) --> "cumberbund"
1728 ;;; (completion-search-peek t) --> "cumberland"
1729 ;;; (completion-search-next 1) --> "cumberland"
1730 ;;; (completion-search-peek nil) --> nil
1731 ;;; (completion-search-next 2) --> "cumbering" {cdabbrev}
1732 ;;; (completion-search-next 3) --> nil or "cumming"{depends on context}
1733 ;;; (completion-search-next 1) --> "cumberland"
1734 ;;; (completion-search-peek t) --> "cumbering" {cdabbrev}
1736 ;;; - Accepting -
1737 ;;; (completion-search-next 1) --> "cumberland"
1738 ;;; (setq completion-to-accept "cumberland")
1739 ;;; (completion-search-reset "foo")
1740 ;;; (completion-search-reset "cum")
1741 ;;; (completion-search-next 0) --> "cumberland"
1743 ;;; - Deleting -
1744 ;;; (kill-completion "cumberland")
1745 ;;; cummings
1746 ;;; (completion-search-reset "cum")
1747 ;;; (completion-search-next 0) --> "cumberbund"
1748 ;;; (completion-search-next 1) --> "cummings"
1750 ;;; - Ignoring Capitalization -
1751 ;;; (completion-search-reset "CuMb")
1752 ;;; (completion-search-next 0) --> "cumberbund"
1756 ;;;-----------------------------------------------
1757 ;;; COMPLETE
1758 ;;;-----------------------------------------------
1760 (defun completion-mode ()
1761 "Toggles whether or not to add new words to the completion database."
1762 (interactive)
1763 (setq enable-completion (not enable-completion))
1764 (message "Completion mode is now %s." (if enable-completion "ON" "OFF"))
1767 (defvar cmpl-current-index 0)
1768 (defvar cmpl-original-string nil)
1769 (defvar cmpl-last-insert-location -1)
1770 (defvar cmpl-leave-point-at-start nil)
1772 (defun complete (&optional arg)
1773 "Fill out a completion of the word before point.
1774 Point is left at end. Consecutive calls rotate through all possibilities.
1775 Prefix args ::
1776 control-u :: leave the point at the beginning of the completion rather
1777 than at the end.
1778 a number :: rotate through the possible completions by that amount
1779 `-' :: same as -1 (insert previous completion)
1780 {See the comments at the top of `completion.el' for more info.}"
1781 (interactive "*p")
1782 ;;; Set up variables
1783 (cond ((eq last-command this-command)
1784 ;; Undo last one
1785 (delete-region cmpl-last-insert-location (point))
1786 ;; get next completion
1787 (setq cmpl-current-index (+ cmpl-current-index (or arg 1)))
1790 (if (not cmpl-initialized-p)
1791 (initialize-completions)) ;; make sure everything's loaded
1792 (cond ((consp current-prefix-arg) ;; control-u
1793 (setq arg 0)
1794 (setq cmpl-leave-point-at-start t)
1797 (setq cmpl-leave-point-at-start nil)
1799 ;; get string
1800 (setq cmpl-original-string (symbol-before-point-for-complete))
1801 (cond ((not cmpl-original-string)
1802 (setq this-command 'failed-complete)
1803 (error "To complete, the point must be after a symbol at least %d character long."
1804 completion-prefix-min-length)))
1805 ;; get index
1806 (setq cmpl-current-index (if current-prefix-arg arg 0))
1807 ;; statistics
1808 (cmpl-statistics-block
1809 (note-complete-entered-afresh cmpl-original-string))
1810 ;; reset database
1811 (completion-search-reset cmpl-original-string)
1812 ;; erase what we've got
1813 (delete-region cmpl-symbol-start cmpl-symbol-end)
1816 ;; point is at the point to insert the new symbol
1817 ;; Get the next completion
1818 (let* ((print-status-p
1819 (and (>= baud-rate completion-prompt-speed-threshold)
1820 (not (minibuffer-window-selected-p))))
1821 (insert-point (point))
1822 (entry (completion-search-next cmpl-current-index))
1823 string
1825 ;; entry is either a completion entry or a string (if cdabbrev)
1827 ;; If found, insert
1828 (cond (entry
1829 ;; Setup for proper case
1830 (setq string (if (stringp entry)
1831 entry (completion-string entry)))
1832 (setq string (cmpl-merge-string-cases
1833 string cmpl-original-string))
1834 ;; insert
1835 (insert string)
1836 ;; accept it
1837 (setq completion-to-accept string)
1838 ;; fixup and cache point
1839 (cond (cmpl-leave-point-at-start
1840 (setq cmpl-last-insert-location (point))
1841 (goto-char insert-point))
1842 (t;; point at end,
1843 (setq cmpl-last-insert-location insert-point))
1845 ;; statistics
1846 (cmpl-statistics-block
1847 (note-complete-inserted entry cmpl-current-index))
1848 ;; Done ! cmpl-stat-complete-successful
1849 ;;display the next completion
1850 (cond
1851 ((and print-status-p
1852 ;; This updates the display and only prints if there
1853 ;; is no typeahead
1854 (sit-for 0)
1855 (setq entry
1856 (completion-search-peek
1857 completion-cdabbrev-prompt-flag)))
1858 (setq string (if (stringp entry)
1859 entry (completion-string entry)))
1860 (setq string (cmpl-merge-string-cases
1861 string cmpl-original-string))
1862 (message "Next completion: %s" string)
1865 (t;; none found, insert old
1866 (insert cmpl-original-string)
1867 ;; Don't accept completions
1868 (setq completion-to-accept nil)
1869 ;; print message
1870 ;; This used to call cmpl19-sit-for, an undefined function.
1871 ;; I hope that sit-for does the right thing; I don't know -- rms.
1872 (if (and print-status-p (sit-for 0))
1873 (message "No %scompletions."
1874 (if (eq this-command last-command) "more " "")))
1875 ;; statistics
1876 (cmpl-statistics-block
1877 (record-complete-failed cmpl-current-index))
1878 ;; Pretend that we were never here
1879 (setq this-command 'failed-complete)
1880 ))))
1882 ;;;-----------------------------------------------
1883 ;;; "Complete" Key Keybindings
1884 ;;;-----------------------------------------------
1886 (global-set-key "\M-\r" 'complete)
1887 (global-set-key [?\C-\r] 'complete)
1888 (define-key function-key-map [C-return] [?\C-\r])
1890 ;;; Tests -
1891 ;;; (add-completion "cumberland")
1892 ;;; (add-completion "cumberbund")
1893 ;;; cum
1894 ;;; Cumber
1895 ;;; cumbering
1896 ;;; cumb
1899 ;;;---------------------------------------------------------------------------
1900 ;;; Parsing definitions from files into the database
1901 ;;;---------------------------------------------------------------------------
1903 ;;;-----------------------------------------------
1904 ;;; Top Level functions ::
1905 ;;;-----------------------------------------------
1907 ;;; User interface
1908 (defun add-completions-from-file (file)
1909 "Parse possible completions from a file and add them to data base."
1910 (interactive "fFile: ")
1911 (setq file (expand-file-name file))
1912 (let* ((buffer (get-file-buffer file))
1913 (buffer-already-there-p buffer)
1915 (when (not buffer-already-there-p)
1916 (let ((completions-merging-modes nil))
1917 (setq buffer (find-file-noselect file))
1919 (unwind-protect
1920 (save-excursion
1921 (set-buffer buffer)
1922 (add-completions-from-buffer)
1924 (when (not buffer-already-there-p)
1925 (kill-buffer buffer))
1928 (defun add-completions-from-buffer ()
1929 (interactive)
1930 (let ((current-completion-source cmpl-source-file-parsing)
1931 (start-num
1932 (cmpl-statistics-block
1933 (aref completion-add-count-vector cmpl-source-file-parsing)))
1934 mode
1936 (cond ((memq major-mode '(emacs-lisp-mode lisp-mode))
1937 (add-completions-from-lisp-buffer)
1938 (setq mode 'lisp)
1940 ((memq major-mode '(c-mode))
1941 (add-completions-from-c-buffer)
1942 (setq mode 'c)
1945 (error "Do not know how to parse completions in %s buffers."
1946 major-mode)
1948 (cmpl-statistics-block
1949 (record-cmpl-parse-file
1950 mode (point-max)
1951 (- (aref completion-add-count-vector cmpl-source-file-parsing)
1952 start-num)))
1955 ;;; Find file hook
1956 (defun cmpl-find-file-hook ()
1957 (cond (enable-completion
1958 (cond ((and (memq major-mode '(emacs-lisp-mode lisp-mode))
1959 (memq 'lisp completions-merging-modes)
1961 (add-completions-from-buffer))
1962 ((and (memq major-mode '(c-mode))
1963 (memq 'c completions-merging-modes)
1965 (add-completions-from-buffer)
1969 (pushnew 'cmpl-find-file-hook find-file-hooks)
1971 ;;;-----------------------------------------------
1972 ;;; Tags Table Completions
1973 ;;;-----------------------------------------------
1975 (defun add-completions-from-tags-table ()
1976 ;; Inspired by eero@media-lab.media.mit.edu
1977 "Add completions from the current tags table."
1978 (interactive)
1979 (visit-tags-table-buffer) ;this will prompt if no tags-table
1980 (save-excursion
1981 (goto-char (point-min))
1982 (let (string)
1983 (condition-case e
1984 (while t
1985 (search-forward "\177")
1986 (backward-char 3)
1987 (and (setq string (symbol-under-point))
1988 (add-completion-to-tail-if-new string))
1989 (forward-char 3)
1991 (search-failed)
1992 ))))
1995 ;;;-----------------------------------------------
1996 ;;; Lisp File completion parsing
1997 ;;;-----------------------------------------------
1998 ;;; This merely looks for phrases beginning with (def.... or
1999 ;;; (package:def ... and takes the next word.
2001 ;;; We tried using forward-lines and explicit searches but the regexp technique
2002 ;;; was faster. (About 100K characters per second)
2004 (defconst *lisp-def-regexp*
2005 "\n(\\(\\w*:\\)?def\\(\\w\\|\\s_\\)*\\s +(*"
2006 "A regexp that searches for lisp definition form."
2009 ;;; Tests -
2010 ;;; (and (string-match *lisp-def-regexp* "\n(defun foo") (match-end 0)) -> 8
2011 ;;; (and (string-match *lisp-def-regexp* "\n(si:def foo") (match-end 0)) -> 9
2012 ;;; (and (string-match *lisp-def-regexp* "\n(def-bar foo")(match-end 0)) -> 10
2013 ;;; (and (string-match *lisp-def-regexp* "\n(defun (foo") (match-end 0)) -> 9
2015 ;;; Parses all the definition names from a Lisp mode buffer and adds them to
2016 ;;; the completion database.
2017 (defun add-completions-from-lisp-buffer ()
2018 ;;; Benchmarks
2019 ;;; Sun-3/280 - 1500 to 3000 lines of lisp code per second
2020 (let (string)
2021 (save-excursion
2022 (goto-char (point-min))
2023 (condition-case e
2024 (while t
2025 (re-search-forward *lisp-def-regexp*)
2026 (and (setq string (symbol-under-point))
2027 (add-completion-to-tail-if-new string))
2029 (search-failed)
2030 ))))
2033 ;;;-----------------------------------------------
2034 ;;; C file completion parsing
2035 ;;;-----------------------------------------------
2036 ;;; C :
2037 ;;; Looks for #define or [<storage class>] [<type>] <name>{,<name>}
2038 ;;; or structure, array or pointer defs.
2039 ;;; It gets most of the definition names.
2041 ;;; As you might suspect by now, we use some symbol table hackery
2043 ;;; Symbol separator chars (have whitespace syntax) --> , ; * = (
2044 ;;; Opening char --> [ {
2045 ;;; Closing char --> ] }
2046 ;;; opening and closing must be skipped over
2047 ;;; Whitespace chars (have symbol syntax)
2048 ;;; Everything else has word syntax
2050 (defun cmpl-make-c-def-completion-syntax-table ()
2051 (let ((table (make-vector 256 0))
2052 (whitespace-chars '(? ?\n ?\t ?\f ?\v ?\r))
2053 ;; unfortunately the ?( causes the parens to appear unbalanced
2054 (separator-chars '(?, ?* ?= ?\( ?\;
2057 ;; default syntax is whitespace
2058 (dotimes (i 256)
2059 (modify-syntax-entry i "w" table))
2060 (dolist (char whitespace-chars)
2061 (modify-syntax-entry char "_" table))
2062 (dolist (char separator-chars)
2063 (modify-syntax-entry char " " table))
2064 (modify-syntax-entry ?\[ "(]" table)
2065 (modify-syntax-entry ?\{ "(}" table)
2066 (modify-syntax-entry ?\] ")[" table)
2067 (modify-syntax-entry ?\} "){" table)
2068 table))
2070 (defconst cmpl-c-def-syntax-table (cmpl-make-c-def-completion-syntax-table))
2072 ;;; Regexps
2073 (defconst *c-def-regexp*
2074 ;; This stops on lines with possible definitions
2075 "\n[_a-zA-Z#]"
2076 ;; This stops after the symbol to add.
2077 ;;"\n\\(#define\\s +.\\|\\(\\(\\w\\|\\s_\\)+\\b\\s *\\)+[(;,[*{=]\\)"
2078 ;; This stops before the symbol to add. {Test cases in parens. below}
2079 ;;"\n\\(\\(\\w\\|\\s_\\)+\\s *(\\|\\(\\(#define\\|auto\\|extern\\|register\\|static\\|int\\|long\\|short\\|unsigned\\|char\\|void\\|float\\|double\\|enum\\|struct\\|union\\|typedef\\)\\s +\\)+\\)"
2080 ;; this simple version picks up too much extraneous stuff
2081 ;; "\n\\(\\w\\|\\s_\\|#\\)\\B"
2082 "A regexp that searches for a definition form."
2085 ;(defconst *c-cont-regexp*
2086 ; "\\(\\w\\|\\s_\\)+\\b\\s *\\({\\|\\(\\[[0-9\t ]*\\]\\s *\\)*,\\(*\\|\\s \\)*\\b\\)"
2087 ; "This regexp should be used in a looking-at to parse for lists of variables.")
2089 ;(defconst *c-struct-regexp*
2090 ; "\\(*\\|\\s \\)*\\b"
2091 ; "This regexp should be used to test whether a symbol follows a structure definition.")
2093 ;(defun test-c-def-regexp (regexp string)
2094 ; (and (eq 0 (string-match regexp string)) (match-end 0))
2097 ;;; Tests -
2098 ;;; (test-c-def-regexp *c-def-regexp* "\n#define foo") -> 10 (9)
2099 ;;; (test-c-def-regexp *c-def-regexp* "\nfoo (x, y) {") -> 6 (6)
2100 ;;; (test-c-def-regexp *c-def-regexp* "\nint foo (x, y)") -> 10 (5)
2101 ;;; (test-c-def-regexp *c-def-regexp* "\n int foo (x, y)") -> nil
2102 ;;; (test-c-def-regexp *c-cont-regexp* "oo, bar") -> 4
2103 ;;; (test-c-def-regexp *c-cont-regexp* "oo, *bar") -> 5
2104 ;;; (test-c-def-regexp *c-cont-regexp* "a [5][6], bar") -> 10
2105 ;;; (test-c-def-regexp *c-cont-regexp* "oo(x,y)") -> nil
2106 ;;; (test-c-def-regexp *c-cont-regexp* "a [6] ,\t bar") -> 9
2107 ;;; (test-c-def-regexp *c-cont-regexp* "oo {trout =1} my_carp;") -> 14
2108 ;;; (test-c-def-regexp *c-cont-regexp* "truct_p complex foon") -> nil
2110 ;;; Parses all the definition names from a C mode buffer and adds them to the
2111 ;;; completion database.
2112 (defun add-completions-from-c-buffer ()
2113 ;; Benchmark --
2114 ;; Sun 3/280-- 1250 lines/sec.
2116 (let (string next-point char
2117 (saved-syntax (syntax-table))
2119 (save-excursion
2120 (goto-char (point-min))
2121 (catch 'finish-add-completions
2122 (unwind-protect
2123 (while t
2124 ;; we loop here only when scan-sexps fails
2125 ;; (i.e. unbalance exps.)
2126 (set-syntax-table cmpl-c-def-syntax-table)
2127 (condition-case e
2128 (while t
2129 (re-search-forward *c-def-regexp*)
2130 (cond
2131 ((= (preceding-char) ?#)
2132 ;; preprocessor macro, see if it's one we handle
2133 (setq string (buffer-substring (point) (+ (point) 6)))
2134 (cond ((or (string-equal string "define")
2135 (string-equal string "ifdef ")
2137 ;; skip forward over definition symbol
2138 ;; and add it to database
2139 (and (forward-word 2)
2140 (setq string (symbol-before-point))
2141 ;;(push string foo)
2142 (add-completion-to-tail-if-new string)
2143 ))))
2145 ;; C definition
2146 (setq next-point (point))
2147 (while (and
2148 next-point
2149 ;; scan to next separator char.
2150 (setq next-point (scan-sexps next-point 1))
2152 ;; position the point on the word we want to add
2153 (goto-char next-point)
2154 (while (= (setq char (following-char)) ?*)
2155 ;; handle pointer ref
2156 ;; move to next separator char.
2157 (goto-char
2158 (setq next-point (scan-sexps (point) 1)))
2160 (forward-word -1)
2161 ;; add to database
2162 (if (setq string (symbol-under-point))
2163 ;; (push string foo)
2164 (add-completion-to-tail-if-new string)
2165 ;; Local TMC hack (useful for parsing paris.h)
2166 (if (and (looking-at "_AP") ;; "ansi prototype"
2167 (progn
2168 (forward-word -1)
2169 (setq string
2170 (symbol-under-point))
2172 (add-completion-to-tail-if-new string)
2175 ;; go to next
2176 (goto-char next-point)
2177 ;; (push (format "%c" (following-char)) foo)
2178 (if (= (char-syntax char) ?\()
2179 ;; if on an opening delimiter, go to end
2180 (while (= (char-syntax char) ?\()
2181 (setq next-point (scan-sexps next-point 1)
2182 char (char-after next-point))
2184 (or (= char ?,)
2185 ;; Current char is an end char.
2186 (setq next-point nil)
2188 ))))
2189 (search-failed ;;done
2190 (throw 'finish-add-completions t)
2192 (error
2193 ;; Check for failure in scan-sexps
2194 (if (or (string-equal (second e)
2195 "Containing expression ends prematurely")
2196 (string-equal (second e) "Unbalanced parentheses"))
2197 ;; unbalanced paren., keep going
2198 ;;(ding)
2199 (forward-line 1)
2200 (message "Error parsing C buffer for completions. Please bug report.")
2201 (throw 'finish-add-completions t)
2204 (set-syntax-table saved-syntax)
2205 )))))
2208 ;;;---------------------------------------------------------------------------
2209 ;;; Init files
2210 ;;;---------------------------------------------------------------------------
2212 ;;; The version of save-completions-to-file called at kill-emacs time.
2213 (defun kill-emacs-save-completions ()
2214 (when (and save-completions-flag enable-completion cmpl-initialized-p)
2215 (cond
2216 ((not cmpl-completions-accepted-p)
2217 (message "Completions database has not changed - not writing."))
2219 (save-completions-to-file)
2223 (defconst saved-cmpl-file-header
2224 ";;; Completion Initialization file.
2225 ;;; Version = %s
2226 ;;; Format is (<string> . <last-use-time>)
2227 ;;; <string> is the completion
2228 ;;; <last-use-time> is the time the completion was last used
2229 ;;; If it is t, the completion will never be pruned from the file.
2230 ;;; Otherwise it is in hours since origin.
2231 \n")
2233 (defun completion-backup-filename (filename)
2234 (concat filename ".BAK"))
2236 (defun save-completions-to-file (&optional filename)
2237 "Save completions in init file FILENAME.
2238 If file name is not specified, use `save-completions-file-name'."
2239 (interactive)
2240 (setq filename (expand-file-name (or filename save-completions-file-name)))
2241 (when (file-writable-p filename)
2242 (if (not cmpl-initialized-p)
2243 (initialize-completions));; make sure everything's loaded
2244 (message "Saving completions to file %s" filename)
2246 (let* ((trim-versions-without-asking t)
2247 (kept-old-versions 0)
2248 (kept-new-versions completions-file-versions-kept)
2249 last-use-time
2250 (current-time (cmpl-hours-since-origin))
2251 (total-in-db 0)
2252 (total-perm 0)
2253 (total-saved 0)
2254 (backup-filename (completion-backup-filename filename))
2257 (save-excursion
2258 (get-buffer-create " *completion-save-buffer*")
2259 (set-buffer " *completion-save-buffer*")
2260 (setq buffer-file-name filename)
2262 (when (not (verify-visited-file-modtime (current-buffer)))
2263 ;; file has changed on disk. Bring us up-to-date
2264 (message "Completion file has changed. Merging. . .")
2265 (load-completions-from-file filename t)
2266 (message "Merging finished. Saving completions to file %s" filename)
2269 ;; prepare the buffer to be modified
2270 (clear-visited-file-modtime)
2271 (erase-buffer)
2272 ;; (/ 1 0)
2273 (insert (format saved-cmpl-file-header *completion-version*))
2274 (dolist (completion (list-all-completions))
2275 (setq total-in-db (1+ total-in-db))
2276 (setq last-use-time (completion-last-use-time completion))
2277 ;; Update num uses and maybe write completion to a file
2278 (cond ((or;; Write to file if
2279 ;; permanent
2280 (and (eq last-use-time t)
2281 (setq total-perm (1+ total-perm)))
2282 ;; or if
2283 (if (plusp (completion-num-uses completion))
2284 ;; it's been used
2285 (setq last-use-time current-time)
2286 ;; or it was saved before and
2287 (and last-use-time
2288 ;; save-completions-retention-time is nil
2289 (or (not save-completions-retention-time)
2290 ;; or time since last use is < ...retention-time*
2291 (< (- current-time last-use-time)
2292 save-completions-retention-time))
2294 ;; write to file
2295 (setq total-saved (1+ total-saved))
2296 (insert (prin1-to-string (cons (completion-string completion)
2297 last-use-time)) "\n")
2300 ;; write the buffer
2301 (condition-case e
2302 (let ((file-exists-p (file-exists-p filename)))
2303 (when file-exists-p
2304 ;; If file exists . . .
2305 ;; Save a backup(so GNU doesn't screw us when we're out of disk)
2306 ;; (GNU leaves a 0 length file if it gets a disk full error!)
2308 ;; If backup doesn't exit, Rename current to backup
2309 ;; {If backup exists the primary file is probably messed up}
2310 (unless (file-exists-p backup-filename)
2311 (rename-file filename backup-filename))
2312 ;; Copy the backup back to the current name
2313 ;; (so versioning works)
2314 (copy-file backup-filename filename t)
2316 ;; Save it
2317 (save-buffer)
2318 (when file-exists-p
2319 ;; If successful, remove backup
2320 (delete-file backup-filename)
2322 (error
2323 (set-buffer-modified-p nil)
2324 (message "Couldn't save completion file %s." filename)
2326 ;; Reset accepted-p flag
2327 (setq cmpl-completions-accepted-p nil)
2329 (cmpl-statistics-block
2330 (record-save-completions total-in-db total-perm total-saved))
2333 ;;;(defun autosave-completions ()
2334 ;;; (when (and save-completions-flag enable-completion cmpl-initialized-p
2335 ;;; *completion-auto-save-period*
2336 ;;; (> cmpl-emacs-idle-time *completion-auto-save-period*)
2337 ;;; cmpl-completions-accepted-p)
2338 ;;; (save-completions-to-file)
2339 ;;; ))
2341 ;;;(pushnew 'autosave-completions cmpl-emacs-idle-time-hooks)
2343 (defun load-completions-from-file (&optional filename no-message-p)
2344 "Loads a completion init file FILENAME.
2345 If file is not specified, then use `save-completions-file-name'."
2346 (interactive)
2347 (setq filename (expand-file-name (or filename save-completions-file-name)))
2348 (let* ((backup-filename (completion-backup-filename filename))
2349 (backup-readable-p (file-readable-p backup-filename))
2351 (when backup-readable-p (setq filename backup-filename))
2352 (when (file-readable-p filename)
2353 (if (not no-message-p)
2354 (message "Loading completions from %sfile %s . . ."
2355 (if backup-readable-p "backup " "") filename))
2356 (save-excursion
2357 (get-buffer-create " *completion-save-buffer*")
2358 (set-buffer " *completion-save-buffer*")
2359 (setq buffer-file-name filename)
2360 ;; prepare the buffer to be modified
2361 (clear-visited-file-modtime)
2362 (erase-buffer)
2364 (let ((insert-okay-p nil)
2365 (buffer (current-buffer))
2366 (current-time (cmpl-hours-since-origin))
2367 string num-uses entry last-use-time
2368 cmpl-entry cmpl-last-use-time
2369 (current-completion-source cmpl-source-init-file)
2370 (start-num
2371 (cmpl-statistics-block
2372 (aref completion-add-count-vector cmpl-source-file-parsing)))
2373 (total-in-file 0) (total-perm 0)
2375 ;; insert the file into a buffer
2376 (condition-case e
2377 (progn (insert-file-contents filename t)
2378 (setq insert-okay-p t))
2380 (file-error
2381 (message "File error trying to load completion file %s."
2382 filename)))
2383 ;; parse it
2384 (when insert-okay-p
2385 (goto-char (point-min))
2387 (condition-case e
2388 (while t
2389 (setq entry (read buffer))
2390 (setq total-in-file (1+ total-in-file))
2391 (cond
2392 ((and (consp entry)
2393 (stringp (setq string (car entry)))
2394 (cond
2395 ((eq (setq last-use-time (cdr entry)) 'T)
2396 ;; handle case sensitivity
2397 (setq total-perm (1+ total-perm))
2398 (setq last-use-time t))
2399 ((eq last-use-time t)
2400 (setq total-perm (1+ total-perm)))
2401 ((integerp last-use-time))
2403 ;; Valid entry
2404 ;; add it in
2405 (setq cmpl-last-use-time
2406 (completion-last-use-time
2407 (setq cmpl-entry
2408 (add-completion-to-tail-if-new string))
2410 (if (or (eq last-use-time t)
2411 (and (> last-use-time 1000);;backcompatibility
2412 (not (eq cmpl-last-use-time t))
2413 (or (not cmpl-last-use-time)
2414 ;; more recent
2415 (> last-use-time cmpl-last-use-time))
2417 ;; update last-use-time
2418 (set-completion-last-use-time cmpl-entry last-use-time)
2421 ;; Bad format
2422 (message "Error: invalid saved completion - %s"
2423 (prin1-to-string entry))
2424 ;; try to get back in sync
2425 (search-forward "\n(")
2427 (search-failed
2428 (message "End of file while reading completions.")
2430 (end-of-file
2431 (if (= (point) (point-max))
2432 (if (not no-message-p)
2433 (message "Loading completions from file %s . . . Done."
2434 filename))
2435 (message "End of file while reading completions.")
2439 (cmpl-statistics-block
2440 (record-load-completions
2441 total-in-file total-perm
2442 (- (aref completion-add-count-vector cmpl-source-init-file)
2443 start-num)))
2445 )))))
2447 (defun initialize-completions ()
2448 "Load the default completions file.
2449 Also sets up so that exiting emacs will automatically save the file."
2450 (interactive)
2451 (cond ((not cmpl-initialized-p)
2452 (load-completions-from-file)
2454 (setq cmpl-initialized-p t)
2458 ;;;-----------------------------------------------
2459 ;;; Kill EMACS patch
2460 ;;;-----------------------------------------------
2462 (add-hook 'kill-emacs-hook
2463 '(lambda ()
2464 (kill-emacs-save-completions)
2465 (cmpl-statistics-block
2466 (record-cmpl-kill-emacs))))
2468 ;;;-----------------------------------------------
2469 ;;; Kill region patch
2470 ;;;-----------------------------------------------
2472 (defun completion-kill-region (&optional beg end)
2473 "Kill between point and mark.
2474 The text is deleted but saved in the kill ring.
2475 The command \\[yank] can retrieve it from there.
2476 /(If you want to kill and then yank immediately, use \\[copy-region-as-kill].)
2478 This is the primitive for programs to kill text (as opposed to deleting it).
2479 Supply two arguments, character numbers indicating the stretch of text
2480 to be killed.
2481 Any command that calls this function is a \"kill command\".
2482 If the previous command was also a kill command,
2483 the text killed this time appends to the text killed last time
2484 to make one entry in the kill ring.
2485 Patched to remove the most recent completion."
2486 (interactive "r")
2487 (cond ((eq last-command 'complete)
2488 (delete-region (point) cmpl-last-insert-location)
2489 (insert cmpl-original-string)
2490 (setq completion-to-accept nil)
2491 (cmpl-statistics-block
2492 (record-complete-failed)))
2494 (kill-region beg end))))
2496 (global-set-key "\C-w" 'completion-kill-region)
2498 ;;;-----------------------------------------------
2499 ;;; Patches to self-insert-command.
2500 ;;;-----------------------------------------------
2502 ;;; Need 2 versions: generic separator chars. and space (to get auto fill
2503 ;;; to work)
2505 ;;; All common separators (eg. space "(" ")" """) characters go through a
2506 ;;; function to add new words to the list of words to complete from:
2507 ;;; COMPLETION-SEPARATOR-SELF-INSERT-COMMAND (arg).
2508 ;;; If the character before this was an alpha-numeric then this adds the
2509 ;;; symbol before point to the completion list (using ADD-COMPLETION).
2511 (defun completion-separator-self-insert-command (arg)
2512 (interactive "p")
2513 (use-completion-before-separator)
2514 (self-insert-command arg)
2517 (defun completion-separator-self-insert-autofilling (arg)
2518 (interactive "p")
2519 (use-completion-before-separator)
2520 (self-insert-command arg)
2521 (and (> (current-column) fill-column)
2522 auto-fill-function
2523 (funcall auto-fill-function))
2526 ;;;-----------------------------------------------
2527 ;;; Wrapping Macro
2528 ;;;-----------------------------------------------
2530 ;;; Note that because of the way byte compiling works, none of
2531 ;;; the functions defined with this macro get byte compiled.
2533 (defmacro def-completion-wrapper (function-name type &optional new-name)
2534 "Add a call to update the completion database before function execution.
2535 TYPE is the type of the wrapper to be added. Can be :before or :under."
2536 (cond ((eq type ':separator)
2537 (list 'put (list 'quote function-name) ''completion-function
2538 ''use-completion-before-separator))
2539 ((eq type ':before)
2540 (list 'put (list 'quote function-name) ''completion-function
2541 ''use-completion-before-point))
2542 ((eq type ':backward-under)
2543 (list 'put (list 'quote function-name) ''completion-function
2544 ''use-completion-backward-under))
2545 ((eq type ':backward)
2546 (list 'put (list 'quote function-name) ''completion-function
2547 ''use-completion-backward))
2548 ((eq type ':under)
2549 (list 'put (list 'quote function-name) ''completion-function
2550 ''use-completion-under-point))
2551 ((eq type ':under-or-before)
2552 (list 'put (list 'quote function-name) ''completion-function
2553 ''use-completion-under-or-before-point))
2554 ((eq type ':minibuffer-separator)
2555 (list 'put (list 'quote function-name) ''completion-function
2556 ''use-completion-minibuffer-separator))))
2558 (defun use-completion-minibuffer-separator ()
2559 (let ((cmpl-syntax-table cmpl-standard-syntax-table))
2560 (use-completion-before-separator)))
2562 (defun use-completion-backward-under ()
2563 (use-completion-under-point)
2564 (if (eq last-command 'complete)
2565 ;; probably a failed completion if you have to back up
2566 (cmpl-statistics-block (record-complete-failed))))
2568 (defun use-completion-backward ()
2569 (if (eq last-command 'complete)
2570 ;; probably a failed completion if you have to back up
2571 (cmpl-statistics-block (record-complete-failed))))
2573 (defun completion-before-command ()
2574 (funcall (or (get this-command 'completion-function)
2575 'use-completion-under-or-before-point)))
2576 (add-hook 'before-command-hook 'completion-before-command)
2579 ;;;---------------------------------------------------------------------------
2580 ;;; Patches to standard keymaps insert completions
2581 ;;;---------------------------------------------------------------------------
2583 ;;;-----------------------------------------------
2584 ;;; Separators
2585 ;;;-----------------------------------------------
2586 ;;; We've used the completion syntax table given as a guide.
2588 ;;; Global separator chars.
2589 ;;; We left out <tab> because there are too many special cases for it. Also,
2590 ;;; in normal coding it's rarely typed after a word.
2591 (global-set-key " " 'completion-separator-self-insert-autofilling)
2592 (global-set-key "!" 'completion-separator-self-insert-command)
2593 (global-set-key "%" 'completion-separator-self-insert-command)
2594 (global-set-key "^" 'completion-separator-self-insert-command)
2595 (global-set-key "&" 'completion-separator-self-insert-command)
2596 (global-set-key "(" 'completion-separator-self-insert-command)
2597 (global-set-key ")" 'completion-separator-self-insert-command)
2598 (global-set-key "=" 'completion-separator-self-insert-command)
2599 (global-set-key "`" 'completion-separator-self-insert-command)
2600 (global-set-key "|" 'completion-separator-self-insert-command)
2601 (global-set-key "{" 'completion-separator-self-insert-command)
2602 (global-set-key "}" 'completion-separator-self-insert-command)
2603 (global-set-key "[" 'completion-separator-self-insert-command)
2604 (global-set-key "]" 'completion-separator-self-insert-command)
2605 (global-set-key ";" 'completion-separator-self-insert-command)
2606 (global-set-key "\"" 'completion-separator-self-insert-command)
2607 (global-set-key "'" 'completion-separator-self-insert-command)
2608 (global-set-key "#" 'completion-separator-self-insert-command)
2609 (global-set-key "," 'completion-separator-self-insert-command)
2610 (global-set-key "?" 'completion-separator-self-insert-command)
2612 ;;; We include period and colon even though they are symbol chars because :
2613 ;;; - in text we want to pick up the last word in a sentence.
2614 ;;; - in C pointer refs. we want to pick up the first symbol
2615 ;;; - it won't make a difference for lisp mode (package names are short)
2616 (global-set-key "." 'completion-separator-self-insert-command)
2617 (global-set-key ":" 'completion-separator-self-insert-command)
2619 ;;; Lisp Mode diffs
2620 (define-key lisp-mode-map "!" 'self-insert-command)
2621 (define-key lisp-mode-map "&" 'self-insert-command)
2622 (define-key lisp-mode-map "%" 'self-insert-command)
2623 (define-key lisp-mode-map "?" 'self-insert-command)
2624 (define-key lisp-mode-map "=" 'self-insert-command)
2625 (define-key lisp-mode-map "^" 'self-insert-command)
2627 ;;; C mode diffs.
2628 (def-completion-wrapper electric-c-semi :separator)
2629 (define-key c-mode-map "+" 'completion-separator-self-insert-command)
2630 (define-key c-mode-map "*" 'completion-separator-self-insert-command)
2631 (define-key c-mode-map "/" 'completion-separator-self-insert-command)
2633 ;;; FORTRAN mode diffs. (these are defined when fortran is called)
2634 (defun completion-setup-fortran-mode ()
2635 (define-key fortran-mode-map "+" 'completion-separator-self-insert-command)
2636 (define-key fortran-mode-map "-" 'completion-separator-self-insert-command)
2637 (define-key fortran-mode-map "*" 'completion-separator-self-insert-command)
2638 (define-key fortran-mode-map "/" 'completion-separator-self-insert-command)
2641 ;;;-----------------------------------------------
2642 ;;; End of line chars.
2643 ;;;-----------------------------------------------
2644 (def-completion-wrapper newline :separator)
2645 (def-completion-wrapper newline-and-indent :separator)
2646 (def-completion-wrapper comint-send-input :separator)
2647 (def-completion-wrapper exit-minibuffer :minibuffer-separator)
2648 (def-completion-wrapper eval-print-last-sexp :separator)
2649 (def-completion-wrapper eval-last-sexp :separator)
2650 ;;(def-completion-wrapper minibuffer-complete-and-exit :minibuffer)
2652 ;;;-----------------------------------------------
2653 ;;; Cursor movement
2654 ;;;-----------------------------------------------
2656 (def-completion-wrapper next-line :under-or-before)
2657 (def-completion-wrapper previous-line :under-or-before)
2658 (def-completion-wrapper beginning-of-buffer :under-or-before)
2659 (def-completion-wrapper end-of-buffer :under-or-before)
2660 (def-completion-wrapper beginning-of-line :under-or-before)
2661 (def-completion-wrapper end-of-line :under-or-before)
2662 (def-completion-wrapper forward-char :under-or-before)
2663 (def-completion-wrapper forward-word :under-or-before)
2664 (def-completion-wrapper forward-sexp :under-or-before)
2665 (def-completion-wrapper backward-char :backward-under)
2666 (def-completion-wrapper backward-word :backward-under)
2667 (def-completion-wrapper backward-sexp :backward-under)
2669 (def-completion-wrapper delete-backward-char :backward)
2670 (def-completion-wrapper delete-backward-char-untabify :backward)
2672 ;;; Tests --
2673 ;;; foobarbiz
2674 ;;; foobar
2675 ;;; fooquux
2676 ;;; fooper
2678 (cmpl-statistics-block
2679 (record-completion-file-loaded))
2681 ;;; completion.el ends here