(Info-goto-node, Info-search):
[bpt/emacs.git] / lisp / dabbrev.el
index 430824d..d57ba97 100644 (file)
@@ -4,7 +4,7 @@
 ;; Author: Don Morrison
 ;; Maintainer: Lars Lindberg <Lars.Lindberg@sypro.cap.se>
 ;; Created: 16 Mars 1992
-;; Lindberg's last update version: 5.2
+;; Lindberg's last update version: 5.7
 ;; Keywords: abbrev expand completion
 
 ;; This program is free software; you can redistribute it and/or modify
 ;; 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.
 
@@ -85,7 +74,7 @@
 ;;  - Check the kill-ring when everything else fails.  (Maybe something
 ;;  for hippie-expand?).  [Bng] <boris@cs.rochester.edu>
 
-;;; Thanks goes to
+;;; These people gave suggestions:
 ;;  [hymie]    Hyman Rosen <marks!hymie@jyacc.jyacc.com>
 ;;  [burgett]  Steve Burgett <burgett@bizet.eecs.berkeley.edu>
 ;;  [jules]    Julian Gosnell <jules@x.co.uk>
@@ -149,20 +138,20 @@ variable to see if its value is t or nil.
 This variable has an effect only when the value of
 `dabbrev-case-fold-search' evaluates to t.")
 
-(defvar dabbrev-abbrev-char-regexp "\\sw\\|\\s_"
+(defvar 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
@@ -171,28 +160,33 @@ but expanding `yes-or-no' looks for a word starting with `no'.
 
 The recommended value is \"\\\\sw\\\\|\\\\s_\".")
 
-(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.")
+(defvar dabbrev-check-all-buffers t
+  "*Non-nil means dabbrev package should search *all* 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.")
 
-;; I recommend that you set this to t.
-(defvar dabbrev-always-check-other-buffers nil
+(defvar 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.")
 
 ;; 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.
@@ -200,8 +194,7 @@ 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.
-
+  "*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.
@@ -257,8 +250,8 @@ 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)
+;; 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)
@@ -316,8 +309,9 @@ 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)
@@ -343,7 +337,6 @@ 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
@@ -357,22 +350,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,10 +413,6 @@ 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)
@@ -433,7 +422,8 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]."
     ;;    (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,22 +433,57 @@ 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 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))
+
+         ;; 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)))
 
       ;;--------------------------------
       ;; 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 (eval dabbrev-case-fold-search)
+                                             (or (not dabbrev-upcase-means-case-search)
+                                                 (string= abbrev (downcase abbrev))))))))
     (cond
      ((not expansion)
       (dabbrev--reset-global-variables)
@@ -475,6 +500,12 @@ 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.
       (dabbrev--substitute-expansion old abbrev expansion)
       ;; Save state for re-expand.
@@ -488,22 +519,6 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]."
 ;;;----------------------------------------------------------------
 ;;;----------------------------------------------------------------
 
-(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))
-
 ;;; Checks if OTHER-BUFFER has the same major mode as current buffer.
 (defun dabbrev--same-major-mode-p (other-buffer)
   (eq major-mode
@@ -531,22 +546,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 dabbrev--last-abbrev-location
+                     (point))))
        
 ;;; Initializes all global variables
 (defun dabbrev--reset-global-variables ()
@@ -563,7 +588,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 +607,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 +630,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,7 +698,7 @@ 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
@@ -789,7 +816,7 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]."
          ;; Put in `dabbrev--last-table' and decide if we should return
          ;; result or (downcase result)
          ;;--------------------------------
-         (push found-string dabbrev--last-table)
+         (setq dabbrev--last-table (cons 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)