*** empty log message ***
[bpt/emacs.git] / lisp / dabbrev.el
index c959195..20f6fea 100644 (file)
@@ -1,7 +1,7 @@
 ;;; dabbrev.el --- dynamic abbreviation package
 
-;; Copyright (C) 1985, 86, 92, 94, 96, 1997, 2000, 01, 2003
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 1985, 1986, 1992, 1994, 1996, 1997, 2000, 2001, 2002,
+;;   2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 ;; Author: Don Morrison
 ;; Maintainer: Lars Lindberg <Lars.Lindberg@sypro.cap.se>
@@ -13,7 +13,7 @@
 
 ;; 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, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
@@ -23,8 +23,8 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; 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.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 ;;----------------------------------------------------------------
 
 (defgroup dabbrev nil
-  "Dynamic Abbreviations"
+  "Dynamic Abbreviations."
   :tag "Dynamic Abbreviations"
   :group 'abbrev
   :group 'convenience)
@@ -128,7 +128,7 @@ Set this to nil if no characters should be skipped."
                 (const :tag "off" nil))
   :group 'dabbrev)
 
-(defcustom dabbrev--eliminate-newlines t
+(defcustom dabbrev-eliminate-newlines t
   "*Non-nil means dabbrev should not insert newlines.
 Instead it converts them to spaces."
   :type 'boolean
@@ -147,7 +147,7 @@ Any other non-nil version means case is not significant."
 
 (defcustom dabbrev-upcase-means-case-search nil
   "*The significance of an uppercase character in an abbreviation.
-nil means case fold search when searching for possible expansions;
+A nil value means case fold search when searching for possible expansions;
 non-nil means case sensitive search.
 
 This variable has an effect only when the value of
@@ -168,7 +168,7 @@ This variable has an effect only when the value of
                 (const :tag "based on `case-replace'" case-replace)
                 (other :tag "on" t))
   :group 'dabbrev
-  :version "21.4")
+  :version "22.1")
 
 (defcustom dabbrev-case-replace 'case-replace
   "*Whether dabbrev applies the abbreviations's case pattern to the expansion.
@@ -282,7 +282,8 @@ A mode setting this variable should make it buffer local."
   "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.")
+this list."
+  :group 'dabbrev)
 
 ;;----------------------------------------------------------------
 ;; Internal variables
@@ -331,6 +332,9 @@ this list.")
 ;; The regexp for recognizing a character in an abbreviation.
 (defvar dabbrev--abbrev-char-regexp nil)
 
+;; The progress reporter for buffer-scanning progress.
+(defvar dabbrev--progress-reporter nil)
+
 ;;----------------------------------------------------------------
 ;; Macros
 ;;----------------------------------------------------------------
