1 ;;; dabbrev.el --- dynamic abbreviation package
2 ;; Copyright (C) 1985, 1986, 1992, 1994 Free Software Foundation, Inc.
4 ;; Author: Don Morrison
5 ;; Maintainer: Lars Lindberg <Lars.Lindberg@sypro.cap.se>
6 ;; Created: 16 Mars 1992
7 ;; Lindberg's last update version: 5.2
8 ;; Keywords: abbrev expand completion
10 ;; This program is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2 of the License, or
13 ;; (at your option) any later version.
15 ;; This program is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with this program; if not, write to the Free Software
22 ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 ;; The purpose with this package is to let you write just a few
27 ;; characters of words you've written earlier to be able to expand
30 ;; To expand a word, just put the point right after the word and press
31 ;; M-/ (dabbrev-expand) or M-C-/ (dabbrev-completion).
33 ;; There are powerful things in this package that aren't turned on by
34 ;; default. I recommend you to do the following.
36 ;; Put the following 2 lines in your .emacs file:
37 ;; (setq dabbrev-always-check-other-buffers t)
38 ;; (setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_")
40 ;; Dabbrev will now search in all buffers with the same major mode for
41 ;; your expansions. It will also search for complete symbols, the old
42 ;; dabbrev package only looked half-heartedly for symbols.
44 ;; Check out the customizable variables below to learn about all the
45 ;; features of this package.
47 ;;; Hints and tips for major modes writers:
49 ;; Recommended values C/Lisp etc text
50 ;; dabbrev-case-fold-search nil t
51 ;; dabbrev-case-replace nil t
53 ;; Set the variables you want special for your mode like this:
54 ;; (set (make-local-variable 'dabbrev-case-replace) nil)
55 ;; Then you don't interfer with other modes.
57 ;; If your mode handles buffers that refers to other buffers
58 ;; (i.e. compilation-mode, gud-mode), then try to set
59 ;; `dabbrev-select-buffers-function' or `dabbrev-friend-buffer-function'
60 ;; to a function that point out those buffers.
62 ;; Same goes for major-modes that are connected to other modes. There
63 ;; are for instance a number of mail-modes. One for reading, one for
64 ;; creating a new mail etc. Maybe those should be connected.
66 ;; Example for GNUS (when we write a reply, we want dabbrev to look in
67 ;; the article for expansion):
68 ;; (set (make-local-variable 'dabbrev-friend-buffer-function)
71 ;; (set-buffer buffer)
72 ;; (memq major-mode '(news-reply-mode gnus-article-mode)))))
75 ;; Known bugs and limitations.
76 ;; - Possible to do several levels of `dabbrev-completion' in the
78 ;; - dabbrev-completion doesn't handle resetting the globals variables
79 ;; right. It resets them after finding the abbrev.
81 ;; Future enhancements
82 ;; - Check the tags-files? Like tags-complete?
83 ;; - Add the possibility of searching both forward and backward to
84 ;; the nearest expansion.
85 ;; - Check the kill-ring when everything else fails. (Maybe something
86 ;; for hippie-expand?). [Bng] <boris@cs.rochester.edu>
89 ;; [hymie] Hyman Rosen <marks!hymie@jyacc.jyacc.com>
90 ;; [burgett] Steve Burgett <burgett@bizet.eecs.berkeley.edu>
91 ;; [jules] Julian Gosnell <jules@x.co.uk>
92 ;; [kifer] Michael Kifer <kifer@sbcs.sunysb.edu>
93 ;; [ake] Ake Stenhoff <extaksf@aom.ericsson.se>
94 ;; [alon] Alon Albert <al%imercury@uunet.uu.net>
95 ;; [tromey] Tom Tromey <tromey@busco.lanl.gov>
96 ;; [Rolf] Rolf Schreiber <rolf@mathematik.uni-stuttgart.de>
97 ;; [Petri] Petri Raitio <per@tekla.fi>
98 ;; [ejb] Jay Berkenbilt <ejb@ERA.COM>
99 ;; [hawley] Bob Hawley <rth1@quartet.mt.att.com>
100 ;; ... and to all the people who have participated in the beta tests.
104 ;;;----------------------------------------------------------------
105 ;;;----------------------------------------------------------------
106 ;;; Customization variables
107 ;;;----------------------------------------------------------------
108 ;;;----------------------------------------------------------------
109 (defvar dabbrev-backward-only nil
110 "*If non-nil, `dabbrev-expand' only looks backwards.")
112 (defvar dabbrev-limit nil
113 "*Limits region searched by `dabbrev-expand' to this many chars away.")
115 (defvar dabbrev-abbrev-skip-leading-regexp nil
116 "*Regexp for skipping leading characters of an abbreviation.
118 Example: Set this to \"\\\\$\" for programming languages
119 in which variable names may appear with or without a leading `$'.
120 (For example, in Makefiles.)
122 Set this to nil if no characters should be skipped.")
124 ;; I recommend that you set this to nil.
125 (defvar dabbrev-case-fold-search
'case-fold-search
126 "*Non-nil if dabbrev searches should ignore case.
127 A value of nil means case is significant.
129 The value of this variable is an expression; it is evaluated
130 and the resulting value determines the decision.
131 For example: setting this to `case-fold-search' means evaluate that
132 variable to see whether its value is nil.")
134 (defvar dabbrev-upcase-means-case-search nil
135 "*The significance of an uppercase character in an abbreviation.
136 nil means case fold search, non-nil means case sensitive search.
138 This variable has an effect only when the value of
139 `dabbrev-case-fold-search' evaluates to t.")
141 ;; I recommend that you set this to nil.
142 (defvar dabbrev-case-replace
'case-replace
143 "*Non-nil means dabbrev should preserve case when expanding the abbreviation.
144 The value of this variable is an expression; it is evaluated
145 and the resulting value determines the decision.
146 For example, setting this to `case-replace' means evaluate that
147 variable to see if its value is t or nil.
149 This variable has an effect only when the value of
150 `dabbrev-case-fold-search' evaluates to t.")
152 (defvar dabbrev-abbrev-char-regexp
"\\sw\\|\\s_"
153 "*Regexp to recognize a character in an abbreviation or expansion.
154 This regexp will be surrounded with \\\\( ... \\\\) when actually used.
156 Set this variable to \"\\\\sw\" if you want ordinary words or
157 \"\\\\sw\\\\|\\\\s_\" if you want symbols.
159 You can also set it to nil if you want old-style dabbrev searching
160 \(the abbreviation is from point to previous word-start, the
161 search is for symbols).
163 For instance, if you are programming in Lisp, `yes-or-no-p' is a symbol,
164 while `yes', `or', `no' and `p' are considered words. If you set this
165 variable to nil, then expanding `yes-or-no-' looks for a symbol
166 starting with or containing `no-'. If you set this variable to
167 \"\\\\sw\\\\|\\\\s_\", that expansion looks for a symbol starting with
168 `yes-or-no-'. Finally, if you set this variable to \"\\\\sw\", then
169 expanding `yes-or-no-' signals an error because `-' is not part of a word;
170 but expanding `yes-or-no' looks for a word starting with `no'.
172 The recommended value is \"\\\\sw\\\\|\\\\s_\".")
174 (defvar dabbrev-check-rest-of-buffers t
175 "*Non-nil means dabbrev package should search in all buffers.
176 It searches the buffers pointed out by `dabbrev-select-buffers-function'
177 first; afterward it looks in the rest of the buffers.")
180 ;; I recommend that you set this to t.
181 (defvar dabbrev-always-check-other-buffers nil
182 "*Should \\[dabbrev-expand] look in other buffers?\
183 nil = Don't look in other buffers.\n\
184 t = Look in other buffers.\n\
185 Value other than nil and t = ask the user if he want's to look in
188 The recommended value is t.")
190 ;; I guess setting this to a function that selects all C- or C++-
191 ;; mode buffers would be a good choice for a debugging buffer,
192 ;; when debugging C- or C++-code.
193 (defvar dabbrev-select-buffers-function
'dabbrev--select-buffers
194 "A function that selects buffers that should be searched by dabbrev.
196 The function should take no arguments and return a list of buffers to
197 search for expansions. Have a look at `dabbrev--select-buffers' for
200 A mode setting this variable should make it buffer local.")
202 (defvar dabbrev-friend-buffer-function
'dabbrev--same-major-mode-p
203 "*A function to check if OTHER-BUFFER should be searched by dabbrev.
205 The function should take one argument, OTHER-BUFFER, and return
206 non-nil if that buffer should be searched. Have a look at
207 `dabbrev--same-major-mode-p' for an example.
209 The value of `dabbrev-friend-buffer-function' has an effect only if
210 the value of `dabbrev-select-buffers-function' uses it. The function
211 `dabbrev--select-buffers' is one function you can use here.
213 A mode setting this variable should make it buffer local.")
215 (defvar dabbrev-search-these-buffers-only nil
216 "If non-nil, a list of buffers which dabbrev should search.
217 If this variable is non-nil, dabbrev will only look in these buffers.
218 It will not even look in the current buffer if it is not a member of
221 ;;;----------------------------------------------------------------
222 ;;;----------------------------------------------------------------
223 ;;; Internal variables
224 ;;;----------------------------------------------------------------
225 ;;;----------------------------------------------------------------
227 ;; Last obarray of completions in `dabbrev-completion'
228 (defvar dabbrev--last-obarray nil
)
230 ;; Table of expansions seen so far
231 (defvar dabbrev--last-table nil
)
233 ;; Last string we tried to expand.
234 (defvar dabbrev--last-abbreviation nil
)
236 ;; Location last abbreviation began
237 (defvar dabbrev--last-abbrev-location nil
)
239 ;; Direction of last dabbrevs search
240 (defvar dabbrev--last-direction
0)
242 ;; Last expansion of an abbreviation.
243 (defvar dabbrev--last-expansion nil
)
245 ;; Location the last expansion was found.
246 (defvar dabbrev--last-expansion-location nil
)
248 ;; The list of remaining buffers with the same mode as current buffer.
249 (defvar dabbrev--friend-buffer-list nil
)
251 ;; The buffer we looked in last.
252 (defvar dabbrev--last-buffer nil
)
254 ;; The buffer we found the expansion last time.
255 (defvar dabbrev--last-buffer-found nil
)
257 ;; The buffer we last did a completion in.
258 (defvar dabbrev--last-completion-buffer nil
)
260 ;; Same as dabbrev-always-check-other-buffers, but is set for every expand.
261 (defvar dabbrev--check-other-buffers dabbrev-always-check-other-buffers
)
263 ;; The regexp for recognizing a character in an abbreviation.
264 (defvar dabbrev--abbrev-char-regexp nil
)
266 ;;;----------------------------------------------------------------
267 ;;;----------------------------------------------------------------
269 ;;;----------------------------------------------------------------
270 ;;;----------------------------------------------------------------
272 ;;; Get the buffer that mini-buffer was activated from
273 (defsubst dabbrev--minibuffer-origin
()
274 (car (cdr (buffer-list))))
276 ;; Make a list of some of the elements of LIST.
277 ;; Check each element of LIST, storing it temporarily in the
278 ;; variable ELEMENT, and include it in the result
279 ;; if CONDITION evaluates non-nil.
280 (defmacro dabbrev-filter-elements
(element list condition
)
281 (` (let (dabbrev-result dabbrev-tail
(, element
))
282 (setq dabbrev-tail
(, list
))
284 (setq (, element
) (car dabbrev-tail
))
286 (setq dabbrev-result
(cons (, element
) dabbrev-result
)))
287 (setq dabbrev-tail
(cdr dabbrev-tail
)))
288 (nreverse dabbrev-result
))))
290 ;;;----------------------------------------------------------------
291 ;;;----------------------------------------------------------------
292 ;;; Exported functions
293 ;;;----------------------------------------------------------------
294 ;;;----------------------------------------------------------------
297 (define-key esc-map
"/" 'dabbrev-expand
)
298 ;;;??? Do we want this?
300 (define-key esc-map
[?\C-
/] 'dabbrev-completion
)
303 (defun dabbrev-completion (&optional arg
)
304 "Completion on current word.
305 Like \\[dabbrev-expand] but finds all expansions in the current buffer
306 and presents suggestions for completion.
308 With a prefix argument, it searches all buffers accepted by the
309 function pointed out by `dabbrev-friend-buffer-function' to find the
312 If the prefix argument is 16 (which comes from C-u C-u),
313 then it searches *all* buffers.
315 With no prefix argument, it reuses an old completion list
316 if there is a suitable one already."
319 (let* ((dabbrev-always-check-other-buffers (and arg t
))
320 (dabbrev-check-rest-of-buffers
321 (and arg
(= (prefix-numeric-value arg
) 16)))
322 (abbrev (dabbrev--abbrev-at-point))
323 (ignore-case-p (and (eval dabbrev-case-fold-search
)
324 (or (not dabbrev-upcase-means-case-search
)
325 (string= abbrev
(downcase abbrev
)))))
326 (my-obarray dabbrev--last-obarray
)
331 (or (eq dabbrev--last-completion-buffer
(current-buffer))
332 (and (window-minibuffer-p (selected-window))
333 (eq dabbrev--last-completion-buffer
334 (dabbrev--minibuffer-origin))))
335 dabbrev--last-abbreviation
336 (>= (length abbrev
) (length dabbrev--last-abbreviation
))
337 (string= dabbrev--last-abbreviation
339 (length dabbrev--last-abbreviation
)))
340 (setq init
(try-completion abbrev my-obarray
)))
341 ;; We can reuse the existing completion list.
343 ;;--------------------------------
344 ;; New abbreviation to expand.
345 ;;--------------------------------
346 (dabbrev--reset-global-variables)
347 (setq dabbrev--last-abbreviation abbrev
)
348 ;; Find all expansion
349 (let ((completion-list
350 (dabbrev--find-all-expansions abbrev ignore-case-p
)))
351 ;; Make an obarray with all expansions
352 (setq my-obarray
(make-vector (length completion-list
) 0))
353 (or (> (length my-obarray
) 0)
354 (error "No dynamic expansion for \"%s\" found%s"
356 (if dabbrev--check-other-buffers
"" " in this-buffer")))
358 ((or (not ignore-case-p
)
359 (not dabbrev-case-replace
))
360 (mapc (function (lambda (string)
361 (intern string my-obarray
)))
363 ((string= abbrev
(upcase abbrev
))
364 (mapc (function (lambda (string)
365 (intern (upcase string
) my-obarray
)))
367 ((string= (substring abbrev
0 1)
368 (upcase (substring abbrev
0 1)))
369 (mapc (function (lambda (string)
370 (intern (dabbrev--capitalize string
) my-obarray
)))
373 (mapc (function (lambda (string)
374 (intern (downcase string
) my-obarray
)))
376 (setq dabbrev--last-obarray my-obarray
)
377 (setq dabbrev--last-completion-buffer
(current-buffer))
378 ;; Find the longest common string.
379 (setq init
(try-completion abbrev my-obarray
)))))
380 ;;--------------------------------
381 ;; Let the user choose between the expansions
382 ;;--------------------------------
386 ;; * Replace string fragment with matched common substring completion.
387 ((and (not (string-equal init
""))
388 (not (string-equal (downcase init
) (downcase abbrev
))))
389 (if (> (length (all-completions init my-obarray
)) 1)
390 (message "Repeat `%s' to see all completions"
391 (key-description (this-command-keys)))
392 (message "The only possible completion"))
393 (dabbrev--substitute-expansion nil abbrev init
))
395 ;; * String is a common substring completion already. Make list.
396 (message "Making completion list...")
397 (with-output-to-temp-buffer " *Completions*"
398 (display-completion-list (all-completions init my-obarray
)))
399 (message "Making completion list...done")))
400 (and (window-minibuffer-p (selected-window))
404 (defun dabbrev-expand (arg)
405 "Expand previous word \"dynamically\".
407 Expands to the most recent, preceding word for which this is a prefix.
408 If no suitable preceding word is found, words following point are
409 considered. If still no suitable word is found, then look in the
410 buffers accepted by the function pointed out by variable
411 `dabbrev-friend-buffer-function'.
413 A positive prefix argument, N, says to take the Nth backward *distinct*
414 possibility. A negative argument says search forward.
416 If the cursor has not moved from the end of the previous expansion and
417 no argument is given, replace the previously-made expansion
418 with the next possible expansion not yet tried.
420 The variable `dabbrev-backward-only' may be used to limit the
421 direction of search to backward if set non-nil.
424 To make it more powerful, make sure that
425 `dabbrev-always-check-other-buffers' is set to t.
427 See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]."
429 (let (abbrev expansion old direction
)
430 ;; abbrev -- the abbrev to expand
431 ;; expansion -- the expansion found (eventually) or nil until then
432 ;; old -- the text currently in the buffer
433 ;; (the abbrev, or the previously-made expansion)
436 dabbrev--last-abbrev-location
437 (or (eq last-command this-command
)
438 (and (window-minibuffer-p (selected-window))
439 (= dabbrev--last-abbrev-location
441 ;; Find a different expansion for the same abbrev as last time.
443 (setq abbrev dabbrev--last-abbreviation
)
444 (setq old dabbrev--last-expansion
)
445 (setq direction dabbrev--last-direction
))
446 ;; We have a different abbrev to expand.
447 (dabbrev--reset-global-variables)
448 (setq direction
(if (null arg
)
449 (if dabbrev-backward-only
1 0)
450 (prefix-numeric-value arg
)))
451 (setq abbrev
(dabbrev--abbrev-at-point))
454 ;;--------------------------------
455 ;; Find the expansion
456 ;;--------------------------------
458 (dabbrev--find-expansion abbrev direction
459 (and (eval dabbrev-case-fold-search
)
460 (or (not dabbrev-upcase-means-case-search
)
461 (string= abbrev
(downcase abbrev
)))))))
464 (dabbrev--reset-global-variables)
467 (search-backward (substring old
(length abbrev
)))
468 (delete-region (match-beginning 0) (match-end 0))))
469 (error "No%s dynamic expansion for `%s' found"
470 (if old
" further" "") abbrev
))
472 (if (not (eq dabbrev--last-buffer dabbrev--last-buffer-found
))
474 (message "Expansion found in '%s'"
475 (buffer-name dabbrev--last-buffer
))
476 (setq dabbrev--last-buffer-found dabbrev--last-buffer
))
478 ;; Success: stick it in and return.
479 (dabbrev--substitute-expansion old abbrev expansion
)
480 ;; Save state for re-expand.
481 (setq dabbrev--last-expansion expansion
)
482 (setq dabbrev--last-abbreviation abbrev
)
483 (setq dabbrev--last-abbrev-location
(point-marker))))))
485 ;;;----------------------------------------------------------------
486 ;;;----------------------------------------------------------------
488 ;;;----------------------------------------------------------------
489 ;;;----------------------------------------------------------------
491 (defun dabbrev--capitalize (string)
492 ;; Capitalize STRING (See capitalize-word)
493 (let ((new-string ""))
495 (while (string-match "\\w+" string
)
496 (let* ((mb (match-beginning 0))
498 (ms (substring string mb me
)))
501 (substring string
0 mb
)
502 (upcase (substring ms
0 1))
503 (downcase (substring ms
1))))
504 (setq string
(substring string me
)))))
507 ;;; Checks if OTHER-BUFFER has the same major mode as current buffer.
508 (defun dabbrev--same-major-mode-p (other-buffer)
511 (set-buffer other-buffer
)
514 ;;; Back over all abbrev type characters and then moves forward over
515 ;;; all skip characters.
516 (defun dabbrev--goto-start-of-abbrev ()
517 ;; Move backwards over abbrev chars
522 (while (and (looking-at dabbrev--abbrev-char-regexp
)
525 (or (looking-at dabbrev--abbrev-char-regexp
)
527 (and dabbrev-abbrev-skip-leading-regexp
528 (while (looking-at dabbrev-abbrev-skip-leading-regexp
)
531 ;;; Extract the symbol at point to serve as abbreviation.
532 (defun dabbrev--abbrev-at-point ()
539 (not (looking-at (concat "\\("
540 (or dabbrev-abbrev-char-regexp
543 (error "Not positioned immediately after an abbreviation"))))
544 ;; Return abbrev at point
546 (setq dabbrev--last-abbrev-location
(point))
547 (buffer-substring (point)
548 (progn (dabbrev--goto-start-of-abbrev)
551 ;;; Initializes all global variables
552 (defun dabbrev--reset-global-variables ()
553 ;; dabbrev--last-obarray and dabbrev--last-completion-buffer
554 ;; must not be reset here.
555 (setq dabbrev--last-table nil
556 dabbrev--last-abbreviation nil
557 dabbrev--last-abbrev-location nil
558 dabbrev--last-direction nil
559 dabbrev--last-expansion nil
560 dabbrev--last-expansion-location nil
561 dabbrev--friend-buffer-list nil
562 dabbrev--last-buffer nil
563 dabbrev--last-buffer-found nil
564 dabbrev--abbrev-char-regexp
(or dabbrev-abbrev-char-regexp
566 dabbrev--check-other-buffers dabbrev-always-check-other-buffers
))
568 ;;; Find all buffers that are considered "friends" according to the
569 ;;; function pointed out by dabbrev-friend-buffer-function.
570 (defun dabbrev--select-buffers ()
572 (and (window-minibuffer-p (selected-window))
573 (set-buffer (dabbrev--minibuffer-origin)))
574 (let ((orig-buffer (current-buffer)))
575 (dabbrev-filter-elements
577 (and (not (eq orig-buffer buffer
))
578 (boundp 'dabbrev-friend-buffer-function
)
579 (funcall dabbrev-friend-buffer-function buffer
))))))
581 ;;; Search for ABBREV, N times, normally looking forward,
582 ;;; but looking in reverse instead if REVERSE is non-nil.
583 (defun dabbrev--try-find (abbrev reverse n ignore-case
)
585 (let ((expansion nil
))
586 (and dabbrev--last-expansion-location
587 (goto-char dabbrev--last-expansion-location
))
588 (let ((case-fold-search ignore-case
)
590 (while (and (> count
0)
591 (setq expansion
(dabbrev--search abbrev
594 (setq count
(1- count
))))
596 (setq dabbrev--last-expansion-location
(point)))
599 ;;; Find all expansions of ABBREV
600 (defun dabbrev--find-all-expansions (abbrev ignore-case
)
601 (let ((all-expansions nil
)
604 (goto-char (point-min))
605 (while (setq expansion
(dabbrev--find-expansion abbrev -
1 ignore-case
))
606 (push expansion all-expansions
)))
609 (defun dabbrev--scanning-message ()
610 (message "Scanning `%s'" (buffer-name (current-buffer))))
612 ;;; Find one occasion of ABBREV.
613 ;;; DIRECTION > 0 means look that many times backwards.
614 ;;; DIRECTION < 0 means look that many times forward.
615 ;;; DIRECTION = 0 means try both backward and forward.
616 ;;; IGNORE-CASE non-nil means ignore case when searching.
617 (defun dabbrev--find-expansion (abbrev direction ignore-case
)
621 (dabbrev--last-buffer
622 (set-buffer dabbrev--last-buffer
)
623 (dabbrev--scanning-message))
624 ((and (not dabbrev-search-these-buffers-only
)
625 (window-minibuffer-p (selected-window)))
626 (set-buffer (dabbrev--minibuffer-origin))
627 ;; In the minibuffer-origin buffer we will only search from
629 (goto-char (point-min))
631 (dabbrev--scanning-message)))
633 ;; ------------------------------------------
635 ;; ------------------------------------------
636 ((and (not dabbrev-search-these-buffers-only
)
638 (setq dabbrev--last-direction
(min 1 direction
))
639 (setq expansion
(dabbrev--try-find abbrev t
643 ;; ------------------------------------------
645 ;; ------------------------------------------
646 ((and (or (not dabbrev-search-these-buffers-only
)
647 dabbrev--last-buffer
)
649 (setq dabbrev--last-direction -
1)
650 (setq expansion
(dabbrev--try-find abbrev nil
651 (max 1 (- direction
))
654 ;; ------------------------------------------
655 ;; Look in other buffers.
656 ;; Start at (point-min) and look forward.
657 ;; ------------------------------------------
659 (setq dabbrev--last-direction -
1)
660 ;; Make sure that we should check other buffers
661 (or dabbrev--friend-buffer-list
663 (setq dabbrev--friend-buffer-list
664 (mapcar (function get-buffer
)
665 dabbrev-search-these-buffers-only
))
666 (not dabbrev--check-other-buffers
)
667 (not (or (eq dabbrev--check-other-buffers t
)
669 (setq dabbrev--check-other-buffers
670 (y-or-n-p "Scan other buffers also? ")))))
671 (let* (friend-buffer-list non-friend-buffer-list
)
672 (setq dabbrev--friend-buffer-list
673 (funcall dabbrev-select-buffers-function
))
674 (if dabbrev-check-rest-of-buffers
675 (setq non-friend-buffer-list
677 (dabbrev-filter-elements
679 (not (memq buffer dabbrev--friend-buffer-list
))))
680 dabbrev--friend-buffer-list
681 (append dabbrev--friend-buffer-list
682 non-friend-buffer-list
)))))
683 ;; Walk through the buffers
684 (while (and (not expansion
) dabbrev--friend-buffer-list
)
685 (setq dabbrev--last-buffer
686 (car dabbrev--friend-buffer-list
))
687 (setq dabbrev--friend-buffer-list
688 (cdr dabbrev--friend-buffer-list
))
689 (set-buffer dabbrev--last-buffer
)
690 (dabbrev--scanning-message)
691 (setq dabbrev--last-expansion-location
(point-min))
692 (setq expansion
(dabbrev--try-find abbrev nil
1 ignore-case
)))
695 (defun dabbrev--safe-replace-match (string &optional fixedcase literal
)
696 (if (eq major-mode
'picture-mode
)
697 (picture-replace-match string fixedcase literal
)
698 (replace-match string fixedcase literal
)))
700 ;;;----------------------------------------------------------------
701 ;;; Substitute the current string in buffer with the expansion
702 ;;; OLD is nil or the last expansion substring.
703 ;;; ABBREV is the abbreviation we are working with.
704 ;;; EXPANSION is the expansion substring.
705 (defun dabbrev--substitute-expansion (old abbrev expansion
)
707 (let ((use-case-replace (and (eval dabbrev-case-fold-search
)
708 (or (not dabbrev-upcase-means-case-search
)
709 (string= abbrev
(downcase abbrev
)))
710 (eval dabbrev-case-replace
))))
711 (and nil use-case-replace
712 (setq old
(concat abbrev
(or old
"")))
713 (setq expansion
(concat abbrev expansion
)))
716 (search-backward old
))
717 ;;(store-match-data (list (point-marker) (point-marker)))
718 (search-backward abbrev
))
719 ;; Make case of replacement conform to case of abbreviation
720 ;; provided (1) that kind of thing is enabled in this buffer
721 ;; and (2) the replacement itself is all lower case.
722 (dabbrev--safe-replace-match expansion
723 (not use-case-replace
)
727 ;;;----------------------------------------------------------------
728 ;;; Search function used by dabbrevs library.
730 ;;; ABBREV is string to find as prefix of word. Second arg, REVERSE,
731 ;;; is t for reverse search, nil for forward. Variable dabbrev-limit
732 ;;; controls the maximum search region size. Third argment IGNORE-CASE
733 ;;; non-nil means treat case as insignificant while looking for a match
734 ;;; and when comparing with previous matches. Also if that's non-nil
735 ;;; and the match is found at the beginning of a sentence and is in
736 ;;; lower case except for the initial then it is converted to all lower
739 ;;; Table of expansions already seen is examined in buffer
740 ;;; `dabbrev--last-table' so that only distinct possibilities are found
741 ;;; by dabbrev-re-expand.
743 ;;; Value is the expansion, or nil if not found.
745 (defun dabbrev--search (abbrev reverse ignore-case
)
747 (let ((pattern1 (concat (regexp-quote abbrev
)
748 "\\(" dabbrev--abbrev-char-regexp
"\\)"))
749 (pattern2 (concat (regexp-quote abbrev
)
750 "\\(\\(" dabbrev--abbrev-char-regexp
"\\)+\\)"))
755 (narrow-to-region dabbrev--last-expansion-location
757 (if reverse
(- dabbrev-limit
) dabbrev-limit
))))
758 ;;--------------------------------
759 ;; Look for a distinct expansion, using dabbrev--last-table.
760 ;;--------------------------------
761 (while (and (not found-string
)
763 (re-search-backward pattern1 nil t
)
764 (re-search-forward pattern1 nil t
)))
767 (goto-char (match-beginning 0))
768 (dabbrev--goto-start-of-abbrev)
769 (/= (point) (match-beginning 0)))
770 ;; Prefix of found abbreviation not OK
773 (goto-char (match-beginning 0))
774 (re-search-forward pattern2
)
776 (buffer-substring (match-beginning 1) (match-end 1)))
777 (and ignore-case
(setq found-string
(downcase found-string
)))
778 ;; Throw away if found in table
779 (if (dabbrev-filter-elements
780 table-string dabbrev--last-table
781 (string= found-string table-string
))
782 (setq found-string nil
))))
784 (goto-char (match-beginning 0))
785 (goto-char (match-end 0))))
788 ;;--------------------------------
789 ;; Put in `dabbrev--last-table' and decide if we should return
790 ;; result or (downcase result)
791 ;;--------------------------------
792 (push found-string dabbrev--last-table
)
793 (let ((result (buffer-substring (match-beginning 0) (match-end 0))))
794 (if (and ignore-case
(eval dabbrev-case-replace
))
800 ;; dabbrev.el ends here