Merge from trunk
[bpt/emacs.git] / lisp / hippie-exp.el
CommitLineData
e8af40ee 1;;; hippie-exp.el --- expand text trying various ways to find its expansion
3b1e4dd1 2
73b0cd50 3;; Copyright (C) 1992, 2001-2011 Free Software Foundation, Inc.
b578f267 4
3b1e4dd1 5;; Author: Anders Holst <aho@sans.kth.se>
41b8e71c
RS
6;; Last change: 3 March 1998
7;; Version: 1.6
f5f727f8 8;; Keywords: abbrev convenience
3b1e4dd1 9
652304c9
RS
10;; This file is part of GNU Emacs.
11
eb3fa2cf 12;; GNU Emacs is free software: you can redistribute it and/or modify
652304c9 13;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
652304c9
RS
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
eb3fa2cf 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
652304c9 24
76550a57 25;;; Commentary:
b578f267 26
652304c9
RS
27;; `hippie-expand' is a single function for a lot of different kinds
28;; of completions and expansions. Called repeatedly it tries all
c60ee5e7 29;; possible completions in succession.
652304c9
RS
30;; Which kinds of completions to try, and in which order, is
31;; determined by the contents of `hippie-expand-try-functions-list'.
32;; Much customization of `hippie-expand' can be made by changing the
33;; order of, removing, or inserting new functions in this list.
34;; Given a positive numeric argument, `hippie-expand' jumps directly
35;; ARG functions forward in this list. Given some other argument
36;; (a negative argument or just Ctrl-U) it undoes the tried
37;; completion.
d1d1ddbd 38;;
652304c9
RS
39;; If the variable `hippie-expand-verbose' is non-nil, `hippie-expand'
40;; outputs in a message which try-function in the list that is used
41;; currently (ie. was used currently and will be tried first the next
42;; time).
8c6677ed
JB
43;; The variable `hippie-expand-max-buffers' determines in how many
44;; buffers, apart from the current, to search for expansions in. It
45;; is used by the try-functions named "-all-buffers".
d1d1ddbd
RS
46;; The variable `hippie-expand-ignore-buffers' is a list of regexps
47;; matching buffer names (as strings) or major modes (as atoms) of
48;; buffers that should not be searched by the try-functions named
49;; "-all-buffers".
41b8e71c
RS
50;; If set, the variable `hippie-expand-only-buffers' does the opposite
51;; of `hippie-expand-ignore-buffers', in that the search is restricted
52;; to only the kind of buffers listed.
53;; If the variable `hippie-expand-no-restriction' is non-nil, narrowed
54;; buffers are widened before they are searched.
55;; The variable `hippie-expand-dabbrev-skip-space' controls whether
56;; trailing spaces will be included in the abbreviation to search for,
57;; which then gives the same behavior as the original `dabbrev-expand'.
58;; The variable `hippie-expand-dabbrev-as-symbol' controls whether
59;; characters of syntax '_' is considered part of the words to expand
60;; dynamically.
652304c9 61;; See also the macro `make-hippie-expand-function' below.
c60ee5e7 62;;
652304c9
RS
63;; A short description of the current try-functions in this file:
64;; `try-complete-file-name' : very convenient to have in any buffer,
65;; and not just in the minibuffer or (some) shell-mode. It goes
66;; through all possible completions instead of just completing as
67;; much as is unique.
68;; `try-complete-file-name-partially' : To insert in the list just
69;; before `try-complete-file-name' for those who want first to get
70;; a file name completed only as many characters as is unique.
652304c9
RS
71;; `try-expand-all-abbrevs' : can be removed if you don't use abbrevs.
72;; Otherwise it looks through all abbrev-tables, starting with
c60ee5e7
JB
73;; the local followed by the global.
74;; `try-expand-line' : Searches the buffer for an entire line that
75;; begins exactly as the current line. Convenient sometimes, for
652304c9 76;; example as a substitute for (or complement to) the history
8c6677ed 77;; list in shell-like buffers. At other times, only confusing.
652304c9
RS
78;; `try-expand-line-all-buffers' : Like `try-expand-line' but searches
79;; in all buffers (except the current). (This may be a little
8c6677ed
JB
80;; slow, don't use it unless you are really fond of `hippie-expand'.)
81;; `try-expand-list' : Tries to expand the text back to the nearest
f72f0c23
SM
82;; open delimiter, to a whole list from the buffer. Convenient for
83;; example when writing Lisp or TeX.
c60ee5e7
JB
84;; `try-expand-list-all-buffers' : Like `try-expand-list' but searches
85;; in all buffers (except the current).
652304c9
RS
86;; `try-expand-dabbrev' : works exactly as dabbrev-expand (but of
87;; course in a way compatible with the other try-functions).
88;; `try-expand-dabbrev-all-buffers' : perhaps the most useful of them,
89;; like `dabbrev-expand' but searches all Emacs buffers (except the
90;; current) for matching words. (No, I don't find this one
c60ee5e7 91;; particularly slow.)
510cbc92
RS
92;; `try-expand-dabbrev-visible': Searches the currently visible parts of
93;; all windows. Can be put before `try-expand-dabbrev-all-buffers' to
94;; first try the expansions you can see.
95;; `try-expand-dabbrev-from-kill': Searches the kill ring for a suitable
96;; completion of the word. Good to have, just in case the word was not
97;; found elsewhere.
98;; `try-expand-whole-kill' : Tries to complete text with a whole entry
99;; from the kill ring. May be good if you don't know how far up in
100;; the kill-ring the required entry is, and don't want to mess with
101;; "Choose Next Paste".
652304c9
RS
102;; `try-complete-lisp-symbol' : like `lisp-complete-symbol', but goes
103;; through all possibilities instead of completing what is unique.
104;; Might be tedious (usually a lot of possible completions) and
105;; since its function is much like `lisp-complete-symbol', which
106;; already has a key of its own, you might want to remove this.
107;; `try-complete-lisp-symbol-partially' : To insert in the list just
108;; before `try-complete-lisp-symbol' for those who first want to get
c60ee5e7 109;; completion of what is unique in the name.
8c6677ed
JB
110;;
111;; Not all of the above functions are by default in
112;; `hippie-expand-try-functions-list'. This variable is better set
113;; in ".emacs" to make `hippie-expand' behave maximally convenient
114;; according to personal taste. Also, instead of loading the
115;; variable with all kinds of try-functions above, it might be an
116;; idea to use `make-hippie-expand-function' to construct different
117;; `hippie-expand'-like functions, with different try-lists and bound
f72f0c23 118;; to different keys. It is also possible to make
8c6677ed
JB
119;; `hippie-expand-try-functions-list' a buffer local variable, and
120;; let it depend on the mode (by setting it in the mode-hooks).
652304c9
RS
121;;
122;; To write new try-functions, consider the following:
123;; Each try-function takes one argument OLD which is nil the first
124;; time the function is called and true in succeeding calls for the
125;; same string to complete. The first time the function has to
126;; extract the string before point to complete, and substitute the
127;; first completion alternative for it. On following calls it has to
128;; substitute the next possible completion for the last tried string.
129;; The try-function is to return t as long as it finds new
130;; possible completions. When there are no more alternatives it has
131;; to restore the text before point to its original contents, and
132;; return nil (don't beep or message or anything).
133;; The try-function can (should) use the following functions:
134;; `he-init-string' : Initializes the text to substitute to the
135;; contents of the region BEGIN to END. Also sets the variable
136;; `he-search-string' to the text to expand.
137;; `he-substitute-string' : substitutes STR into the region
138;; initialized with `he-init-string'. (An optional second argument
139;; TRANS-CASE non-nil, means transfer of case from the abbreviation
140;; to the expansion is ok if that is enabled in the buffer.)
141;; `he-reset-string' : Resets the initialized region to its original
142;; contents.
143;; There is also a variable: `he-tried-table' which is meant to contain
c60ee5e7 144;; all tried expansions so far. The try-function can check this
652304c9 145;; variable to see whether an expansion has already been tried
510cbc92 146;; (hint: `he-string-member').
652304c9 147;;
8c6677ed 148;; Known bugs
652304c9
RS
149;;
150;; It may happen that some completion suggestion occurs twice, in
c60ee5e7 151;; spite of the use of `he-tried-table' to prevent that. This is
652304c9
RS
152;; because different try-functions may try to complete different
153;; lengths of text, and thus put different amounts of the
510cbc92
RS
154;; text in `he-tried-table'. Anyway this seems to occur seldom enough
155;; not to be too disturbing. Also it should NOT be possible for the
652304c9
RS
156;; opposite situation to occur, that `hippie-expand' misses some
157;; suggestion because it thinks it has already tried it.
158;;
8c6677ed 159;; Acknowledgement
652304c9
RS
160;;
161;; I want to thank Mikael Djurfeldt in discussions with whom the idea
162;; of this function took form.
163;; I am also grateful to all those who have given me suggestions on
510cbc92 164;; how to improve it, and all those who helped to find and remove bugs.
652304c9
RS
165;;
166
76550a57 167;;; Code:
652304c9 168
6df53d08 169(require 'comint)
ddb6e2e2 170
94114394
RS
171(defgroup hippie-expand nil
172 "Expand text trying various ways to find its expansion."
ddb6e2e2
DL
173 :link '(custom-manual "(autotype)Hippie Expand")
174 :link '(emacs-commentary-link "hippie-exp")
f5f727f8
DN
175 :group 'abbrev
176 :group 'convenience)
94114394 177
652304c9
RS
178(defvar he-num -1)
179
8c6677ed 180(defvar he-string-beg (make-marker))
652304c9 181
8c6677ed 182(defvar he-string-end (make-marker))
652304c9
RS
183
184(defvar he-search-string ())
185
186(defvar he-expand-list ())
187
188(defvar he-tried-table ())
189
8c6677ed 190(defvar he-search-loc (make-marker))
652304c9 191
510cbc92
RS
192(defvar he-search-loc2 ())
193
652304c9
RS
194(defvar he-search-bw ())
195
196(defvar he-search-bufs ())
197
8c6677ed
JB
198(defvar he-searched-n-bufs ())
199
510cbc92
RS
200(defvar he-search-window ())
201
8c6677ed 202;;;###autoload
ddb6e2e2
DL
203(defcustom hippie-expand-try-functions-list
204 '(try-complete-file-name-partially
205 try-complete-file-name
206 try-expand-all-abbrevs
207 try-expand-list
208 try-expand-line
209 try-expand-dabbrev
210 try-expand-dabbrev-all-buffers
211 try-expand-dabbrev-from-kill
212 try-complete-lisp-symbol-partially
213 try-complete-lisp-symbol)
652304c9
RS
214 "The list of expansion functions tried in order by `hippie-expand'.
215To change the behavior of `hippie-expand', remove, change the order of,
ddb6e2e2
DL
216or insert functions in this list."
217 :type '(repeat function)
218 :group 'hippie-expand)
652304c9 219
8c6677ed 220;;;###autoload
94114394 221(defcustom hippie-expand-verbose t
9201cc28 222 "Non-nil makes `hippie-expand' output which function it is trying."
94114394
RS
223 :type 'boolean
224 :group 'hippie-expand)
652304c9 225
41b8e71c
RS
226;;;###autoload
227(defcustom hippie-expand-dabbrev-skip-space nil
9201cc28 228 "Non-nil means tolerate trailing spaces in the abbreviation to expand."
41b8e71c
RS
229 :group 'hippie-expand
230 :type 'boolean)
231
232;;;###autoload
233(defcustom hippie-expand-dabbrev-as-symbol t
9201cc28 234 "Non-nil means expand as symbols, i.e. syntax `_' is considered a letter."
41b8e71c
RS
235 :group 'hippie-expand
236 :type 'boolean)
237
238;;;###autoload
239(defcustom hippie-expand-no-restriction t
9201cc28 240 "Non-nil means that narrowed buffers are widened during search."
41b8e71c
RS
241 :group 'hippie-expand
242 :type 'boolean)
243
8c6677ed 244;;;###autoload
94114394 245(defcustom hippie-expand-max-buffers ()
9201cc28 246 "The maximum number of buffers (apart from the current) searched.
94114394
RS
247If nil, all buffers are searched."
248 :type '(choice (const :tag "All" nil)
249 integer)
250 :group 'hippie-expand)
8c6677ed 251
d1d1ddbd 252;;;###autoload
6bdad9ae 253(defcustom hippie-expand-ignore-buffers (list (purecopy "^ \\*.*\\*$") 'dired-mode)
9201cc28 254 "A list specifying which buffers not to search (if not current).
d1d1ddbd 255Can contain both regexps matching buffer names (as strings) and major modes
94114394
RS
256\(as atoms)"
257 :type '(repeat (choice regexp (symbol :tag "Major Mode")))
258 :group 'hippie-expand)
d1d1ddbd 259
41b8e71c
RS
260;;;###autoload
261(defcustom hippie-expand-only-buffers ()
9201cc28 262 "A list specifying the only buffers to search (in addition to current).
41b8e71c 263Can contain both regexps matching buffer names (as strings) and major modes
0ff9b955 264\(as atoms). If non-nil, this variable overrides the variable
41b8e71c
RS
265`hippie-expand-ignore-buffers'."
266 :type '(repeat (choice regexp (symbol :tag "Major Mode")))
267 :group 'hippie-expand)
268
8c6677ed 269;;;###autoload
652304c9
RS
270(defun hippie-expand (arg)
271 "Try to expand text before point, using multiple methods.
272The expansion functions in `hippie-expand-try-functions-list' are
273tried in order, until a possible expansion is found. Repeated
274application of `hippie-expand' inserts successively possible
c60ee5e7 275expansions.
652304c9 276With a positive numeric argument, jumps directly to the ARG next
c60ee5e7
JB
277function in this list. With a negative argument or just \\[universal-argument],
278undoes the expansion."
652304c9 279 (interactive "P")
c60ee5e7 280 (if (or (not arg)
652304c9
RS
281 (and (integerp arg) (> arg 0)))
282 (let ((first (or (= he-num -1)
283 (not (equal this-command last-command)))))
284 (if first
285 (progn
286 (setq he-num -1)
287 (setq he-tried-table nil)))
288 (if arg
289 (if (not first) (he-reset-string))
290 (setq arg 0))
291 (let ((i (max (+ he-num arg) 0)))
292 (while (not (or (>= i (length hippie-expand-try-functions-list))
c60ee5e7 293 (apply (nth i hippie-expand-try-functions-list)
652304c9
RS
294 (list (= he-num i)))))
295 (setq i (1+ i)))
296 (setq he-num i))
297 (if (>= he-num (length hippie-expand-try-functions-list))
298 (progn
299 (setq he-num -1)
300 (if first
301 (message "No expansion found")
302 (message "No further expansions found"))
303 (ding))
8c6677ed 304 (if (and hippie-expand-verbose
510cbc92 305 (not (window-minibuffer-p (selected-window))))
32561aba 306 (message "Using %s"
41b8e71c 307 (nth he-num hippie-expand-try-functions-list)))))
510cbc92
RS
308 (if (and (>= he-num 0)
309 (eq (marker-buffer he-string-beg) (current-buffer)))
652304c9
RS
310 (progn
311 (setq he-num -1)
312 (he-reset-string)
8c6677ed 313 (if (and hippie-expand-verbose
510cbc92 314 (not (window-minibuffer-p (selected-window))))
652304c9 315 (message "Undoing expansions"))))))
8c6677ed 316
652304c9
RS
317;; Initializes the region to expand (to between BEG and END).
318(defun he-init-string (beg end)
8c6677ed
JB
319 (set-marker he-string-beg beg)
320 (set-marker he-string-end end)
41b8e71c 321 (setq he-search-string (buffer-substring-no-properties beg end)))
652304c9
RS
322
323;; Resets the expanded region to its original contents.
324(defun he-reset-string ()
8c6677ed 325 (let ((newpos (point-marker)))
8c6677ed
JB
326 (goto-char he-string-beg)
327 (insert he-search-string)
510cbc92
RS
328 (delete-region (point) he-string-end)
329 (goto-char newpos)))
652304c9
RS
330
331;; Substitutes an expansion STR into the correct region (the region
c60ee5e7 332;; initialized with `he-init-string').
652304c9
RS
333;; An optional argument TRANS-CASE means that it is ok to transfer case
334;; from the abbreviation to the expansion if that is possible, and is
335;; enabled in the buffer.
336(defun he-substitute-string (str &optional trans-case)
337 (let ((trans-case (and trans-case
338 case-replace
510cbc92
RS
339 case-fold-search))
340 (newpos (point-marker))
341 (subst ()))
652304c9 342 (goto-char he-string-beg)
510cbc92
RS
343 (setq subst (if trans-case (he-transfer-case he-search-string str) str))
344 (setq he-tried-table (cons subst he-tried-table))
345 (insert subst)
346 (delete-region (point) he-string-end)
347 (goto-char newpos)))
348
349(defun he-capitalize-first (str)
350 (save-match-data
351 (if (string-match "\\Sw*\\(\\sw\\).*" str)
352 (let ((res (downcase str))
353 (no (match-beginning 1)))
354 (aset res no (upcase (aref str no)))
355 res)
356 str)))
652304c9
RS
357
358(defun he-ordinary-case-p (str)
359 (or (string= str (downcase str))
360 (string= str (upcase str))
510cbc92
RS
361 (string= str (capitalize str))
362 (string= str (he-capitalize-first str))))
363
364(defun he-transfer-case (from-str to-str)
365 (cond ((string= from-str (substring to-str 0 (min (length from-str)
366 (length to-str))))
367 to-str)
368 ((not (he-ordinary-case-p to-str))
8d392c8e 369 to-str)
510cbc92
RS
370 ((string= from-str (downcase from-str))
371 (downcase to-str))
372 ((string= from-str (upcase from-str))
373 (upcase to-str))
374 ((string= from-str (he-capitalize-first from-str))
375 (he-capitalize-first to-str))
376 ((string= from-str (capitalize from-str))
377 (capitalize to-str))
378 (t
379 to-str)))
380
652304c9
RS
381
382;; Check if STR is a member of LST.
0ff9b955 383;; Transform to the final case if optional TRANS-CASE is non-nil.
510cbc92
RS
384(defun he-string-member (str lst &optional trans-case)
385 (if str
386 (member (if (and trans-case
387 case-replace
388 case-fold-search)
389 (he-transfer-case he-search-string str)
390 str)
391 lst)))
652304c9 392
41b8e71c
RS
393;; Check if current buffer matches any atom or regexp in LST.
394;; Atoms are interpreted as major modes, strings as regexps mathing the name.
395(defun he-buffer-member (lst)
396 (or (memq major-mode lst)
397 (progn
398 (while (and lst
399 (or (not (stringp (car lst)))
400 (not (string-match (car lst) (buffer-name)))))
401 (setq lst (cdr lst)))
402 lst)))
d1d1ddbd 403
652304c9
RS
404;; For the real hippie-expand enthusiast: A macro that makes it
405;; possible to use many functions like hippie-expand, but with
406;; different try-functions-lists.
407;; Usage is for example:
408;; (fset 'my-complete-file (make-hippie-expand-function
409;; '(try-complete-file-name-partially
410;; try-complete-file-name)))
411;; (fset 'my-complete-line (make-hippie-expand-function
412;; '(try-expand-line
413;; try-expand-line-all-buffers)))
c60ee5e7 414;;
8c6677ed 415;;;###autoload
652304c9
RS
416(defmacro make-hippie-expand-function (try-list &optional verbose)
417 "Construct a function similar to `hippie-expand'.
418Make it use the expansion functions in TRY-LIST. An optional second
419argument VERBOSE non-nil makes the function verbose."
d7d20e6a 420 `(function (lambda (arg)
c60ee5e7 421 ,(concat
d7d20e6a
GM
422 "Try to expand text before point, using the following functions: \n"
423 (mapconcat 'prin1-to-string (eval try-list) ", "))
424 (interactive "P")
425 (let ((hippie-expand-try-functions-list ,try-list)
426 (hippie-expand-verbose ,verbose))
427 (hippie-expand arg)))))
652304c9
RS
428
429
430;;; Here follows the try-functions and their requisites:
431
510cbc92 432
652304c9
RS
433(defun try-complete-file-name (old)
434 "Try to complete text as a file name.
435The argument OLD has to be nil the first call of this function, and t
436for subsequent calls (for further possible completions of the same
437string). It returns t if a new completion is found, nil otherwise."
438 (if (not old)
c60ee5e7 439 (progn
652304c9 440 (he-init-string (he-file-name-beg) (point))
7c2fb837
DN
441 (let ((name-part (file-name-nondirectory he-search-string))
442 (dir-part (expand-file-name (or (file-name-directory
652304c9
RS
443 he-search-string) ""))))
444 (if (not (he-string-member name-part he-tried-table))
445 (setq he-tried-table (cons name-part he-tried-table)))
446 (if (and (not (equal he-search-string ""))
7c2fb837 447 (file-directory-p dir-part))
c60ee5e7 448 (setq he-expand-list (sort (file-name-all-completions
652304c9
RS
449 name-part
450 dir-part)
451 'string-lessp))
452 (setq he-expand-list ())))))
453
454 (while (and he-expand-list
455 (he-string-member (car he-expand-list) he-tried-table))
456 (setq he-expand-list (cdr he-expand-list)))
457 (if (null he-expand-list)
458 (progn
510cbc92 459 (if old (he-reset-string))
652304c9 460 ())
510cbc92 461 (let ((filename (he-concat-directory-file-name
7c2fb837 462 (file-name-directory he-search-string)
510cbc92 463 (car he-expand-list))))
652304c9 464 (he-substitute-string filename)
510cbc92 465 (setq he-tried-table (cons (car he-expand-list) (cdr he-tried-table)))
652304c9
RS
466 (setq he-expand-list (cdr he-expand-list))
467 t)))
468
469(defun try-complete-file-name-partially (old)
470 "Try to complete text as a file name, as many characters as unique.
471The argument OLD has to be nil the first call of this function. It
c60ee5e7 472returns t if a unique, possibly partial, completion is found, nil
652304c9
RS
473otherwise."
474 (let ((expansion ()))
475 (if (not old)
c60ee5e7 476 (progn
652304c9 477 (he-init-string (he-file-name-beg) (point))
7c2fb837
DN
478 (let ((name-part (file-name-nondirectory he-search-string))
479 (dir-part (expand-file-name (or (file-name-directory
652304c9
RS
480 he-search-string) ""))))
481 (if (and (not (equal he-search-string ""))
7c2fb837 482 (file-directory-p dir-part))
652304c9
RS
483 (setq expansion (file-name-completion name-part
484 dir-part)))
485 (if (or (eq expansion t)
510cbc92
RS
486 (string= expansion name-part)
487 (he-string-member expansion he-tried-table))
652304c9
RS
488 (setq expansion ())))))
489
490 (if (not expansion)
491 (progn
510cbc92 492 (if old (he-reset-string))
652304c9 493 ())
510cbc92 494 (let ((filename (he-concat-directory-file-name
7c2fb837 495 (file-name-directory he-search-string)
510cbc92 496 expansion)))
652304c9 497 (he-substitute-string filename)
510cbc92 498 (setq he-tried-table (cons expansion (cdr he-tried-table)))
652304c9
RS
499 t))))
500
510cbc92 501(defvar he-file-name-chars
7c2fb837 502 (cond ((memq system-type '(ms-dos windows-nt cygwin))
510cbc92
RS
503 "-a-zA-Z0-9_/.,~^#$+=:\\\\")
504 (t ;; More strange file formats ?
505 "-a-zA-Z0-9_/.,~^#$+="))
506 "Characters that are considered part of the file name to expand.")
507
652304c9 508(defun he-file-name-beg ()
de073e06
KH
509 (let ((op (point)))
510 (save-excursion
511 (skip-chars-backward he-file-name-chars)
512 (if (> (skip-syntax-backward "w") 0) ;; No words with non-file chars
41b8e71c
RS
513 op
514 (point)))))
652304c9 515
7c2fb837 516;; Thanks go to David Hughes <ukchugd@ukpmr.cs.philips.nl> who
510cbc92 517;; helped to make it work on PC.
510cbc92
RS
518(defun he-concat-directory-file-name (dir-part name-part)
519 "Try to slam together two parts of a file specification, system dependently."
a0341d13 520 (cond ((null dir-part) name-part)
a3374680 521 ((eq system-type 'ms-dos)
510cbc92
RS
522 (if (and (string-match "\\\\" dir-part)
523 (not (string-match "/" dir-part))
524 (= (aref name-part (1- (length name-part))) ?/))
525 (aset name-part (1- (length name-part)) ?\\))
526 (concat dir-part name-part))
c60ee5e7 527 (t
510cbc92 528 (concat dir-part name-part))))
c60ee5e7 529
652304c9
RS
530(defun try-complete-lisp-symbol (old)
531 "Try to complete word as an Emacs Lisp symbol.
532The argument OLD has to be nil the first call of this function, and t
533for subsequent calls (for further possible completions of the same
534string). It returns t if a new completion is found, nil otherwise."
535 (if (not old)
c60ee5e7 536 (progn
652304c9
RS
537 (he-init-string (he-lisp-symbol-beg) (point))
538 (if (not (he-string-member he-search-string he-tried-table))
539 (setq he-tried-table (cons he-search-string he-tried-table)))
c60ee5e7 540 (setq he-expand-list
652304c9
RS
541 (and (not (equal he-search-string ""))
542 (sort (all-completions he-search-string obarray
543 (function (lambda (sym)
544 (or (boundp sym)
545 (fboundp sym)
546 (symbol-plist sym)))))
547 'string-lessp)))))
548 (while (and he-expand-list
549 (he-string-member (car he-expand-list) he-tried-table))
550 (setq he-expand-list (cdr he-expand-list)))
551 (if (null he-expand-list)
552 (progn
510cbc92 553 (if old (he-reset-string))
652304c9
RS
554 ())
555 (progn
556 (he-substitute-string (car he-expand-list))
652304c9
RS
557 (setq he-expand-list (cdr he-expand-list))
558 t)))
559
560(defun try-complete-lisp-symbol-partially (old)
561 "Try to complete as an Emacs Lisp symbol, as many characters as unique.
562The argument OLD has to be nil the first call of this function. It
c60ee5e7 563returns t if a unique, possibly partial, completion is found, nil
652304c9
RS
564otherwise."
565 (let ((expansion ()))
566 (if (not old)
c60ee5e7 567 (progn
652304c9
RS
568 (he-init-string (he-lisp-symbol-beg) (point))
569 (if (not (string= he-search-string ""))
c60ee5e7 570 (setq expansion
652304c9
RS
571 (try-completion he-search-string obarray
572 (function (lambda (sym)
573 (or (boundp sym)
574 (fboundp sym)
575 (symbol-plist sym)))))))
576 (if (or (eq expansion t)
510cbc92
RS
577 (string= expansion he-search-string)
578 (he-string-member expansion he-tried-table))
652304c9
RS
579 (setq expansion ()))))
580
581 (if (not expansion)
582 (progn
510cbc92 583 (if old (he-reset-string))
652304c9
RS
584 ())
585 (progn
586 (he-substitute-string expansion)
652304c9
RS
587 t))))
588
589(defun he-lisp-symbol-beg ()
de073e06
KH
590 (save-excursion
591 (skip-syntax-backward "w_")
592 (point)))
652304c9
RS
593
594(defun try-expand-line (old)
595 "Try to complete the current line to an entire line in the buffer.
596The argument OLD has to be nil the first call of this function, and t
597for subsequent calls (for further possible completions of the same
598string). It returns t if a new completion is found, nil otherwise."
599 (let ((expansion ())
600 (strip-prompt (and (get-buffer-process (current-buffer))
d7210472 601 comint-use-prompt-regexp
8c6677ed 602 comint-prompt-regexp)))
652304c9
RS
603 (if (not old)
604 (progn
605 (he-init-string (he-line-beg strip-prompt) (point))
8c6677ed 606 (set-marker he-search-loc he-string-beg)
652304c9
RS
607 (setq he-search-bw t)))
608
609 (if (not (equal he-search-string ""))
610 (save-excursion
41b8e71c
RS
611 (save-restriction
612 (if hippie-expand-no-restriction
613 (widen))
614 ;; Try looking backward unless inhibited.
615 (if he-search-bw
c60ee5e7 616 (progn
41b8e71c
RS
617 (goto-char he-search-loc)
618 (setq expansion (he-line-search he-search-string
619 strip-prompt t))
620 (set-marker he-search-loc (point))
621 (if (not expansion)
622 (progn
623 (set-marker he-search-loc he-string-end)
624 (setq he-search-bw ())))))
625
626 (if (not expansion) ; Then look forward.
c60ee5e7 627 (progn
41b8e71c 628 (goto-char he-search-loc)
c60ee5e7 629 (setq expansion (he-line-search he-search-string
41b8e71c
RS
630 strip-prompt nil))
631 (set-marker he-search-loc (point)))))))
652304c9
RS
632
633 (if (not expansion)
634 (progn
510cbc92 635 (if old (he-reset-string))
652304c9
RS
636 ())
637 (progn
638 (he-substitute-string expansion t)
652304c9
RS
639 t))))
640
641(defun try-expand-line-all-buffers (old)
642 "Try to complete the current line, searching all other buffers.
643The argument OLD has to be nil the first call of this function, and t
644for subsequent calls (for further possible completions of the same
645string). It returns t if a new completion is found, nil otherwise."
646 (let ((expansion ())
647 (strip-prompt (and (get-buffer-process (current-buffer))
d7210472 648 comint-use-prompt-regexp
8c6677ed 649 comint-prompt-regexp))
510cbc92
RS
650 (buf (current-buffer))
651 (orig-case-fold-search case-fold-search))
652304c9
RS
652 (if (not old)
653 (progn
654 (he-init-string (he-line-beg strip-prompt) (point))
8c6677ed 655 (setq he-search-bufs (buffer-list))
510cbc92 656 (setq he-searched-n-bufs 0)
8c6677ed 657 (set-marker he-search-loc 1 (car he-search-bufs))))
652304c9
RS
658
659 (if (not (equal he-search-string ""))
c60ee5e7 660 (while (and he-search-bufs
510cbc92
RS
661 (not expansion)
662 (or (not hippie-expand-max-buffers)
663 (< he-searched-n-bufs hippie-expand-max-buffers)))
652304c9
RS
664 (set-buffer (car he-search-bufs))
665 (if (and (not (eq (current-buffer) buf))
41b8e71c
RS
666 (if hippie-expand-only-buffers
667 (he-buffer-member hippie-expand-only-buffers)
668 (not (he-buffer-member hippie-expand-ignore-buffers))))
652304c9 669 (save-excursion
41b8e71c
RS
670 (save-restriction
671 (if hippie-expand-no-restriction
672 (widen))
673 (goto-char he-search-loc)
674 (setq strip-prompt (and (get-buffer-process (current-buffer))
d7210472 675 comint-use-prompt-regexp
41b8e71c 676 comint-prompt-regexp))
c60ee5e7 677 (setq expansion
41b8e71c
RS
678 (let ((case-fold-search orig-case-fold-search))
679 (he-line-search he-search-string
680 strip-prompt nil)))
681 (set-marker he-search-loc (point))
682 (if (not expansion)
683 (progn
684 (setq he-search-bufs (cdr he-search-bufs))
685 (setq he-searched-n-bufs (1+ he-searched-n-bufs))
686 (set-marker he-search-loc 1 (car he-search-bufs))))))
510cbc92
RS
687 (setq he-search-bufs (cdr he-search-bufs))
688 (set-marker he-search-loc 1 (car he-search-bufs)))))
652304c9
RS
689
690 (set-buffer buf)
691 (if (not expansion)
692 (progn
510cbc92 693 (if old (he-reset-string))
652304c9
RS
694 ())
695 (progn
696 (he-substitute-string expansion t)
697 t))))
698
c60ee5e7 699(defun he-line-search (str strip-prompt reverse)
652304c9
RS
700 (let ((result ()))
701 (while (and (not result)
702 (if reverse
c60ee5e7 703 (re-search-backward
652304c9
RS
704 (he-line-search-regexp str strip-prompt)
705 nil t)
706 (re-search-forward
707 (he-line-search-regexp str strip-prompt)
708 nil t)))
d7d20e6a
GM
709 (setq result (buffer-substring-no-properties (match-end 1)
710 (match-end 0)))
510cbc92
RS
711 (if (he-string-member result he-tried-table t)
712 (setq result nil))) ; if already in table, ignore
652304c9
RS
713 result))
714
715(defun he-line-beg (strip-prompt)
716 (save-excursion
c60ee5e7 717 (if (re-search-backward (he-line-search-regexp "" strip-prompt)
9b026d9f 718 (line-beginning-position) t)
652304c9 719 (match-beginning 2)
652304c9
RS
720 (point))))
721
722(defun he-line-search-regexp (pat strip-prompt)
723 (if strip-prompt
8c6677ed 724 (concat "\\(" comint-prompt-regexp "\\|^\\s-*\\)\\("
652304c9
RS
725 (regexp-quote pat)
726 "[^\n]*[^ \t\n]\\)")
c60ee5e7 727 (concat "^\\(\\s-*\\)\\("
652304c9
RS
728 (regexp-quote pat)
729 "[^\n]*[^ \t\n]\\)")))
730
8c6677ed
JB
731(defun try-expand-list (old)
732 "Try to complete the current beginning of a list.
733The argument OLD has to be nil the first call of this function, and t
734for subsequent calls (for further possible completions of the same
735string). It returns t if a new completion is found, nil otherwise."
736 (let ((expansion ()))
737 (if (not old)
738 (progn
739 (he-init-string (he-list-beg) (point))
740 (set-marker he-search-loc he-string-beg)
741 (setq he-search-bw t)))
742
743 (if (not (equal he-search-string ""))
744 (save-excursion
41b8e71c
RS
745 (save-restriction
746 (if hippie-expand-no-restriction
747 (widen))
748 ;; Try looking backward unless inhibited.
749 (if he-search-bw
c60ee5e7 750 (progn
41b8e71c
RS
751 (goto-char he-search-loc)
752 (setq expansion (he-list-search he-search-string t))
753 (set-marker he-search-loc (point))
754 (if (not expansion)
755 (progn
756 (set-marker he-search-loc he-string-end)
757 (setq he-search-bw ())))))
758
759 (if (not expansion) ; Then look forward.
c60ee5e7 760 (progn
41b8e71c
RS
761 (goto-char he-search-loc)
762 (setq expansion (he-list-search he-search-string nil))
763 (set-marker he-search-loc (point)))))))
8c6677ed
JB
764
765 (if (not expansion)
766 (progn
767 (if old (he-reset-string))
768 ())
769 (progn
770 (he-substitute-string expansion t)
8c6677ed
JB
771 t))))
772
773(defun try-expand-list-all-buffers (old)
774 "Try to complete the current list, searching all other buffers.
775The argument OLD has to be nil the first call of this function, and t
776for subsequent calls (for further possible completions of the same
777string). It returns t if a new completion is found, nil otherwise."
778 (let ((expansion ())
510cbc92
RS
779 (buf (current-buffer))
780 (orig-case-fold-search case-fold-search))
8c6677ed
JB
781 (if (not old)
782 (progn
783 (he-init-string (he-list-beg) (point))
784 (setq he-search-bufs (buffer-list))
510cbc92 785 (setq he-searched-n-bufs 0)
8c6677ed
JB
786 (set-marker he-search-loc 1 (car he-search-bufs))))
787
788 (if (not (equal he-search-string ""))
c60ee5e7 789 (while (and he-search-bufs
510cbc92
RS
790 (not expansion)
791 (or (not hippie-expand-max-buffers)
792 (< he-searched-n-bufs hippie-expand-max-buffers)))
8c6677ed
JB
793 (set-buffer (car he-search-bufs))
794 (if (and (not (eq (current-buffer) buf))
41b8e71c
RS
795 (if hippie-expand-only-buffers
796 (he-buffer-member hippie-expand-only-buffers)
797 (not (he-buffer-member hippie-expand-ignore-buffers))))
8c6677ed 798 (save-excursion
41b8e71c
RS
799 (save-restriction
800 (if hippie-expand-no-restriction
801 (widen))
802 (goto-char he-search-loc)
c60ee5e7 803 (setq expansion
41b8e71c
RS
804 (let ((case-fold-search orig-case-fold-search))
805 (he-list-search he-search-string nil)))
806 (set-marker he-search-loc (point))
807 (if (not expansion)
808 (progn
809 (setq he-search-bufs (cdr he-search-bufs))
810 (setq he-searched-n-bufs (1+ he-searched-n-bufs))
811 (set-marker he-search-loc 1 (car he-search-bufs))))))
510cbc92
RS
812 (setq he-search-bufs (cdr he-search-bufs))
813 (set-marker he-search-loc 1 (car he-search-bufs)))))
8c6677ed
JB
814
815 (set-buffer buf)
816 (if (not expansion)
817 (progn
510cbc92 818 (if old (he-reset-string))
8c6677ed
JB
819 ())
820 (progn
821 (he-substitute-string expansion t)
822 t))))
823
c60ee5e7 824(defun he-list-search (str reverse)
8c6677ed 825 (let ((result ())
510cbc92 826 beg pos err)
8c6677ed
JB
827 (while (and (not result)
828 (if reverse
829 (search-backward str nil t)
830 (search-forward str nil t)))
831 (setq pos (point))
832 (setq beg (match-beginning 0))
833 (goto-char beg)
834 (setq err ())
835 (condition-case ()
510cbc92
RS
836 (forward-list 1)
837 (error (setq err t)))
c60ee5e7 838 (if (and reverse
510cbc92
RS
839 (> (point) he-string-beg))
840 (setq err t))
8c6677ed 841 (if (not err)
510cbc92 842 (progn
41b8e71c 843 (setq result (buffer-substring-no-properties beg (point)))
510cbc92
RS
844 (if (he-string-member result he-tried-table t)
845 (setq result nil)))) ; if already in table, ignore
8c6677ed
JB
846 (goto-char pos))
847 result))
848
849(defun he-list-beg ()
850 (save-excursion
851 (condition-case ()
510cbc92 852 (backward-up-list 1)
8c6677ed
JB
853 (error ()))
854 (point)))
855
652304c9
RS
856(defun try-expand-all-abbrevs (old)
857 "Try to expand word before point according to all abbrev tables.
858The argument OLD has to be nil the first call of this function, and t
859for subsequent calls (for further possible expansions of the same
860string). It returns t if a new expansion is found, nil otherwise."
861 (if (not old)
862 (progn
863 (he-init-string (he-dabbrev-beg) (point))
c60ee5e7 864 (setq he-expand-list
652304c9
RS
865 (and (not (equal he-search-string ""))
866 (mapcar (function (lambda (sym)
510cbc92
RS
867 (if (and (boundp sym) (vectorp (eval sym)))
868 (abbrev-expansion (downcase he-search-string)
869 (eval sym)))))
c60ee5e7 870 (append '(local-abbrev-table
652304c9
RS
871 global-abbrev-table)
872 abbrev-table-name-list))))))
873 (while (and he-expand-list
874 (or (not (car he-expand-list))
510cbc92 875 (he-string-member (car he-expand-list) he-tried-table t)))
652304c9
RS
876 (setq he-expand-list (cdr he-expand-list)))
877 (if (null he-expand-list)
878 (progn
510cbc92 879 (if old (he-reset-string))
652304c9
RS
880 ())
881 (progn
8c6677ed 882 (he-substitute-string (car he-expand-list) t)
652304c9
RS
883 (setq he-expand-list (cdr he-expand-list))
884 t)))
885
886(defun try-expand-dabbrev (old)
887 "Try to expand word \"dynamically\", searching the current buffer.
888The argument OLD has to be nil the first call of this function, and t
889for subsequent calls (for further possible expansions of the same
890string). It returns t if a new expansion is found, nil otherwise."
891 (let ((expansion ()))
892 (if (not old)
893 (progn
894 (he-init-string (he-dabbrev-beg) (point))
8c6677ed 895 (set-marker he-search-loc he-string-beg)
652304c9
RS
896 (setq he-search-bw t)))
897
898 (if (not (equal he-search-string ""))
899 (save-excursion
41b8e71c
RS
900 (save-restriction
901 (if hippie-expand-no-restriction
902 (widen))
903 ;; Try looking backward unless inhibited.
904 (if he-search-bw
c60ee5e7 905 (progn
41b8e71c
RS
906 (goto-char he-search-loc)
907 (setq expansion (he-dabbrev-search he-search-string t))
908 (set-marker he-search-loc (point))
909 (if (not expansion)
910 (progn
911 (set-marker he-search-loc he-string-end)
912 (setq he-search-bw ())))))
913
914 (if (not expansion) ; Then look forward.
c60ee5e7 915 (progn
41b8e71c
RS
916 (goto-char he-search-loc)
917 (setq expansion (he-dabbrev-search he-search-string nil))
918 (set-marker he-search-loc (point)))))))
c60ee5e7 919
652304c9
RS
920 (if (not expansion)
921 (progn
510cbc92 922 (if old (he-reset-string))
652304c9
RS
923 ())
924 (progn
925 (he-substitute-string expansion t)
652304c9
RS
926 t))))
927
928(defun try-expand-dabbrev-all-buffers (old)
f72f0c23 929 "Try to expand word \"dynamically\", searching all other buffers.
652304c9
RS
930The argument OLD has to be nil the first call of this function, and t
931for subsequent calls (for further possible expansions of the same
932string). It returns t if a new expansion is found, nil otherwise."
933 (let ((expansion ())
510cbc92
RS
934 (buf (current-buffer))
935 (orig-case-fold-search case-fold-search))
652304c9
RS
936 (if (not old)
937 (progn
938 (he-init-string (he-dabbrev-beg) (point))
8c6677ed 939 (setq he-search-bufs (buffer-list))
510cbc92 940 (setq he-searched-n-bufs 0)
8c6677ed 941 (set-marker he-search-loc 1 (car he-search-bufs))))
652304c9
RS
942
943 (if (not (equal he-search-string ""))
c60ee5e7 944 (while (and he-search-bufs
510cbc92
RS
945 (not expansion)
946 (or (not hippie-expand-max-buffers)
947 (< he-searched-n-bufs hippie-expand-max-buffers)))
652304c9
RS
948 (set-buffer (car he-search-bufs))
949 (if (and (not (eq (current-buffer) buf))
41b8e71c
RS
950 (if hippie-expand-only-buffers
951 (he-buffer-member hippie-expand-only-buffers)
952 (not (he-buffer-member hippie-expand-ignore-buffers))))
652304c9 953 (save-excursion
41b8e71c
RS
954 (save-restriction
955 (if hippie-expand-no-restriction
956 (widen))
957 (goto-char he-search-loc)
958 (setq expansion
959 (let ((case-fold-search orig-case-fold-search))
960 (he-dabbrev-search he-search-string nil)))
961 (set-marker he-search-loc (point))
962 (if (not expansion)
963 (progn
964 (setq he-search-bufs (cdr he-search-bufs))
965 (setq he-searched-n-bufs (1+ he-searched-n-bufs))
966 (set-marker he-search-loc 1 (car he-search-bufs))))))
510cbc92
RS
967 (setq he-search-bufs (cdr he-search-bufs))
968 (set-marker he-search-loc 1 (car he-search-bufs)))))
652304c9
RS
969
970 (set-buffer buf)
971 (if (not expansion)
972 (progn
510cbc92 973 (if old (he-reset-string))
652304c9
RS
974 ())
975 (progn
976 (he-substitute-string expansion t)
977 t))))
978
510cbc92
RS
979;; Thanks go to Jeff Dairiki <dairiki@faraday.apl.washington.edu> who
980;; suggested this one.
981(defun try-expand-dabbrev-visible (old)
982 "Try to expand word \"dynamically\", searching visible window parts.
983The argument OLD has to be nil the first call of this function, and t
984for subsequent calls (for further possible expansions of the same
985string). It returns t if a new expansion is found, nil otherwise."
986 (let ((expansion ())
510cbc92
RS
987 (flag (if (frame-visible-p (window-frame (selected-window)))
988 'visible t)))
f72f0c23
SM
989 (unless old
990 (he-init-string (he-dabbrev-beg) (point))
991 (setq he-search-window (selected-window))
992 (set-marker he-search-loc
993 (window-start he-search-window)
994 (window-buffer he-search-window)))
510cbc92
RS
995
996 (while (and (not (equal he-search-string ""))
f72f0c23
SM
997 (marker-position he-search-loc)
998 (not expansion))
7fdbcd83 999 (with-current-buffer (marker-buffer he-search-loc)
f72f0c23
SM
1000 (save-excursion
1001 (goto-char he-search-loc)
1002 (setq expansion (he-dabbrev-search he-search-string ()
1003 (window-end he-search-window)))
1004 (if (and expansion
1005 (eq (marker-buffer he-string-beg) (current-buffer))
1006 (eq (marker-position he-string-beg) (match-beginning 0)))
1007 (setq expansion
1008 (he-dabbrev-search he-search-string ()
1009 (window-end he-search-window))))
1010 (set-marker he-search-loc (point) (current-buffer))))
1011 (unless expansion
1012 (setq he-search-window (next-window he-search-window nil flag))
1013 (if (eq he-search-window (selected-window))
1014 (set-marker he-search-loc nil)
1015 (set-marker he-search-loc (window-start he-search-window)
1016 (window-buffer he-search-window)))))
c60ee5e7 1017
510cbc92
RS
1018 (if (not expansion)
1019 (progn
1020 (if old (he-reset-string))
1021 ())
1022 (progn
1023 (he-substitute-string expansion t)
1024 t))))
652304c9 1025
510cbc92
RS
1026(defun he-dabbrev-search (pattern &optional reverse limit)
1027 (let ((result ())
41b8e71c
RS
1028 (regpat (cond ((not hippie-expand-dabbrev-as-symbol)
1029 (concat "\\<" (regexp-quote pattern) "\\sw+"))
1030 ((eq (char-syntax (aref pattern 0)) ?_)
1031 (concat (regexp-quote pattern) "\\(\\sw\\|\\s_\\)+"))
1032 (t
1033 (concat "\\<" (regexp-quote pattern)
1034 "\\(\\sw\\|\\s_\\)+")))))
c60ee5e7 1035 (while (and (not result)
652304c9 1036 (if reverse
510cbc92
RS
1037 (re-search-backward regpat limit t)
1038 (re-search-forward regpat limit t)))
41b8e71c
RS
1039 (setq result (buffer-substring-no-properties (match-beginning 0)
1040 (match-end 0)))
1041 (if (or (and hippie-expand-dabbrev-as-symbol
1042 (> (match-beginning 0) (point-min))
510cbc92
RS
1043 (memq (char-syntax (char-after (1- (match-beginning 0))))
1044 '(?_ ?w)))
1045 (he-string-member result he-tried-table t))
1046 (setq result nil))) ; ignore if bad prefix or already in table
652304c9
RS
1047 result))
1048
1049(defun he-dabbrev-beg ()
510cbc92
RS
1050 (let ((op (point)))
1051 (save-excursion
41b8e71c 1052 (if hippie-expand-dabbrev-skip-space
510cbc92 1053 (skip-syntax-backward ". "))
41b8e71c
RS
1054 (if (= (skip-syntax-backward (if hippie-expand-dabbrev-as-symbol
1055 "w_" "w"))
1056 0)
510cbc92
RS
1057 op
1058 (point)))))
1059
1060(defun try-expand-dabbrev-from-kill (old)
1061 "Try to expand word \"dynamically\", searching the kill ring.
1062The argument OLD has to be nil the first call of this function, and t
1063for subsequent calls (for further possible completions of the same
1064string). It returns t if a new completion is found, nil otherwise."
1065 (let ((expansion ()))
1066 (if (not old)
c60ee5e7 1067 (progn
510cbc92
RS
1068 (he-init-string (he-dabbrev-beg) (point))
1069 (setq he-expand-list
1070 (if (not (equal he-search-string ""))
1071 kill-ring))
1072 (setq he-search-loc2 0)))
1073 (if (not (equal he-search-string ""))
1074 (setq expansion (he-dabbrev-kill-search he-search-string)))
1075 (if (not expansion)
1076 (progn
1077 (if old (he-reset-string))
1078 ())
1079 (progn
1080 (he-substitute-string expansion t)
1081 t))))
1082
1083(defun he-dabbrev-kill-search (pattern)
1084 (let ((result ())
41b8e71c
RS
1085 (regpat (cond ((not hippie-expand-dabbrev-as-symbol)
1086 (concat "\\<" (regexp-quote pattern) "\\sw+"))
1087 ((eq (char-syntax (aref pattern 0)) ?_)
1088 (concat (regexp-quote pattern) "\\(\\sw\\|\\s_\\)+"))
1089 (t
1090 (concat "\\<" (regexp-quote pattern)
1091 "\\(\\sw\\|\\s_\\)+"))))
510cbc92 1092 (killstr (car he-expand-list)))
c60ee5e7 1093 (while (and (not result)
510cbc92
RS
1094 he-expand-list)
1095 (while (and (not result)
1096 (string-match regpat killstr he-search-loc2))
1097 (setq result (substring killstr (match-beginning 0) (match-end 0)))
41b8e71c 1098 (set-text-properties 0 (length result) () result)
510cbc92 1099 (setq he-search-loc2 (1+ (match-beginning 0)))
41b8e71c
RS
1100 (if (or (and hippie-expand-dabbrev-as-symbol
1101 (> (match-beginning 0) 0)
510cbc92
RS
1102 (memq (char-syntax (aref killstr (1- (match-beginning 0))))
1103 '(?_ ?w)))
1104 (he-string-member result he-tried-table t))
1105 (setq result nil))) ; ignore if bad prefix or already in table
c60ee5e7 1106 (if (and (not result)
510cbc92
RS
1107 he-expand-list)
1108 (progn
c60ee5e7 1109 (setq he-expand-list (cdr he-expand-list))
510cbc92
RS
1110 (setq killstr (car he-expand-list))
1111 (setq he-search-loc2 0))))
1112 result))
1113
1114(defun try-expand-whole-kill (old)
1115 "Try to complete text with something from the kill ring.
1116The argument OLD has to be nil the first call of this function, and t
1117for subsequent calls (for further possible completions of the same
1118string). It returns t if a new completion is found, nil otherwise."
1119 (let ((expansion ()))
1120 (if (not old)
c60ee5e7 1121 (progn
510cbc92
RS
1122 (he-init-string (he-kill-beg) (point))
1123 (if (not (he-string-member he-search-string he-tried-table))
1124 (setq he-tried-table (cons he-search-string he-tried-table)))
c60ee5e7 1125 (setq he-expand-list
510cbc92
RS
1126 (if (not (equal he-search-string ""))
1127 kill-ring))
1128 (setq he-search-loc2 ())))
1129 (if (not (equal he-search-string ""))
1130 (setq expansion (he-whole-kill-search he-search-string)))
1131 (if (not expansion)
1132 (progn
1133 (if old (he-reset-string))
1134 ())
1135 (progn
1136 (he-substitute-string expansion)
1137 t))))
1138
1139(defun he-whole-kill-search (str)
1140 (let ((case-fold-search ())
1141 (result ())
1142 (str (regexp-quote str))
1143 (killstr (car he-expand-list))
1144 (pos -1))
1145 (while (and (not result)
1146 he-expand-list)
1147 (if (not he-search-loc2)
1148 (while (setq pos (string-match str killstr (1+ pos)))
1149 (setq he-search-loc2 (cons pos he-search-loc2))))
1150 (while (and (not result)
1151 he-search-loc2)
1152 (setq pos (car he-search-loc2))
1153 (setq he-search-loc2 (cdr he-search-loc2))
1154 (save-excursion
1155 (goto-char he-string-beg)
1156 (if (and (>= (- (point) pos) (point-min)) ; avoid some string GC
1157 (eq (char-after (- (point) pos)) (aref killstr 0))
1158 (search-backward (substring killstr 0 pos)
1159 (- (point) pos) t))
41b8e71c
RS
1160 (progn
1161 (setq result (substring killstr pos))
1162 (set-text-properties 0 (length result) () result))))
510cbc92
RS
1163 (if (and result
1164 (he-string-member result he-tried-table))
1165 (setq result nil))) ; ignore if already in table
1166 (if (and (not result)
1167 he-expand-list)
1168 (progn
c60ee5e7 1169 (setq he-expand-list (cdr he-expand-list))
510cbc92
RS
1170 (setq killstr (car he-expand-list))
1171 (setq pos -1))))
1172 result))
1173
1174(defun he-kill-beg ()
1175 (let ((op (point)))
1176 (save-excursion
1177 (skip-syntax-backward "^w_")
1178 (if (= (skip-syntax-backward "w_") 0)
1179 op
1180 (point)))))
1181
8c6677ed
JB
1182
1183(provide 'hippie-exp)
652304c9 1184
8c6677ed 1185;;; hippie-exp.el ends here