@@ -372,11 +376,7 @@ function pointed out by `dabbrev-friend-buffer-function' to find the
 completions.
 
 If the prefix argument is 16 (which comes from C-u C-u),
-then it searches *all* buffers.
-
-With no prefix argument, it reuses an old completion list
-if there is a suitable one already."
-
+then it searches *all* buffers."
   (interactive "*P")
   (dabbrev--reset-global-variables)
   (let* ((dabbrev-check-other-buffers (and arg t))
@@ -391,57 +391,43 @@ if there is a suitable one already."
         (my-obarray dabbrev--last-obarray)
         init)
     (save-excursion
-      (if (and (null arg)
-              my-obarray
-              (or (eq dabbrev--last-completion-buffer (current-buffer))
-                  (and (window-minibuffer-p (selected-window))
-                       (eq dabbrev--last-completion-buffer
-                           (dabbrev--minibuffer-origin))))
-              dabbrev--last-abbreviation
-              (>= (length abbrev) (length dabbrev--last-abbreviation))
-              (string= dabbrev--last-abbreviation
-                       (substring abbrev 0
-                                  (length dabbrev--last-abbreviation)))
-              (setq init (try-completion abbrev my-obarray)))
-         ;; We can reuse the existing completion list.
-         nil
-       ;;--------------------------------
-       ;; New abbreviation to expand.
-       ;;--------------------------------
-       (setq dabbrev--last-abbreviation abbrev)
-       ;; Find all expansion
-       (let ((completion-list
-              (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)
-             (error "No dynamic expansion for \"%s\" found%s"
-                    abbrev
-                    (if dabbrev--check-other-buffers "" " in this-buffer")))
-         (cond
-          ((or (not ignore-case-p)
-               (not dabbrev-case-replace))
-           (mapc (function (lambda (string)
-                             (intern string my-obarray)))
-                   completion-list))
-          ((string= abbrev (upcase abbrev))
-           (mapc (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 (capitalize string) my-obarray)))
-                   completion-list))
-          (t
-           (mapc (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.
-         (setq init (try-completion abbrev my-obarray)))))
+      ;;--------------------------------
+      ;; New abbreviation to expand.
+      ;;--------------------------------
+      (setq dabbrev--last-abbreviation abbrev)
+      ;; Find all expansion
+      (let ((completion-list
+            (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)
+           (error "No dynamic expansion for \"%s\" found%s"
+                  abbrev
+                  (if dabbrev--check-other-buffers "" " in this-buffer")))
+       (cond
+        ((or (not ignore-case-p)
+             (not dabbrev-case-replace))
+         (mapc (function (lambda (string)
+                           (intern string my-obarray)))
+               completion-list))
+        ((string= abbrev (upcase abbrev))
+         (mapc (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 (capitalize string) my-obarray)))
+               completion-list))
+        (t
+         (mapc (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.
+       (setq init (try-completion abbrev my-obarray))))
     ;;--------------------------------
     ;; Let the user choose between the expansions
     ;;--------------------------------
@@ -460,7 +446,8 @@ if there is a suitable one already."
       ;; * String is a common substring completion already.  Make list.
       (message "Making completion list...")
       (with-output-to-temp-buffer "*Completions*"
-       (display-completion-list (all-completions init my-obarray)))
+       (display-completion-list (all-completions init my-obarray)
+                                init))
       (message "Making completion list...done")))
     (and (window-minibuffer-p (selected-window))
         (message nil))))
@@ -508,7 +495,7 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]."
            (setq direction dabbrev--last-direction))
        ;; If the user inserts a space after expanding
        ;; and then asks to expand again, always fetch the next word.
-       (if (and (eq (preceding-char) ?\ )
+       (if (and (eq (preceding-char) ?\s)
                 (markerp dabbrev--last-abbrev-location)
                 (marker-position dabbrev--last-abbrev-location)
                 (= (point) (1+ dabbrev--last-abbrev-location)))
@@ -516,25 +503,27 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]."
              ;; 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)))
-
-               ;; Record the end of this expansion, in case we repeat this.
-               (setq dabbrev--last-expansion-location (point)))
+               (save-restriction
+                 (widen)
+                 (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)))
+
+                 ;; 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))
@@ -725,10 +714,6 @@ If IGNORE-CASE is non-nil, accept matches which differ in case."
        (setq all-expansions (cons expansion all-expansions))))
     all-expansions))
 
-(defun dabbrev--scanning-message ()
-  (unless (window-minibuffer-p (selected-window))
-    (message "Scanning `%s'" (buffer-name (current-buffer)))))
-
 (defun dabbrev--ignore-buffer-p (buffer)
   "Return non-nil if BUFFER should be ignored by dabbrev."
   (let ((bn (buffer-name buffer)))
@@ -754,8 +739,7 @@ of the start of the occurrence."
     ;; If we were scanning something other than the current buffer,
     ;; continue scanning there.
     (when dabbrev--last-buffer
-      (set-buffer dabbrev--last-buffer)
-      (dabbrev--scanning-message))
+      (set-buffer dabbrev--last-buffer))
     (or
      ;; ------------------------------------------
      ;; Look backward in current buffer.
@@ -787,18 +771,20 @@ of the start of the occurrence."
         ;; If we have just now begun to search other buffers,
         ;; determine which other buffers we should check.
         ;; Put that list in dabbrev--friend-buffer-list.
-        (or dabbrev--friend-buffer-list
-            (setq dabbrev--friend-buffer-list
-                  (dabbrev--make-friend-buffer-list))))
+        (unless dabbrev--friend-buffer-list
+           (setq dabbrev--friend-buffer-list
+                 (dabbrev--make-friend-buffer-list))
+           (setq dabbrev--progress-reporter
+                 (make-progress-reporter
+                  "Scanning for dabbrevs..."
+                  (- (length dabbrev--friend-buffer-list)) 0 0 1 1.5))))
        ;; Walk through the buffers till we find a match.
        (let (expansion)
         (while (and (not expansion) dabbrev--friend-buffer-list)
-          (setq dabbrev--last-buffer
-                (car dabbrev--friend-buffer-list))
-          (setq dabbrev--friend-buffer-list
-                (cdr dabbrev--friend-buffer-list))
+          (setq dabbrev--last-buffer (pop dabbrev--friend-buffer-list))
           (set-buffer dabbrev--last-buffer)
-          (dabbrev--scanning-message)
+           (progress-reporter-update dabbrev--progress-reporter
+                                     (- (length dabbrev--friend-buffer-list)))
           (setq dabbrev--last-expansion-location (point-min))
           (setq expansion (dabbrev--try-find abbrev nil 1 ignore-case)))
         expansion)))))
