home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / NeXT / GnuSource / emacs-15.0.3 / lisp / dabbrev.el < prev    next >
Lisp/Scheme  |  1990-07-19  |  9KB  |  219 lines

  1. ;; Dynamic abbreviation package for GNU Emacs.
  2. ;; Copyright (C) 1985, 1986 Free Software Foundation, Inc.
  3.  
  4. ;; This file is part of GNU Emacs.
  5.  
  6. ;; GNU Emacs is distributed in the hope that it will be useful,
  7. ;; but WITHOUT ANY WARRANTY.  No author or distributor
  8. ;; accepts responsibility to anyone for the consequences of using it
  9. ;; or for whether it serves any particular purpose or works at all,
  10. ;; unless he says so in writing.  Refer to the GNU Emacs General Public
  11. ;; License for full details.
  12.  
  13. ;; Everyone is granted permission to copy, modify and redistribute
  14. ;; GNU Emacs, but only under the conditions described in the
  15. ;; GNU Emacs General Public License.   A copy of this license is
  16. ;; supposed to have been given to you along with GNU Emacs so you
  17. ;; can know your rights and responsibilities.  It should be in a
  18. ;; file named COPYING.  Among other things, the copyright notice
  19. ;; and this notice must be preserved on all copies.
  20.  
  21.  
  22. ; DABBREVS - "Dynamic abbreviations" hack, originally written by Don Morrison
  23. ; for Twenex Emacs.  Converted to mlisp by Russ Fish.  Supports the table
  24. ; feature to avoid hitting the same expansion on re-expand, and the search
  25. ; size limit variable.  Bugs fixed from the Twenex version are flagged by
  26. ; comments starting with ;;; .
  27. ; converted to elisp by Spencer Thomas.
  28. ; Thoroughly cleaned up by Richard Stallman.
  29. ;  
  30. ; If anyone feels like hacking at it, Bob Keller (Keller@Utah-20) first
  31. ; suggested the beast, and has some good ideas for its improvement, but
  32. ; doesn?tknow TECO (the lucky devil...).  One thing that should definitely
  33. ; be done is adding the ability to search some other buffer(s) if you can?t
  34. ; find the expansion you want in the current one.
  35.  
  36. ;; (defun dabbrevs-help ()
  37. ;;   "Give help about dabbrevs."
  38. ;;   (interactive)
  39. ;;   (&info "emacs" "dabbrevs")    ; Select the specific info node.
  40. ;; )
  41. (provide 'dabbrevs)
  42.  
  43. (defvar dabbrevs-limit nil
  44.   "*Limits region searched by dabbrevs-expand to that many chars away (local).")
  45. (make-variable-buffer-local 'dabbrevs-limit)
  46.  
  47. (defvar dabbrevs-backward-only nil
  48.   "*If non-NIL, dabbrevs-expand only looks backwards.")
  49.  
  50. ; State vars for dabbrevs-re-expand.
  51. (defvar last-dabbrevs-table nil
  52.   "Table of expansions seen so far. (local)")
  53. (make-variable-buffer-local 'last-dabbrevs-table)
  54.  
  55. (defvar last-dabbrevs-abbreviation ""
  56.   "Last string we tried to expand.  Buffer-local.")
  57. (make-variable-buffer-local 'last-dabbrevs-abbreviation)
  58.  
  59. (defvar last-dabbrevs-direction 0
  60.   "Direction of last dabbrevs search. (local)")
  61. (make-variable-buffer-local 'last-dabbrevs-direction)
  62.  
  63. (defvar last-dabbrevs-abbrev-location nil
  64.   "Location last abbreviation began (local).")
  65. (make-variable-buffer-local 'last-dabbrevs-abbrev-location)
  66.  
  67. (defvar last-dabbrevs-expansion nil
  68.     "Last expansion of an abbreviation. (local)")
  69. (make-variable-buffer-local 'last-dabbrevs-expansion)
  70.  
  71. (defvar last-dabbrevs-expansion-location nil
  72.   "Location the last expansion was found. (local)")
  73. (make-variable-buffer-local 'last-dabbrevs-expansion-location)
  74.  
  75. (defun dabbrev-expand (arg)
  76.   "Expand previous word \"dynamically\".
  77. Expands to the most recent, preceding word for which this is a prefix.
  78. If no suitable preceding word is found, words following point are considered.
  79.  
  80. A positive prefix argument, N, says to take the Nth backward DISTINCT
  81. possibility.  A negative argument says search forward.  The variable
  82. dabbrev-backward-only may be used to limit the direction of search to
  83. backward if set non-nil.
  84.  
  85. If the cursor has not moved from the end of the previous expansion and
  86. no argument is given, replace the previously-made expansion
  87. with the next possible expansion not yet tried."
  88.   (interactive "*P")
  89.   (let (abbrev expansion old which loc n pattern
  90.     (nocase (and case-fold-search case-replace)))
  91.     ;; abbrev -- the abbrev to expand
  92.     ;; expansion -- the expansion found (eventually) or nil until then
  93.     ;; old -- the text currently in the buffer
  94.     ;;    (the abbrev, or the previously-made expansion)
  95.     ;; loc -- place where expansion is found
  96.     ;;    (to start search there for next expansion if requested later)
  97.     ;; nocase -- non-nil if should consider case significant.
  98.     (save-excursion
  99.       (if (and (null arg)
  100.            (eq last-command this-command)
  101.            last-dabbrevs-abbrev-location)
  102.       (progn
  103.         (setq abbrev last-dabbrevs-abbreviation)
  104.         (setq old last-dabbrevs-expansion)
  105.         (setq which last-dabbrevs-direction))
  106.     (setq which (if (null arg)
  107.             (if dabbrevs-backward-only 1 0)
  108.                 (prefix-numeric-value arg)))
  109.     (setq loc (point))
  110.     (forward-word -1)
  111.     (setq last-dabbrevs-abbrev-location (point)) ; Original location.
  112.     (setq abbrev (buffer-substring (point) loc))
  113.     (setq old abbrev)
  114.     (setq last-dabbrevs-expansion-location nil)
  115.     (setq last-dabbrev-table nil))      ; Clear table of things seen.
  116.  
  117.       (setq pattern (concat "\\b" (regexp-quote abbrev) "\\(\\sw\\|\\s_\\)+"))
  118.       ;; Try looking backward unless inhibited.
  119.       (if (>= which 0)
  120.       (progn 
  121.         (setq n (max 1 which))
  122.         (if last-dabbrevs-expansion-location
  123.         (goto-char last-dabbrevs-expansion-location))
  124.         (while (and (> n 0)
  125.             (setq expansion (dabbrevs-search pattern t nocase)))
  126.           (setq loc (point-marker))
  127.           (setq last-dabbrev-table (cons expansion last-dabbrev-table))
  128.           (setq n (1- n)))
  129.         (or expansion
  130.         (setq last-dabbrevs-expansion-location nil))
  131.         (setq last-dabbrevs-direction (min 1 which))))
  132.  
  133.       (if (and (<= which 0) (not expansion)) ; Then look forward.
  134.       (progn 
  135.         (setq n (max 1 (- which)))
  136.         (if last-dabbrevs-expansion-location
  137.         (goto-char last-dabbrevs-expansion-location))
  138.         (while (and (> n 0)
  139.             (setq expansion (dabbrevs-search pattern nil nocase)))
  140.           (setq loc (point-marker))
  141.           (setq last-dabbrev-table (cons expansion last-dabbrev-table))
  142.           (setq n (1- n)))
  143.         (setq last-dabbrevs-direction -1))))
  144.  
  145.     (if (not expansion)
  146.     (let ((first (string= abbrev old)))
  147.       (setq last-dabbrevs-abbrev-location nil)
  148.       (if (not first)
  149.           (progn (undo-boundary)
  150.              (delete-backward-char (length old))
  151.              (insert abbrev)))
  152.       (error (if first
  153.              "No dynamic expansion for \"%s\" found."
  154.              "No further dynamic expansions for \"%s\" found.")
  155.          abbrev))
  156.       ;; Success: stick it in and return.
  157.       (undo-boundary)
  158.       (search-backward old)
  159.       ;; Make case of replacement conform to case of abbreviation
  160.       ;; provided (1) that kind of thing is enabled in this buffer
  161.       ;; and (2) the replacement itself is all lower case
  162.       ;; except perhaps for the first character.
  163.       (let ((nocase (and nocase
  164.              (string= expansion
  165.                   (concat (substring expansion 0 1)
  166.                       (downcase (substring expansion 1)))))))
  167.     (replace-match (if nocase (downcase expansion) expansion)
  168.                (not nocase)
  169.                'literal))
  170.       ;; Save state for re-expand.
  171.       (setq last-dabbrevs-abbreviation abbrev)
  172.       (setq last-dabbrevs-expansion expansion)
  173.       (setq last-dabbrevs-expansion-location loc))))
  174.  
  175. ;; Search function used by dabbrevs library.  
  176. ;; First arg is string to find as prefix of word.  Second arg is
  177. ;; t for reverse search, nil for forward.  Variable dabbrevs-limit
  178. ;; controls the maximum search region size.
  179.  
  180. ;; Table of expansions already seen is examined in buffer last-dabbrev-table,
  181. ;; so that only distinct possibilities are found by dabbrevs-re-expand.
  182. ;; Note that to prevent finding the abbrev itself it must have been
  183. ;; entered in the table.
  184.  
  185. ;; Value is the expansion, or nil if not found.  After a successful
  186. ;; search, point is left right after the expansion found.
  187.  
  188. (defun dabbrevs-search (pattern reverse nocase)
  189.   (let (missing result)
  190.     (save-restriction         ; Uses restriction for limited searches.
  191.       (if dabbrevs-limit
  192.       (narrow-to-region last-dabbrevs-abbrev-location
  193.                 (+ (point)
  194.                    (* dabbrevs-limit (if reverse -1 1)))))
  195.       ;; Keep looking for a distinct expansion.
  196.       (setq result nil)
  197.       (setq missing nil)
  198.       (while  (and (not result) (not missing))
  199.     ; Look for it, leave loop if search fails.
  200.     (setq missing
  201.           (not (if reverse
  202.                (re-search-backward pattern nil t)
  203.                (re-search-forward pattern nil t))))
  204.  
  205.     (if (not missing)
  206.         (progn
  207.           (setq result (buffer-substring (match-beginning 0)
  208.                          (match-end 0)))
  209.           (let* ((test last-dabbrev-table))
  210.         (while (and test
  211.                 (not
  212.                  (if nocase
  213.                  (string= (downcase (car test)) (downcase result))
  214.                    (string= (car test) result))))
  215.           (setq test (cdr test)))
  216.         (if test (setq result nil))))))    ; if already in table, ignore
  217.       result)))
  218.