home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / h / hipexpnd.zip / HIPEXPND.EL next >
Text File  |  1993-03-25  |  27KB  |  734 lines

  1. ;; Expand text trying various ways to find its expansion.
  2. ;; Copyright (C) 1992 Free Software Foundation, Inc.
  3. ;;
  4. ;; This file is part of GNU Emacs.
  5.  
  6. ;; GNU Emacs is free software; you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation; either version 2, or (at your option)
  9. ;; any later version.
  10.  
  11. ;; GNU Emacs is distributed in the hope that it will be useful,
  12. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ;; GNU General Public License for more details.
  15.  
  16. ;; You should have received a copy of the GNU General Public License
  17. ;; along with GNU Emacs; see the file COPYING.  If not, write to
  18. ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  19. ;; 
  20. ;;  Author: Anders Holst (aho@sans.kth.se)
  21. ;;
  22. ;;  Last change: 10 March 1993
  23. ;;  
  24. ;;  LCD Archive Entry:
  25. ;;  hippie-expand|Anders Holst|aho@sans.kth.se|
  26. ;;  Expand text trying various ways to find its expansion.|
  27. ;;  10-Mar-1993|1.1|~/misc/hippie-expand.el.Z|
  28.  
  29. ;;  
  30. ;;  DESCRIPTION
  31. ;;  
  32. ;;  `hippie-expand' is a single function for a lot of different kinds
  33. ;;  of completions and expansions.  Called repeatedly it tries all
  34. ;;  possible completions in succession. 
  35. ;;  Which kinds of completions to try, and in which order, is
  36. ;;  determined by the contents of `hippie-expand-try-functions-list'.
  37. ;;  Much customization of `hippie-expand' can be made by changing the
  38. ;;  order of, removing, or inserting new functions in this list.
  39. ;;  Given a positive numeric argument, `hippie-expand' jumps directly
  40. ;;  ARG functions forward in this list.  Given some other argument
  41. ;;  (a negative argument or just Ctrl-U) it undoes the tried
  42. ;;  completion.
  43. ;;  If the variable `hippie-expand-verbose' is non-nil, `hippie-expand'
  44. ;;  outputs in a message which try-function in the list that is used
  45. ;;  currently (ie. was used currently and will be tried first the next
  46. ;;  time).
  47. ;;  The variable `hippie-expand-max-buffers' determines in how many
  48. ;;  buffers, apart from the current, to search for expansions in.  It
  49. ;;  is used by the try-functions named "-all-buffers".
  50. ;;  See also the macro `make-hippie-expand-function' below.
  51. ;;  
  52. ;;  A short description of the current try-functions in this file:
  53. ;;    `try-complete-file-name' : very convenient to have in any buffer,
  54. ;;      and not just in the minibuffer or (some) shell-mode.  It goes
  55. ;;      through all possible completions instead of just completing as
  56. ;;      much as is unique.
  57. ;;    `try-complete-file-name-partially' : To insert in the list just
  58. ;;      before `try-complete-file-name' for those who want first to get
  59. ;;      a file name completed only as many characters as is unique.
  60. ;;      (NOTE: Not by default in `hippie-expand-try-functions-list'.)
  61. ;;    `try-expand-all-abbrevs' : can be removed if you don't use abbrevs.
  62. ;;      Otherwise it looks through all abbrev-tables, starting with
  63. ;;      the local followed by the global. 
  64. ;;    `try-expand-line' : Searches the buffer for an entire line that 
  65. ;;      begins exactly as the current line.  Convenient sometimes, for 
  66. ;;      example as a substitute for (or complement to) the history
  67. ;;      list in shell-like buffers.  Remove it if you find it confusing.
  68. ;;    `try-expand-line-all-buffers' : Like `try-expand-line' but searches
  69. ;;      in all buffers (except the current).  (This may be a little
  70. ;;      slow, don't use it unless you are really fond of `hippie-expand'.
  71. ;;      NOTE: Not by default in hippie-expand-try-functions-list.)
  72. ;;    `try-expand-dabbrev' : works exactly as dabbrev-expand (but of
  73. ;;      course in a way compatible with the other try-functions).
  74. ;;    `try-expand-dabbrev-all-buffers' : perhaps the most useful of them,
  75. ;;      like `dabbrev-expand' but searches all Emacs buffers (except the
  76. ;;      current) for matching words.  (No, I don't find this one
  77. ;;      particularly slow.) 
  78. ;;    `try-complete-lisp-symbol' : like `lisp-complete-symbol', but goes
  79. ;;      through all possibilities instead of completing what is unique.
  80. ;;      Might be tedious (usually a lot of possible completions) and
  81. ;;      since its function is much like `lisp-complete-symbol', which
  82. ;;      already has a key of its own, you might want to remove this.
  83. ;;    `try-complete-lisp-symbol-partially' : To insert in the list just
  84. ;;      before `try-complete-lisp-symbol' for those who first want to get
  85. ;;      completion of what is unique in the name.  (NOTE: Not by
  86. ;;      default in hippie-expand-try-functions-list.)
  87. ;;
  88. ;;  To write new try-functions, consider the following:
  89. ;;  Each try-function takes one argument OLD which is nil the first
  90. ;;  time the function is called and true in succeeding calls for the
  91. ;;  same string to complete.  The first time the function has to
  92. ;;  extract the string before point to complete, and substitute the
  93. ;;  first completion alternative for it.  On following calls it has to
  94. ;;  substitute the next possible completion for the last tried string.
  95. ;;  The try-function is to return t as long as it finds new
  96. ;;  possible completions.  When there are no more alternatives it has
  97. ;;  to restore the text before point to its original contents, and
  98. ;;  return nil (don't beep or message or anything).
  99. ;;  The try-function can (should) use the following functions:
  100. ;;    `he-init-string' : Initializes the text to substitute to the
  101. ;;      contents of the region BEGIN to END.  Also sets the variable
  102. ;;      `he-search-string' to the text to expand.
  103. ;;    `he-substitute-string' : substitutes STR into the region
  104. ;;      initialized with `he-init-string'.  (An optional second argument
  105. ;;      TRANS-CASE non-nil, means transfer of case from the abbreviation
  106. ;;      to the expansion is ok if that is enabled in the buffer.)
  107. ;;    `he-reset-string' : Resets the initialized region to its original
  108. ;;      contents.
  109. ;;  There is also a variable: `he-tried-table' which is meant to contain
  110. ;;  all tried expansions so far.  The try-function can check this 
  111. ;;  variable to see whether an expansion has already been tried
  112. ;;  (hint: `he-string-member'), and add its own tried expansions to it.
  113. ;;
  114. ;;
  115. ;;  INSTALLATION
  116. ;;
  117. ;;  To install this file, put it in your load-path, and put the
  118. ;;  following or something similar in your .emacs :
  119. ;;  
  120. ;;    (autoload 'hippie-expand "hippie-expand" "Try to expand text before point")
  121. ;;    (define-key esc-map " " 'hippie-expand)
  122. ;;
  123. ;;  (Note that hippie-expand must be bound to a key to work properly.)
  124. ;;
  125. ;;  
  126. ;;  KNOWN BUGS
  127. ;;
  128. ;;  It may happen that some completion suggestion occurs twice, in
  129. ;;  spite of the use of `he-tried-table' to prevent that.  This is 
  130. ;;  because different try-functions may try to complete different
  131. ;;  lengths of text, and thus put different amounts of the
  132. ;;  text in `he-try-table'.  Anyway this seems to occur seldom enough not
  133. ;;  to be too disturbing.  Also it should NOT bee possible for the
  134. ;;  opposite situation to occur, that `hippie-expand' misses some
  135. ;;  suggestion because it thinks it has already tried it.
  136. ;;
  137. ;;  
  138. ;;  ACKNOWLEDGEMENT
  139. ;;
  140. ;;  I want to thank Mikael Djurfeldt in discussions with whom the idea
  141. ;;  of this function took form.
  142. ;;  I am also grateful to all those who have given me suggestions on
  143. ;;  how to improve it.
  144. ;;
  145.  
  146.  
  147. (defvar he-num -1)
  148.  
  149. (defvar he-string-beg (make-marker))
  150.  
  151. (defvar he-string-end (make-marker))
  152.  
  153. (defvar he-search-string ())
  154.  
  155. (defvar he-expand-list ())
  156.  
  157. (defvar he-tried-table ())
  158.  
  159. (defvar he-search-loc (make-marker))
  160.  
  161. (defvar he-search-bw ())
  162.  
  163. (defvar he-search-bufs ())
  164.  
  165. (defvar he-searched-n-bufs ())
  166.  
  167. (defvar hippie-expand-load-hook () 
  168.   "Run after loading `hippie-expand', for customization.
  169. Here can for example `hippie-expand-try-functions-list' be changed,
  170. and functions be defined with `make-hippie-expand-function'.")
  171.  
  172. (defvar hippie-expand-try-functions-list '(try-complete-file-name
  173.                        try-expand-all-abbrevs
  174.                        try-expand-line
  175.                        try-expand-dabbrev
  176.                        try-expand-dabbrev-all-buffers
  177.                        try-complete-lisp-symbol)
  178.   "The list of expansion functions tried in order by `hippie-expand'.
  179. To change the behavior of `hippie-expand', remove, change the order of,
  180. or insert functions in this list.")
  181.  
  182. (defvar hippie-expand-verbose t
  183.   "*Non-nil makes `hippie-expand' output which function it is trying.")
  184.  
  185. (defvar hippie-expand-max-buffers ()
  186.   "*The maximum number of buffers (apart from the current) searched.
  187. If nil, all buffers are searched.")
  188.  
  189. (defun hippie-expand (arg)
  190.   "Try to expand text before point, using multiple methods.
  191. The expansion functions in `hippie-expand-try-functions-list' are
  192. tried in order, until a possible expansion is found.  Repeated
  193. application of `hippie-expand' inserts successively possible
  194. expansions.  
  195. With a positive numeric argument, jumps directly to the ARG next
  196. function in this list.  With a negative argument or just \\[universal-argument], 
  197. undoes the expansion." 
  198.   (interactive "P")
  199.   (if (or (not arg) 
  200.       (and (integerp arg) (> arg 0)))
  201.       (let ((first (or (= he-num -1)
  202.                (not (equal this-command last-command)))))
  203.     (if first
  204.         (progn
  205.           (setq he-num -1)
  206.           (setq he-tried-table nil)))
  207.     (if arg
  208.         (if (not first) (he-reset-string))
  209.         (setq arg 0))
  210.     (let ((i (max (+ he-num arg) 0)))
  211.       (while (not (or (>= i (length hippie-expand-try-functions-list))
  212.               (apply (nth i hippie-expand-try-functions-list) 
  213.                  (list (= he-num i)))))
  214.         (setq i (1+ i)))
  215.       (setq he-num i))
  216.     (if (>= he-num (length hippie-expand-try-functions-list))
  217.         (progn
  218.           (setq he-num -1)
  219.           (if first
  220.           (message "No expansion found")
  221.           (message "No further expansions found"))
  222.           (ding))
  223.         (if hippie-expand-verbose
  224.         (message (concat "Using "
  225.                  (prin1-to-string (nth he-num 
  226.                    hippie-expand-try-functions-list)))))))
  227.       (if (>= he-num 0)
  228.       (progn
  229.         (setq he-num -1)
  230.         (he-reset-string)
  231.         (if hippie-expand-verbose
  232.         (message "Undoing expansions"))))))
  233.       
  234. ;; Initializes the region to expand (to between BEG and END).
  235. (defun he-init-string (beg end)
  236.   (set-marker he-string-beg beg)
  237.   (set-marker he-string-end end)
  238.   (setq he-search-string (buffer-substring beg end)))
  239.  
  240. ;; Resets the expanded region to its original contents.
  241. (defun he-reset-string ()
  242.   (let ((newpos (point-marker)))
  243.     (delete-region he-string-beg he-string-end)
  244.     (goto-char he-string-beg)
  245.     (insert he-search-string)
  246.     (set-marker he-string-end (point))
  247.     (if (= newpos he-string-beg)
  248.     (goto-char he-string-end)
  249.     (goto-char newpos))))
  250.  
  251. ;; Substitutes an expansion STR into the correct region (the region
  252. ;; initialized with `he-init-string'). 
  253. ;; An optional argument TRANS-CASE means that it is ok to transfer case
  254. ;; from the abbreviation to the expansion if that is possible, and is
  255. ;; enabled in the buffer.
  256. (defun he-substitute-string (str &optional trans-case)
  257.   (let ((trans-case (and trans-case
  258.              case-replace
  259.              case-fold-search
  260.              (he-transfer-case-ok str he-search-string)))
  261.     (newpos (point-marker)))
  262.     (he-reset-string)
  263.     (goto-char he-string-beg)
  264.     (search-forward he-search-string)
  265.     (replace-match (if trans-case (downcase str) str)
  266.            (not trans-case)
  267.            'literal)
  268.     (set-marker he-string-end (point))
  269.     (if (= newpos he-string-beg)
  270.     (goto-char he-string-end)
  271.     (goto-char newpos))))
  272.  
  273. (defun he-ordinary-case-p (str)
  274.   (or (string= str (downcase str))
  275.       (string= str (upcase str))
  276.       (string= str (capitalize str))))
  277.  
  278. (defun he-transfer-case-ok (to-str from-str)
  279.   (and (not (string= from-str (substring to-str 0 (length from-str))))
  280.          ;; otherwise transfer is not needed (and this also solves
  281.      ;; some obscure situations)
  282.        (he-ordinary-case-p to-str)
  283.          ;; otherwise case may be significant 
  284.        (he-ordinary-case-p from-str)
  285.          ;; otherwise replace-match wont know what to do
  286.   ))
  287.  
  288. ;; Check if STR is a member of LST.
  289. ;; Ignore case if `case-replace' and `case-fold-search' are both t.
  290. (defun he-string-member (str lst)
  291.   (while (and lst
  292.           (not
  293.            (if (and case-fold-search case-replace)
  294.            (string= (downcase (car lst)) (downcase str))
  295.            (string= (car lst) str))))
  296.     (setq lst (cdr lst)))
  297.   lst)
  298.  
  299. ;;  For the real hippie-expand enthusiast: A macro that makes it
  300. ;;  possible to use many functions like hippie-expand, but with
  301. ;;  different try-functions-lists.
  302. ;;  Usage is for example:
  303. ;;    (fset 'my-complete-file (make-hippie-expand-function
  304. ;;                             '(try-complete-file-name-partially
  305. ;;                               try-complete-file-name)))
  306. ;;    (fset 'my-complete-line (make-hippie-expand-function
  307. ;;                             '(try-expand-line
  308. ;;                               try-expand-line-all-buffers)))
  309. ;;  
  310. (defmacro make-hippie-expand-function (try-list &optional verbose)
  311.   "Construct a function similar to `hippie-expand'.
  312. Make it use the expansion functions in TRY-LIST.  An optional second
  313. argument VERBOSE non-nil makes the function verbose."
  314.   (` '(lambda (arg)
  315.        (, (concat 
  316.            "Try to expand text before point, using the following functions: \n"
  317.        (mapconcat 'prin1-to-string (eval try-list) ", ")))
  318.        (interactive "P")
  319.        (let ((hippie-expand-try-functions-list (, try-list))
  320.          (hippie-expand-verbose (, verbose)))
  321.      (hippie-expand arg)))))
  322.  
  323.  
  324. ;;;  Here follows the try-functions and their requisites:
  325.  
  326. (defun try-complete-file-name (old)
  327.   "Try to complete text as a file name.
  328. The argument OLD has to be nil the first call of this function, and t
  329. for subsequent calls (for further possible completions of the same
  330. string).  It returns t if a new completion is found, nil otherwise."
  331.   (if (not old)
  332.       (progn 
  333.     (he-init-string (he-file-name-beg) (point))
  334.     (let ((name-part (file-name-nondirectory he-search-string))
  335.           (dir-part (expand-file-name (or (file-name-directory
  336.                            he-search-string) ""))))
  337.       (if (not (he-string-member name-part he-tried-table))
  338.           (setq he-tried-table (cons name-part he-tried-table)))
  339.       (if (and (not (equal he-search-string ""))
  340.            (file-directory-p dir-part))
  341.           (setq he-expand-list (sort (file-name-all-completions 
  342.                       name-part
  343.                       dir-part)
  344.                      'string-lessp))
  345.           (setq he-expand-list ())))))
  346.  
  347.   (while (and he-expand-list
  348.           (he-string-member (car he-expand-list) he-tried-table))
  349.     (setq he-expand-list (cdr he-expand-list)))
  350.   (if (null he-expand-list)
  351.       (progn
  352.     (he-reset-string)
  353.     ())
  354.       (let ((filename (concat (file-name-directory he-search-string)
  355.                   (car he-expand-list))))
  356.     (he-substitute-string filename)
  357.     (setq he-tried-table (cons (car he-expand-list) he-tried-table))
  358.     (setq he-expand-list (cdr he-expand-list))
  359.     t)))
  360.  
  361. (defun try-complete-file-name-partially (old)
  362.   "Try to complete text as a file name, as many characters as unique.
  363. The argument OLD has to be nil the first call of this function.  It
  364. returns t if a unique, possibly partial, completion is found, nil 
  365. otherwise."
  366.   (let ((expansion ()))
  367.     (if (not old)
  368.     (progn 
  369.       (he-init-string (he-file-name-beg) (point))
  370.       (let ((name-part (file-name-nondirectory he-search-string))
  371.         (dir-part (expand-file-name (or (file-name-directory
  372.                          he-search-string) ""))))
  373.         (if (and (not (equal he-search-string ""))
  374.              (file-directory-p dir-part))
  375.         (setq expansion (file-name-completion name-part
  376.                               dir-part)))
  377.         (if (or (eq expansion t)
  378.             (string= expansion name-part))
  379.         (setq expansion ())))))
  380.  
  381.     (if (not expansion)
  382.     (progn
  383.       (he-reset-string)
  384.       ())
  385.     (let ((filename (concat (file-name-directory he-search-string)
  386.                 expansion)))
  387.       (he-substitute-string filename)
  388.       (setq he-tried-table (cons expansion he-tried-table))
  389.       t))))
  390.  
  391. (defun he-file-name-beg ()
  392.   (let ((skips "-a-zA-Z0-9_./~^#$"))
  393.     (save-excursion
  394.       (skip-chars-backward skips)
  395.       (point))))
  396.  
  397. (defun try-complete-lisp-symbol (old)
  398.   "Try to complete word as an Emacs Lisp symbol.
  399. The argument OLD has to be nil the first call of this function, and t
  400. for subsequent calls (for further possible completions of the same
  401. string).  It returns t if a new completion is found, nil otherwise."
  402.   (if (not old)
  403.       (progn 
  404.     (he-init-string (he-lisp-symbol-beg) (point))
  405.     (if (not (he-string-member he-search-string he-tried-table))
  406.         (setq he-tried-table (cons he-search-string he-tried-table)))
  407.     (setq he-expand-list 
  408.           (and (not (equal he-search-string ""))
  409.            (sort (all-completions he-search-string obarray
  410.                       (function (lambda (sym)
  411.                         (or (boundp sym)
  412.                         (fboundp sym)
  413.                         (symbol-plist sym)))))
  414.              'string-lessp)))))
  415.   (while (and he-expand-list
  416.           (he-string-member (car he-expand-list) he-tried-table))
  417.     (setq he-expand-list (cdr he-expand-list)))
  418.   (if (null he-expand-list)
  419.       (progn
  420.     (he-reset-string)
  421.     ())
  422.       (progn
  423.     (he-substitute-string (car he-expand-list))
  424.     (setq he-tried-table (cons (car he-expand-list) he-tried-table))
  425.     (setq he-expand-list (cdr he-expand-list))
  426.     t)))
  427.  
  428. (defun try-complete-lisp-symbol-partially (old)
  429.   "Try to complete as an Emacs Lisp symbol, as many characters as unique.
  430. The argument OLD has to be nil the first call of this function.  It
  431. returns t if a unique, possibly partial, completion is found, nil 
  432. otherwise."
  433.   (let ((expansion ()))
  434.     (if (not old)
  435.     (progn 
  436.       (he-init-string (he-lisp-symbol-beg) (point))
  437.       (if (not (string= he-search-string ""))
  438.           (setq expansion 
  439.             (try-completion he-search-string obarray
  440.                     (function (lambda (sym)
  441.                       (or (boundp sym)
  442.                       (fboundp sym)
  443.                       (symbol-plist sym)))))))
  444.       (if (or (eq expansion t)
  445.           (string= expansion he-search-string))
  446.           (setq expansion ()))))
  447.  
  448.   (if (not expansion)
  449.       (progn
  450.     (he-reset-string)
  451.     ())
  452.       (progn
  453.     (he-substitute-string expansion)
  454.     (setq he-tried-table (cons expansion he-tried-table))
  455.     t))))
  456.  
  457. (defun he-lisp-symbol-beg ()
  458.   (let ((skips "-a-zA-Z0-9_."))
  459.     (save-excursion
  460.       (skip-chars-backward skips)
  461.       (point))))
  462.  
  463. (defun try-expand-line (old)
  464.   "Try to complete the current line to an entire line in the buffer.
  465. The argument OLD has to be nil the first call of this function, and t
  466. for subsequent calls (for further possible completions of the same
  467. string).  It returns t if a new completion is found, nil otherwise."
  468.   (let ((expansion ())
  469.     (strip-prompt (and (get-buffer-process (current-buffer))
  470.                shell-prompt-pattern)))
  471.     (if (not old)
  472.     (progn
  473.       (he-init-string (he-line-beg strip-prompt) (point))
  474.       (set-marker he-search-loc he-string-beg)
  475.       (setq he-search-bw t)))
  476.  
  477.     (if (not (equal he-search-string ""))
  478.     (save-excursion
  479.       ;; Try looking backward unless inhibited.
  480.       (if he-search-bw
  481.           (progn 
  482.         (goto-char he-search-loc)
  483.         (setq expansion (he-line-search he-search-string
  484.                         strip-prompt t))
  485.         (set-marker he-search-loc (point))
  486.         (if (not expansion)
  487.             (progn
  488.               (set-marker he-search-loc he-string-end)
  489.               (setq he-search-bw ())))))
  490.       
  491.       (if (not expansion) ; Then look forward.
  492.           (progn 
  493.         (goto-char he-search-loc)
  494.         (setq expansion (he-line-search he-search-string 
  495.                         strip-prompt nil))
  496.         (set-marker he-search-loc (point))))))
  497.  
  498.     (if (not expansion)
  499.     (progn
  500.       (he-reset-string)
  501.       ())
  502.     (progn
  503.       (he-substitute-string expansion t)
  504.       (setq he-tried-table (cons expansion he-tried-table))
  505.       t))))
  506.  
  507. (defun try-expand-line-all-buffers (old)
  508.   "Try to complete the current line, searching all other buffers.
  509. The argument OLD has to be nil the first call of this function, and t
  510. for subsequent calls (for further possible completions of the same
  511. string).  It returns t if a new completion is found, nil otherwise."
  512.   (let ((expansion ())
  513.     (strip-prompt (and (get-buffer-process (current-buffer))
  514.                shell-prompt-pattern))
  515.     (buf (current-buffer)))
  516.     (if (not old)
  517.     (progn
  518.       (he-init-string (he-line-beg strip-prompt) (point))
  519.       (setq he-search-bufs (buffer-list))
  520.           (setq he-searched-n-bufs 0)
  521.       (set-marker he-search-loc 1 (car he-search-bufs))))
  522.  
  523.     (if (not (equal he-search-string ""))
  524.     (while (and he-search-bufs 
  525.                     (not expansion)
  526.                     (or (not hippie-expand-max-buffers)
  527.                         (< he-searched-n-bufs hippie-expand-max-buffers)))
  528.       (set-buffer (car he-search-bufs))
  529.       (if (and (not (eq (current-buffer) buf))
  530.                    (not (string-match " \\*Minibuf-[0-9]+\\*"
  531.                                       (buffer-name (current-buffer))))
  532.            (not (eq major-mode 'dired-mode)))
  533.            ;; Dont search minibuffers nor dired buffers
  534.           (save-excursion
  535.         (goto-char he-search-loc)
  536.                 (setq strip-prompt (and (get-buffer-process (current-buffer))
  537.                                         shell-prompt-pattern))
  538.         (setq expansion (he-line-search he-search-string
  539.                         strip-prompt nil))
  540.         (set-marker he-search-loc (point))
  541.                 (if expansion
  542.                     (setq he-tried-table (cons expansion he-tried-table))
  543.                   (setq he-search-bufs (cdr he-search-bufs))
  544.                   (setq he-searched-n-bufs (1+ he-searched-n-bufs))
  545.                   (set-marker he-search-loc 1 (car he-search-bufs))))
  546.             (setq he-search-bufs (cdr he-search-bufs))
  547.             (set-marker he-search-loc 1 (car he-search-bufs)))))
  548.  
  549.     (set-buffer buf)
  550.     (if (not expansion)
  551.     (progn
  552.       (he-reset-string)
  553.       ())
  554.     (progn
  555.       (he-substitute-string expansion t)
  556.       t))))
  557.  
  558. (defun he-line-search (str strip-prompt reverse) 
  559.   (let ((result ()))
  560.     (while (and (not result)
  561.         (if reverse
  562.             (re-search-backward 
  563.              (he-line-search-regexp str strip-prompt)
  564.              nil t)
  565.             (re-search-forward
  566.              (he-line-search-regexp str strip-prompt)
  567.              nil t)))
  568.       (setq result (buffer-substring (match-beginning 2) (match-end 2)))
  569.       (if (he-string-member result he-tried-table)
  570.       (setq result nil)))                ; if already in table, ignore
  571.     result))
  572.  
  573. (defun he-line-beg (strip-prompt)
  574.   (save-excursion
  575.     (end-of-line)
  576.     (if (re-search-backward (he-line-search-regexp "" strip-prompt) 
  577.                 (save-excursion (beginning-of-line)
  578.                         (point)) t)
  579.     (match-beginning 2)
  580.       (beginning-of-line)
  581.       (point))))
  582.  
  583. (defun he-line-search-regexp (pat strip-prompt)
  584.   (if strip-prompt
  585.       (concat "\\(" shell-prompt-pattern "\\|^\\s-*\\)\\("
  586.           (regexp-quote pat)
  587.           "[^\n]*[^ \t\n]\\)")
  588.       (concat "^\\(\\s-*\\)\\(" 
  589.           (regexp-quote pat)
  590.           "[^\n]*[^ \t\n]\\)")))
  591.  
  592. (defun try-expand-all-abbrevs (old)
  593.   "Try to expand word before point according to all abbrev tables.
  594. The argument OLD has to be nil the first call of this function, and t
  595. for subsequent calls (for further possible expansions of the same
  596. string).  It returns t if a new expansion is found, nil otherwise."
  597.   (if (not old)
  598.       (progn
  599.     (he-init-string (he-dabbrev-beg) (point))
  600.     (setq he-expand-list 
  601.           (and (not (equal he-search-string ""))
  602.            (mapcar (function (lambda (sym)
  603.                  (abbrev-expansion (downcase he-search-string)
  604.                            (eval sym))))
  605.                (append '(local-abbrev-table 
  606.                      global-abbrev-table)
  607.                    abbrev-table-name-list))))))
  608.   (while (and he-expand-list
  609.           (or (not (car he-expand-list))
  610.           (he-string-member (car he-expand-list) he-tried-table)))
  611.     (setq he-expand-list (cdr he-expand-list)))
  612.   (if (null he-expand-list)
  613.       (progn
  614.     (he-reset-string)
  615.     ())
  616.       (progn
  617.     (he-substitute-string (car he-expand-list) t)
  618.     (setq he-tried-table (cons (car he-expand-list) he-tried-table))
  619.     (setq he-expand-list (cdr he-expand-list))
  620.     t)))
  621.  
  622. (defun try-expand-dabbrev (old)
  623.   "Try to expand word \"dynamically\", searching the current buffer.
  624. The argument OLD has to be nil the first call of this function, and t
  625. for subsequent calls (for further possible expansions of the same
  626. string).  It returns t if a new expansion is found, nil otherwise."
  627.   (let ((expansion ()))
  628.     (if (not old)
  629.     (progn
  630.       (he-init-string (he-dabbrev-beg) (point))
  631.       (set-marker he-search-loc he-string-beg)
  632.       (setq he-search-bw t)))
  633.  
  634.     (if (not (equal he-search-string ""))
  635.     (save-excursion
  636.       ;; Try looking backward unless inhibited.
  637.       (if he-search-bw
  638.           (progn 
  639.         (goto-char he-search-loc)
  640.         (setq expansion (he-dab-search he-search-string t))
  641.         (set-marker he-search-loc (point))
  642.         (if (not expansion)
  643.             (progn
  644.               (set-marker he-search-loc he-string-end)
  645.               (setq he-search-bw ())))))
  646.       
  647.       (if (not expansion) ; Then look forward.
  648.           (progn 
  649.         (goto-char he-search-loc)
  650.         (setq expansion (he-dab-search he-search-string nil))
  651.         (set-marker he-search-loc (point))))))
  652.     
  653.     (if (not expansion)
  654.     (progn
  655.       (he-reset-string)
  656.       ())
  657.     (progn
  658.       (he-substitute-string expansion t)
  659.       (setq he-tried-table (cons expansion he-tried-table))
  660.       t))))
  661.  
  662. (defun try-expand-dabbrev-all-buffers (old)
  663.   "Tries to expand word \"dynamically\", searching all other buffers.
  664. The argument OLD has to be nil the first call of this function, and t
  665. for subsequent calls (for further possible expansions of the same
  666. string).  It returns t if a new expansion is found, nil otherwise."
  667.   (let ((expansion ())
  668.     (buf (current-buffer)))
  669.     (if (not old)
  670.     (progn
  671.       (he-init-string (he-dabbrev-beg) (point))
  672.       (setq he-search-bufs (buffer-list))
  673.           (setq he-searched-n-bufs 0)
  674.       (set-marker he-search-loc 1 (car he-search-bufs))))
  675.  
  676.     (if (not (equal he-search-string ""))
  677.     (while (and he-search-bufs 
  678.                     (not expansion)
  679.                     (or (not hippie-expand-max-buffers)
  680.                         (< he-searched-n-bufs hippie-expand-max-buffers)))
  681.       (set-buffer (car he-search-bufs))
  682.       (if (and (not (eq (current-buffer) buf))
  683.                    (not (string-match " \\*Minibuf-[0-9]+\\*"
  684.                                       (buffer-name (current-buffer))))
  685.            (not (eq major-mode 'dired-mode)))
  686.            ;; Dont search minibuffers nor dired buffers
  687.           (save-excursion
  688.         (goto-char he-search-loc)
  689.         (setq expansion (he-dab-search he-search-string nil))
  690.         (set-marker he-search-loc (point))
  691.                 (if expansion
  692.                     (setq he-tried-table (cons expansion he-tried-table))
  693.                   (setq he-search-bufs (cdr he-search-bufs))
  694.                   (setq he-searched-n-bufs (1+ he-searched-n-bufs))
  695.                   (set-marker he-search-loc 1 (car he-search-bufs))))
  696.             (setq he-search-bufs (cdr he-search-bufs))
  697.             (set-marker he-search-loc 1 (car he-search-bufs)))))
  698.  
  699.     (set-buffer buf)
  700.     (if (not expansion)
  701.     (progn
  702.       (he-reset-string)
  703.       ())
  704.     (progn
  705.       (he-substitute-string expansion t)
  706.       t))))
  707.  
  708. (defun he-dab-search-regexp (pat)
  709.   (concat "\\b" (regexp-quote pat) 
  710.       "\\(\\sw\\|\\s_\\)+"))
  711.  
  712. (defun he-dab-search (pattern reverse)
  713.   (let ((result ()))
  714.     (while (and (not result) 
  715.         (if reverse
  716.              (re-search-backward (he-dab-search-regexp pattern)
  717.                      nil t)
  718.              (re-search-forward (he-dab-search-regexp pattern)
  719.                     nil t)))
  720.       (setq result (buffer-substring (match-beginning 0) (match-end 0)))
  721.       (if (he-string-member result he-tried-table)
  722.       (setq result nil)))                ; if already in table, ignore
  723.     result))
  724.  
  725. (defun he-dabbrev-beg ()
  726.   (let ((skips "-a-zA-Z0-9_."))
  727.     (save-excursion
  728.       (skip-chars-backward skips)
  729.       (skip-chars-forward "-_.")
  730.       (point))))
  731.  
  732. (run-hooks 'hippie-expand-load-hook)
  733.  
  734.