@@ -891,23 +877,28 @@ to record whether we upcased the expansion, downcased it, or did neither."
     ;; matches the start of the expansion,
     ;; copy the expansion's case
     ;; instead of downcasing all the rest.
-    ;; Treat a one-capital-letter abbrev as "not all upper case",
-    ;; so as to force preservation of the expansion's pattern
-    ;; if the expansion starts with a capital letter.
-    (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))
-                            (and (string= abbrev (upcase abbrev))
-                                 (> (length abbrev) 1)))))
-              (string= abbrev
-                       (substring expansion 0 (length abbrev))))
+    ;;
+    ;; Treat a one-capital-letter (possibly with preceding non-letter
+    ;; characters) abbrev as "not all upper case", so as to force
+    ;; preservation of the expansion's pattern if the expansion starts
+    ;; with a capital letter.
+    (let ((expansion-rest (substring expansion 1))
+         (first-letter-position (string-match "[[:alpha:]]" abbrev)))
+      (if (or (null first-letter-position)
+             (and (not (and (or (string= expansion-rest (downcase expansion-rest))
+                                (string= expansion-rest (upcase expansion-rest)))
+                            (or (string= abbrev (downcase abbrev))
+                                (and (string= abbrev (upcase abbrev))
+                                     (> (- (length abbrev) first-letter-position)
+                                        1)))))
+                  (string= abbrev
+                           (substring expansion 0 (length abbrev)))))
          (setq use-case-replace nil)))
 
     ;; If the abbrev and the expansion are both all-lower-case
     ;; then don't do any conversion.  The conversion would be a no-op
     ;; for this replacement, but it would carry forward to subsequent words.
-    ;; The goal of this is to preven that carrying forward.
+    ;; The goal of this is to prevent that carrying forward.
     (if (and (string= expansion (downcase expansion))
             (string= abbrev (downcase abbrev)))
        (setq use-case-replace nil))
@@ -925,10 +916,12 @@ to record whether we upcased the expansion, downcased it, or did neither."
                          ((equal abbrev (downcase abbrev)) 'downcase)))))
 
     ;; Convert whitespace to single spaces.
-    (if dabbrev--eliminate-newlines
-       ;; Start searching at end of ABBREV so that any whitespace
-       ;; carried over from the existing text is not changed.
-       (let ((pos (length abbrev)))
+    (if dabbrev-eliminate-newlines
+       (let ((pos
+              (if (equal abbrev " ") 0 (length abbrev))))
+         ;; If ABBREV is real, search after the end of it.
+         ;; If ABBREV is space and we are copying successive words,
+         ;; search starting at the front.
          (while (string-match "[\n \t]+" expansion pos)
            (setq pos (1+ (match-beginning 0)))
            (setq expansion (replace-match " " nil nil expansion)))))
@@ -1000,8 +993,7 @@ Leaves point at the location of the start of the expansion."
              nil
            ;; We have a truly valid match.  Find the end.
            (re-search-forward pattern2)
-           (setq found-string (buffer-substring-no-properties
-                               (match-beginning 0) (match-end 0)))
+           (setq found-string (match-string-no-properties 0))
            (setq result found-string)
            (and ignore-case (setq found-string (downcase found-string)))
            ;; Ignore this match if it's already in the table.
@@ -1010,9 +1002,7 @@ Leaves point at the location of the start of the expansion."
                 (string= found-string table-string))
                (setq found-string nil)))
          ;; Prepare to continue searching.
-         (if reverse
-             (goto-char (match-beginning 0))
-           (goto-char (match-end 0))))
+         (goto-char (if reverse (match-beginning 0) (match-end 0))))
        ;; If we found something, use it.
        (when found-string
          ;; Put it into `dabbrev--last-table'