X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/f8b581fa239ace91c181a25d94a07c779afa617f..a2236dc611360edfb8f5f891b4e63d586793f38f:/lisp/dabbrev.el diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el index 430824de8e..11da3b68e7 100644 --- a/lisp/dabbrev.el +++ b/lisp/dabbrev.el @@ -1,25 +1,29 @@ ;;; dabbrev.el --- dynamic abbreviation package -;; Copyright (C) 1985, 1986, 1992, 1994 Free Software Foundation, Inc. + +;; Copyright (C) 1985, 86, 92, 94, 96, 1997 Free Software Foundation, Inc. ;; Author: Don Morrison ;; Maintainer: Lars Lindberg ;; Created: 16 Mars 1992 -;; Lindberg's last update version: 5.2 -;; Keywords: abbrev expand completion +;; Lindberg's last update version: 5.7 +;; Keywords: abbrev expand completion convenience + +;; This file is part of GNU Emacs. -;; This program is free software; you can redistribute it and/or modify +;; GNU Emacs is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. -;; + ;; You should have received a copy of the GNU General Public License -;; along with this program; if not, write to the Free Software -;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. ;;; Commentary: @@ -30,17 +34,6 @@ ;; To expand a word, just put the point right after the word and press ;; M-/ (dabbrev-expand) or M-C-/ (dabbrev-completion). ;; -;; There are powerful things in this package that aren't turned on by -;; default. I recommend you to do the following. -;; -;; Put the following 2 lines in your .emacs file: -;; (setq dabbrev-always-check-other-buffers t) -;; (setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_") -;; -;; Dabbrev will now search in all buffers with the same major mode for -;; your expansions. It will also search for complete symbols, the old -;; dabbrev package only looked half-heartedly for symbols. -;; ;; Check out the customizable variables below to learn about all the ;; features of this package. @@ -52,7 +45,7 @@ ;; ;; Set the variables you want special for your mode like this: ;; (set (make-local-variable 'dabbrev-case-replace) nil) -;; Then you don't interfer with other modes. +;; Then you don't interfere with other modes. ;; ;; If your mode handles buffers that refers to other buffers ;; (i.e. compilation-mode, gud-mode), then try to set @@ -85,7 +78,7 @@ ;; - Check the kill-ring when everything else fails. (Maybe something ;; for hippie-expand?). [Bng] -;;; Thanks goes to +;;; These people gave suggestions: ;; [hymie] Hyman Rosen ;; [burgett] Steve Burgett ;; [jules] Julian Gosnell @@ -95,113 +88,150 @@ ;; [tromey] Tom Tromey ;; [Rolf] Rolf Schreiber ;; [Petri] Petri Raitio -;; [ejb] Jay Berkenbilt +;; [ejb] Jay Berkenbilt ;; [hawley] Bob Hawley ;; ... and to all the people who have participated in the beta tests. ;;; Code: -;;;---------------------------------------------------------------- -;;;---------------------------------------------------------------- -;;; Customization variables -;;;---------------------------------------------------------------- -;;;---------------------------------------------------------------- -(defvar dabbrev-backward-only nil - "*If non-nil, `dabbrev-expand' only looks backwards.") +;;---------------------------------------------------------------- +;; Customization variables +;;---------------------------------------------------------------- + +(defgroup dabbrev nil + "Dynamic Abbreviations" + :tag "Dynamic Abbreviations" + :group 'abbrev + :group 'convenience) -(defvar dabbrev-limit nil - "*Limits region searched by `dabbrev-expand' to this many chars away.") +(defcustom dabbrev-backward-only nil + "*If non-nil, `dabbrev-expand' only looks backwards." + :type 'boolean + :group 'dabbrev) -(defvar dabbrev-abbrev-skip-leading-regexp nil +(defcustom dabbrev-limit nil + "*Limits region searched by `dabbrev-expand' to this many chars away." + :type '(choice (const :tag "off" nil) + integer) + :group 'dabbrev) + +(defcustom dabbrev-abbrev-skip-leading-regexp nil "*Regexp for skipping leading characters of an abbreviation. Example: Set this to \"\\\\$\" for programming languages in which variable names may appear with or without a leading `$'. -(For example, in Makefiles.) +\(For example, in Makefiles.\) -Set this to nil if no characters should be skipped.") +Set this to nil if no characters should be skipped." + :type '(choice regexp + (const :tag "off" nil)) + :group 'dabbrev) -;; I recommend that you set this to nil. -(defvar dabbrev-case-fold-search 'case-fold-search - "*Non-nil if dabbrev searches should ignore case. +(defcustom dabbrev-case-fold-search 'case-fold-search + "*Control whether dabbrev searches should ignore case. A value of nil means case is significant. - -The value of this variable is an expression; it is evaluated -and the resulting value determines the decision. -For example: setting this to `case-fold-search' means evaluate that -variable to see whether its value is nil.") - -(defvar dabbrev-upcase-means-case-search nil +A value of `case-fold-search' means case is significant + if `case-fold-search' is nil. +Any other non-nil version means case is not significant." + :type '(choice (const :tag "off" nil) + (const :tag "like search" case-fold-search) + (other :tag "on" t)) + :group 'dabbrev) + +(defcustom dabbrev-upcase-means-case-search nil "*The significance of an uppercase character in an abbreviation. nil means case fold search, non-nil means case sensitive search. This variable has an effect only when the value of -`dabbrev-case-fold-search' evaluates to t.") +`dabbrev-case-fold-search' says to ignore case." + :type 'boolean + :group 'dabbrev) -;; I recommend that you set this to nil. -(defvar dabbrev-case-replace 'case-replace - "*Non-nil means dabbrev should preserve case when expanding the abbreviation. -The value of this variable is an expression; it is evaluated -and the resulting value determines the decision. -For example, setting this to `case-replace' means evaluate that -variable to see if its value is t or nil. +(defcustom dabbrev-case-replace 'case-replace + "*Controls whether dabbrev preserves case when expanding the abbreviation. +A value of nil means preserve case. +A value of `case-replace' means preserve case if `case-replace' is nil. +Any other non-nil version means do not preserve case. This variable has an effect only when the value of -`dabbrev-case-fold-search' evaluates to t.") +`dabbrev-case-fold-search' specifies to ignore case." + :type '(choice (const :tag "off" nil) + (const :tag "like M-x query-replace" case-replace) + (other :tag "on" t)) + :group 'dabbrev) -(defvar dabbrev-abbrev-char-regexp "\\sw\\|\\s_" +(defcustom dabbrev-abbrev-char-regexp nil "*Regexp to recognize a character in an abbreviation or expansion. This regexp will be surrounded with \\\\( ... \\\\) when actually used. Set this variable to \"\\\\sw\" if you want ordinary words or -\"\\\\sw\\\\|\\\\s_\" if you want symbols. +\"\\\\sw\\\\|\\\\s_\" if you want symbols (including characters whose +syntax is \"symbol\" as well as those whose syntax is \"word\". -You can also set it to nil if you want old-style dabbrev searching -\(the abbreviation is from point to previous word-start, the -search is for symbols). +The value nil has a special meaning: the abbreviation is from point to +previous word-start, but the search is for symbols. For instance, if you are programming in Lisp, `yes-or-no-p' is a symbol, -while `yes', `or', `no' and `p' are considered words. If you set this -variable to nil, then expanding `yes-or-no-' looks for a symbol +while `yes', `or', `no' and `p' are considered words. If this +variable is nil, then expanding `yes-or-no-' looks for a symbol starting with or containing `no-'. If you set this variable to \"\\\\sw\\\\|\\\\s_\", that expansion looks for a symbol starting with `yes-or-no-'. Finally, if you set this variable to \"\\\\sw\", then expanding `yes-or-no-' signals an error because `-' is not part of a word; but expanding `yes-or-no' looks for a word starting with `no'. -The recommended value is \"\\\\sw\\\\|\\\\s_\".") +The recommended value is \"\\\\sw\\\\|\\\\s_\"." + :type '(choice (const nil) + regexp) + :group 'dabbrev) + +(defcustom dabbrev-check-all-buffers t + "*Non-nil means dabbrev package should search *all* buffers. -(defvar dabbrev-check-rest-of-buffers t - "*Non-nil means dabbrev package should search in all buffers. -It searches the buffers pointed out by `dabbrev-select-buffers-function' -first; afterward it looks in the rest of the buffers.") +Dabbrev always searches the current buffer first. Then, if +`dabbrev-check-other-buffers' says so, it searches the buffers +designated by `dabbrev-select-buffers-function'. +Then, if `dabbrev-check-all-buffers' is non-nil, dabbrev searches +all the other buffers, except those named in `dabbrev-ignored-buffer-names'." + :type 'boolean + :group 'dabbrev) -;; I recommend that you set this to t. -(defvar dabbrev-always-check-other-buffers nil +(defcustom dabbrev-ignored-buffer-names '("*Messages*" "*Buffer List*") + "*List of buffer names that dabbrev should not check." + :type '(repeat (string :tag "Buffer name")) + :group 'dabbrev + :version "20.3") + +(defcustom dabbrev-check-other-buffers t "*Should \\[dabbrev-expand] look in other buffers?\ -nil = Don't look in other buffers.\n\ -t = Look in other buffers.\n\ -Value other than nil and t = ask the user if he want's to look in -other buffers. -The recommended value is t.") +nil: Don't look in other buffers. +t: Also look for expansions in the buffers pointed out by + `dabbrev-select-buffers-function'. +Anything else: When we can't find any more expansions in +the current buffer, then ask the user whether to look in other +buffers too. + +The default value is t." + :type '(choice (const :tag "off" nil) + (const :tag "on" t) + (other :tag "ask" other)) + :group 'dabbrev) ;; I guess setting this to a function that selects all C- or C++- ;; mode buffers would be a good choice for a debugging buffer, ;; when debugging C- or C++-code. (defvar dabbrev-select-buffers-function 'dabbrev--select-buffers "A function that selects buffers that should be searched by dabbrev. - The function should take no arguments and return a list of buffers to search for expansions. Have a look at `dabbrev--select-buffers' for an example. A mode setting this variable should make it buffer local.") -(defvar dabbrev-friend-buffer-function 'dabbrev--same-major-mode-p - "*A function to check if OTHER-BUFFER should be searched by dabbrev. - +(defcustom dabbrev-friend-buffer-function 'dabbrev--same-major-mode-p + "*A function to decide whether dabbrev should search OTHER-BUFFER. The function should take one argument, OTHER-BUFFER, and return non-nil if that buffer should be searched. Have a look at `dabbrev--same-major-mode-p' for an example. @@ -210,19 +240,19 @@ The value of `dabbrev-friend-buffer-function' has an effect only if the value of `dabbrev-select-buffers-function' uses it. The function `dabbrev--select-buffers' is one function you can use here. -A mode setting this variable should make it buffer local.") +A mode setting this variable should make it buffer local." + :type 'function + :group 'dabbrev) -(defvar dabbrev-search-these-buffers-only nil +(defcustom dabbrev-search-these-buffers-only nil "If non-nil, a list of buffers which dabbrev should search. If this variable is non-nil, dabbrev will only look in these buffers. It will not even look in the current buffer if it is not a member of this list.") -;;;---------------------------------------------------------------- -;;;---------------------------------------------------------------- -;;; Internal variables -;;;---------------------------------------------------------------- -;;;---------------------------------------------------------------- +;;---------------------------------------------------------------- +;; Internal variables +;;---------------------------------------------------------------- ;; Last obarray of completions in `dabbrev-completion' (defvar dabbrev--last-obarray nil) @@ -257,17 +287,19 @@ this list.") ;; The buffer we last did a completion in. (defvar dabbrev--last-completion-buffer nil) -;; Same as dabbrev-always-check-other-buffers, but is set for every expand. -(defvar dabbrev--check-other-buffers dabbrev-always-check-other-buffers) +;; Non-nil means we should upcase +;; when copying successive words. +(defvar dabbrev--last-case-pattern nil) + +;; Same as dabbrev-check-other-buffers, but is set for every expand. +(defvar dabbrev--check-other-buffers dabbrev-check-other-buffers) ;; The regexp for recognizing a character in an abbreviation. (defvar dabbrev--abbrev-char-regexp nil) -;;;---------------------------------------------------------------- -;;;---------------------------------------------------------------- -;;; Macros -;;;---------------------------------------------------------------- -;;;---------------------------------------------------------------- +;;---------------------------------------------------------------- +;; Macros +;;---------------------------------------------------------------- ;;; Get the buffer that mini-buffer was activated from (defsubst dabbrev--minibuffer-origin () @@ -287,11 +319,9 @@ this list.") (setq dabbrev-tail (cdr dabbrev-tail))) (nreverse dabbrev-result)))) -;;;---------------------------------------------------------------- -;;;---------------------------------------------------------------- -;;; Exported functions -;;;---------------------------------------------------------------- -;;;---------------------------------------------------------------- +;;---------------------------------------------------------------- +;; Exported functions +;;---------------------------------------------------------------- ;;;###autoload (define-key esc-map "/" 'dabbrev-expand) @@ -316,13 +346,16 @@ With no prefix argument, it reuses an old completion list if there is a suitable one already." (interactive "*P") - (let* ((dabbrev-always-check-other-buffers (and arg t)) - (dabbrev-check-rest-of-buffers + (dabbrev--reset-global-variables) + (let* ((dabbrev-check-other-buffers (and arg t)) + (dabbrev-check-all-buffers (and arg (= (prefix-numeric-value arg) 16))) (abbrev (dabbrev--abbrev-at-point)) - (ignore-case-p (and (eval dabbrev-case-fold-search) - (or (not dabbrev-upcase-means-case-search) - (string= abbrev (downcase abbrev))))) + (ignore-case-p (and (if (eq dabbrev-case-fold-search 'case-fold-search) + case-fold-search + dabbrev-case-fold-search) + (or (not dabbrev-upcase-means-case-search) + (string= abbrev (downcase abbrev))))) (my-obarray dabbrev--last-obarray) init) (save-excursion @@ -343,11 +376,11 @@ if there is a suitable one already." ;;-------------------------------- ;; New abbreviation to expand. ;;-------------------------------- - (dabbrev--reset-global-variables) (setq dabbrev--last-abbreviation abbrev) ;; Find all expansion (let ((completion-list - (dabbrev--find-all-expansions abbrev ignore-case-p))) + (dabbrev--find-all-expansions abbrev ignore-case-p)) + (completion-ignore-case ignore-case-p)) ;; Make an obarray with all expansions (setq my-obarray (make-vector (length completion-list) 0)) (or (> (length my-obarray) 0) @@ -357,22 +390,22 @@ if there is a suitable one already." (cond ((or (not ignore-case-p) (not dabbrev-case-replace)) - (mapc (function (lambda (string) - (intern string my-obarray))) - completion-list)) + (mapcar (function (lambda (string) + (intern string my-obarray))) + completion-list)) ((string= abbrev (upcase abbrev)) - (mapc (function (lambda (string) - (intern (upcase string) my-obarray))) - completion-list)) + (mapcar (function (lambda (string) + (intern (upcase string) my-obarray))) + completion-list)) ((string= (substring abbrev 0 1) (upcase (substring abbrev 0 1))) - (mapc (function (lambda (string) - (intern (dabbrev--capitalize string) my-obarray))) - completion-list)) + (mapcar (function (lambda (string) + (intern (capitalize string) my-obarray))) + completion-list)) (t - (mapc (function (lambda (string) - (intern (downcase string) my-obarray))) - completion-list))) + (mapcar (function (lambda (string) + (intern (downcase string) my-obarray))) + completion-list))) (setq dabbrev--last-obarray my-obarray) (setq dabbrev--last-completion-buffer (current-buffer)) ;; Find the longest common string. @@ -420,20 +453,18 @@ with the next possible expansion not yet tried. The variable `dabbrev-backward-only' may be used to limit the direction of search to backward if set non-nil. -??? -To make it more powerful, make sure that -`dabbrev-always-check-other-buffers' is set to t. - See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." (interactive "*P") - (let (abbrev expansion old direction) + (let (abbrev record-case-pattern + expansion old direction (orig-point (point))) ;; abbrev -- the abbrev to expand ;; expansion -- the expansion found (eventually) or nil until then ;; old -- the text currently in the buffer ;; (the abbrev, or the previously-made expansion) (save-excursion (if (and (null arg) - dabbrev--last-abbrev-location + (markerp dabbrev--last-abbrev-location) + (marker-position dabbrev--last-abbrev-location) (or (eq last-command this-command) (and (window-minibuffer-p (selected-window)) (= dabbrev--last-abbrev-location @@ -443,29 +474,71 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." (setq abbrev dabbrev--last-abbreviation) (setq old dabbrev--last-expansion) (setq direction dabbrev--last-direction)) - ;; We have a different abbrev to expand. - (dabbrev--reset-global-variables) - (setq direction (if (null arg) - (if dabbrev-backward-only 1 0) - (prefix-numeric-value arg))) - (setq abbrev (dabbrev--abbrev-at-point)) - (setq old nil)) + ;; If the user inserts a space after expanding + ;; and then asks to expand again, always fetch the next word. + (if (and (eq (preceding-char) ?\ ) + (markerp dabbrev--last-abbrev-location) + (marker-position dabbrev--last-abbrev-location) + (= (point) (1+ dabbrev--last-abbrev-location))) + (progn + ;; The "abbrev" to expand is just the space. + (setq abbrev " ") + (save-excursion + (if dabbrev--last-buffer + (set-buffer dabbrev--last-buffer)) + ;; Find the end of the last "expansion" word. + (if (or (eq dabbrev--last-direction 1) + (and (eq dabbrev--last-direction 0) + (< dabbrev--last-expansion-location (point)))) + (setq dabbrev--last-expansion-location + (+ dabbrev--last-expansion-location + (length dabbrev--last-expansion)))) + (goto-char dabbrev--last-expansion-location) + ;; Take the following word, with intermediate separators, + ;; as our expansion this time. + (re-search-forward + (concat "\\(\\(" dabbrev--abbrev-char-regexp "\\)+\\)")) + (setq expansion (buffer-substring-no-properties + dabbrev--last-expansion-location (point))) + (if dabbrev--last-case-pattern + (setq expansion (upcase expansion))) + + ;; Record the end of this expansion, in case we repeat this. + (setq dabbrev--last-expansion-location (point))) + ;; Indicate that dabbrev--last-expansion-location is + ;; at the end of the expansion. + (setq dabbrev--last-direction -1)) + + ;; We have a different abbrev to expand. + (dabbrev--reset-global-variables) + (setq direction (if (null arg) + (if dabbrev-backward-only 1 0) + (prefix-numeric-value arg))) + (setq abbrev (dabbrev--abbrev-at-point)) + (setq record-case-pattern t) + (setq old nil))) ;;-------------------------------- ;; Find the expansion ;;-------------------------------- - (setq expansion - (dabbrev--find-expansion abbrev direction - (and (eval dabbrev-case-fold-search) - (or (not dabbrev-upcase-means-case-search) - (string= abbrev (downcase abbrev))))))) + (or expansion + (setq expansion + (dabbrev--find-expansion abbrev direction + (and (if (eq dabbrev-case-fold-search 'case-fold-search) + case-fold-search + dabbrev-case-fold-search) + (or (not dabbrev-upcase-means-case-search) + (string= abbrev (downcase abbrev)))))))) (cond ((not expansion) (dabbrev--reset-global-variables) (if old (save-excursion - (search-backward (substring old (length abbrev))) - (delete-region (match-beginning 0) (match-end 0)))) + (setq buffer-undo-list (cons orig-point buffer-undo-list)) + ;; Put back the original abbrev with its original case pattern. + (search-backward old) + (insert abbrev) + (delete-region (point) (+ (point) (length old))))) (error "No%s dynamic expansion for `%s' found" (if old " further" "") abbrev)) (t @@ -475,34 +548,34 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." (buffer-name dabbrev--last-buffer)) (setq dabbrev--last-buffer-found dabbrev--last-buffer)) (message nil)) + (if (and (or (eq (current-buffer) dabbrev--last-buffer) + (null dabbrev--last-buffer)) + (numberp dabbrev--last-expansion-location) + (and (> dabbrev--last-expansion-location (point)))) + (setq dabbrev--last-expansion-location + (copy-marker dabbrev--last-expansion-location))) ;; Success: stick it in and return. + (setq buffer-undo-list (cons orig-point buffer-undo-list)) (dabbrev--substitute-expansion old abbrev expansion) + + ;; If we are not copying successive words now, + ;; set dabbrev--last-case-pattern. + (and record-case-pattern + (setq dabbrev--last-case-pattern + (and (if (eq dabbrev-case-fold-search 'case-fold-search) + case-fold-search + dabbrev-case-fold-search) + (not dabbrev-upcase-means-case-search) + (equal abbrev (upcase abbrev))))) + ;; Save state for re-expand. (setq dabbrev--last-expansion expansion) (setq dabbrev--last-abbreviation abbrev) (setq dabbrev--last-abbrev-location (point-marker)))))) -;;;---------------------------------------------------------------- -;;;---------------------------------------------------------------- -;;; Local functions -;;;---------------------------------------------------------------- -;;;---------------------------------------------------------------- - -(defun dabbrev--capitalize (string) - ;; Capitalize STRING (See capitalize-word) - (let ((new-string "")) - (save-match-data - (while (string-match "\\w+" string) - (let* ((mb (match-beginning 0)) - (me (match-end 0)) - (ms (substring string mb me))) - (setq new-string - (concat new-string - (substring string 0 mb) - (upcase (substring ms 0 1)) - (downcase (substring ms 1)))) - (setq string (substring string me))))) - new-string)) +;;---------------------------------------------------------------- +;; Local functions +;;---------------------------------------------------------------- ;;; Checks if OTHER-BUFFER has the same major mode as current buffer. (defun dabbrev--same-major-mode-p (other-buffer) @@ -531,22 +604,32 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." ;;; Extract the symbol at point to serve as abbreviation. (defun dabbrev--abbrev-at-point () ;; Check for error - (save-excursion - (save-match-data - (if (or (bobp) - (progn - (forward-char -1) - (not (looking-at (concat "\\(" - (or dabbrev-abbrev-char-regexp - "\\sw\\|\\s_") - "\\)+"))))) - (error "Not positioned immediately after an abbreviation")))) + (if (bobp) + (error "No possible abbreviation preceding point")) ;; Return abbrev at point (save-excursion + ;; Record the end of the abbreviation. (setq dabbrev--last-abbrev-location (point)) - (buffer-substring (point) - (progn (dabbrev--goto-start-of-abbrev) - (point))))) + ;; If we aren't right after an abbreviation, + ;; move point back to just after one. + ;; This is so the user can get successive words + ;; by typing the punctuation followed by M-/. + (save-match-data + (if (save-excursion + (forward-char -1) + (not (looking-at (concat "\\(" + (or dabbrev-abbrev-char-regexp + "\\sw\\|\\s_") + "\\)+")))) + (if (re-search-backward (or dabbrev-abbrev-char-regexp + "\\sw\\|\\s_") + nil t) + (forward-char 1) + (error "No possible abbreviation preceding point")))) + ;; Now find the beginning of that one. + (dabbrev--goto-start-of-abbrev) + (buffer-substring-no-properties + dabbrev--last-abbrev-location (point)))) ;;; Initializes all global variables (defun dabbrev--reset-global-variables () @@ -563,7 +646,7 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." dabbrev--last-buffer-found nil dabbrev--abbrev-char-regexp (or dabbrev-abbrev-char-regexp "\\sw\\|\\s_") - dabbrev--check-other-buffers dabbrev-always-check-other-buffers)) + dabbrev--check-other-buffers dabbrev-check-other-buffers)) ;;; Find all buffers that are considered "friends" according to the ;;; function pointed out by dabbrev-friend-buffer-function. @@ -582,19 +665,21 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." ;;; but looking in reverse instead if REVERSE is non-nil. (defun dabbrev--try-find (abbrev reverse n ignore-case) (save-excursion - (let ((expansion nil)) - (and dabbrev--last-expansion-location - (goto-char dabbrev--last-expansion-location)) - (let ((case-fold-search ignore-case) - (count n)) - (while (and (> count 0) - (setq expansion (dabbrev--search abbrev - reverse - ignore-case))) - (setq count (1- count)))) - (and expansion - (setq dabbrev--last-expansion-location (point))) - expansion))) + (save-restriction + (widen) + (let ((expansion nil)) + (and dabbrev--last-expansion-location + (goto-char dabbrev--last-expansion-location)) + (let ((case-fold-search ignore-case) + (count n)) + (while (and (> count 0) + (setq expansion (dabbrev--search abbrev + reverse + ignore-case))) + (setq count (1- count)))) + (and expansion + (setq dabbrev--last-expansion-location (point))) + expansion)))) ;;; Find all expansions of ABBREV (defun dabbrev--find-all-expansions (abbrev ignore-case) @@ -603,7 +688,7 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." (save-excursion (goto-char (point-min)) (while (setq expansion (dabbrev--find-expansion abbrev -1 ignore-case)) - (push expansion all-expansions))) + (setq all-expansions (cons expansion all-expansions)))) all-expansions)) (defun dabbrev--scanning-message () @@ -671,15 +756,26 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." (let* (friend-buffer-list non-friend-buffer-list) (setq dabbrev--friend-buffer-list (funcall dabbrev-select-buffers-function)) - (if dabbrev-check-rest-of-buffers + (if dabbrev-check-all-buffers (setq non-friend-buffer-list (nreverse (dabbrev-filter-elements buffer (buffer-list) - (not (memq buffer dabbrev--friend-buffer-list)))) + (and (not (member (buffer-name buffer) + dabbrev-ignored-buffer-names)) + (not (memq buffer dabbrev--friend-buffer-list))))) dabbrev--friend-buffer-list (append dabbrev--friend-buffer-list non-friend-buffer-list))))) + ;; Move buffers that are visible on the screen + ;; to the front of the list. + (if dabbrev--friend-buffer-list + (let ((w (next-window (selected-window)))) + (while (not (eq w (selected-window))) + (setq dabbrev--friend-buffer-list + (cons (window-buffer w) + (delq (window-buffer w) dabbrev--friend-buffer-list))) + (setq w (next-window w))))) ;; Walk through the buffers (while (and (not expansion) dabbrev--friend-buffer-list) (setq dabbrev--last-buffer @@ -704,17 +800,40 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." ;;; EXPANSION is the expansion substring. (defun dabbrev--substitute-expansion (old abbrev expansion) ;;(undo-boundary) - (let ((use-case-replace (and (eval dabbrev-case-fold-search) + (let ((use-case-replace (and (if (eq dabbrev-case-fold-search 'case-fold-search) + case-fold-search + dabbrev-case-fold-search) (or (not dabbrev-upcase-means-case-search) (string= abbrev (downcase abbrev))) - (eval dabbrev-case-replace)))) + (if (eq dabbrev-case-replace 'case-replace) + case-replace + dabbrev-case-replace)))) (and nil use-case-replace (setq old (concat abbrev (or old ""))) (setq expansion (concat abbrev expansion))) + ;; If the expansion has mixed case + ;; and it is not simply a capitalized word, + ;; or if the abbrev has mixed case, + ;; and if the given abbrev's case pattern + ;; matches the start of the expansion, + ;; copy the expansion's case + ;; instead of downcasing all the rest. + (let ((expansion-rest (substring expansion 1))) + (if (and (not (and (or (string= expansion-rest (downcase expansion-rest)) + (string= expansion-rest (upcase expansion-rest))) + (or (string= abbrev (downcase abbrev)) + (string= abbrev (upcase abbrev))))) + (string= abbrev + (substring expansion 0 (length abbrev)))) + (setq use-case-replace nil))) + (if (equal abbrev " ") + (setq use-case-replace nil)) + (if use-case-replace + (setq expansion (downcase expansion))) (if old (save-excursion (search-backward old)) - ;;(store-match-data (list (point-marker) (point-marker))) + ;;(set-match-data (list (point-marker) (point-marker))) (search-backward abbrev)) ;; Make case of replacement conform to case of abbreviation ;; provided (1) that kind of thing is enabled in this buffer @@ -729,7 +848,7 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." ;;; ABBREV is string to find as prefix of word. Second arg, REVERSE, ;;; is t for reverse search, nil for forward. Variable dabbrev-limit -;;; controls the maximum search region size. Third argment IGNORE-CASE +;;; controls the maximum search region size. Third argument IGNORE-CASE ;;; non-nil means treat case as insignificant while looking for a match ;;; and when comparing with previous matches. Also if that's non-nil ;;; and the match is found at the beginning of a sentence and is in @@ -762,41 +881,39 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." (if reverse (re-search-backward pattern1 nil t) (re-search-forward pattern1 nil t))) - (cond - ((progn - (goto-char (match-beginning 0)) - (dabbrev--goto-start-of-abbrev) - (/= (point) (match-beginning 0))) - ;; Prefix of found abbreviation not OK - nil) - (t - (goto-char (match-beginning 0)) + (goto-char (match-beginning 0)) + ;; In case we matched in the middle of a word, + ;; back up to start of word and verify we still match. + (dabbrev--goto-start-of-abbrev) + + (if (not (looking-at pattern1)) + nil + ;; We have a truly valid match. Find the end. (re-search-forward pattern2) - (setq found-string - (buffer-substring (match-beginning 1) (match-end 1))) + (setq found-string (buffer-substring-no-properties + (match-beginning 1) (match-end 1))) (and ignore-case (setq found-string (downcase found-string))) - ;; Throw away if found in table + ;; Ignore this match if it's already in the table. (if (dabbrev-filter-elements table-string dabbrev--last-table (string= found-string table-string)) - (setq found-string nil)))) + (setq found-string nil))) + ;; Prepare to continue searching. (if reverse (goto-char (match-beginning 0)) (goto-char (match-end 0)))) - (cond - (found-string - ;;-------------------------------- - ;; Put in `dabbrev--last-table' and decide if we should return - ;; result or (downcase result) - ;;-------------------------------- - (push found-string dabbrev--last-table) - (let ((result (buffer-substring (match-beginning 0) (match-end 0)))) - (if (and ignore-case (eval dabbrev-case-replace)) - (downcase result) - result)))))))) + ;; If we found something, use it. + (if found-string + ;; Put it into `dabbrev--last-table' + ;; and return it (either downcased, or as is). + (let ((result (buffer-substring-no-properties + (match-beginning 0) (match-end 0)))) + (setq dabbrev--last-table + (cons found-string dabbrev--last-table)) + (if (and ignore-case (eval dabbrev-case-replace)) + result + result))))))) (provide 'dabbrev) -;; dabbrev.el ends here - - +;;; dabbrev.el ends here