*** empty log message ***
[bpt/emacs.git] / lisp / ido.el
CommitLineData
789d1bf0
KS
1;;; ido.el --- interactively do things with buffers and files.
2
c4d9ba39 3;; Copyright (C) 1996-2003 Free Software Foundation, Inc.
789d1bf0
KS
4
5;; Author: Kim F. Storm <storm@cua.dk>
6;; Based on: iswitchb by Stephen Eglen <stephen@cns.ed.ac.uk>
7;; Keywords: extensions convenience
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
25
26;;; Acknowledgements
27
28;; Infinite amounts of gratitude goes to Stephen Eglen <stephen@cns.ed.ac.uk>
71296446 29;; who wrote iswitch-buffer mode - from which I ripped off 99% of the code
789d1bf0
KS
30;; for ido-switch-buffer and found the inspiration for ido-find-file.
31;; The ido package would never have existed without his work.
32
33;; Also thanks to Klaus Berndl, Rohit Namjoshi, Robert Fenk, Alex Schroeder,
34;; Bill Benedetto, and Stephen Eglen for bug fixes and improvements.
35
36;;; History
37
38;; Since I discovered Stephen Eglen's excellent iswitchb package, I just
39;; couldn't live without it, but once being addicted to switching buffers
40;; with a minimum of keystrokes, I soon found that opening files in the
41;; old-fashioned way was just too slow - so I decided to write a package
42;; which could open files with the same speed and ease as iswitchb could
43;; switch buffers.
44
45;; I originally wrote a separate ifindf.el package based on a copy of
46;; iswitchb.el, which did for opening files what iswitchb did for
47;; switching buffers. Along the way, I corrected a few errors in
48;; ifindf which could have found its way back into iswitchb, but since
49;; most of the functionality of the two package was practically
50;; identical, I decided that the proper thing to do was to merge my
51;; ifindf package back into iswitchb.
52;;
53;; This is basically what ido (interactively do) is all about; but I
54;; found it ackward to merge my changes into the "iswitchb-" namespace,
55;; so I invented a common "ido-" namespace for the merged packages.
56;;
57;; This version is based on ido.el version 1.57 released on
58;; gnu.emacs.sources adapted for emacs 21.4 to use command remapping
59;; and optionally hooking the read-buffer and read-file-name functions.
60;;
61;; Prefix matching was added by Klaus Berndl <klaus.berndl@sdm.de> based on
62;; an idea of Yuji Minejima <ggb01164@nifty.ne.jp> and his mcomplete-package.
63
64
65;;; Commentary:
66
67;; Ido - interactive do - switches between buffers and opens files and
68;; directories with a minimum of keystrokes. It is a superset of
69;; iswitchb, the interactive buffer switching package by Stephen Eglen.
70
71;; Interactive substring matching
72;; ------------------------------
73;;
74;; As you type in a substring, the list of buffers or files currently
75;; matching the substring are displayed as you type. The list is
76;; ordered so that the most recent buffers or files visited come at
77;; the start of the list.
78;;
79;; The buffer or file at the start of the list will be the one visited
80;; when you press RETURN. By typing more of the substring, the list is
81;; narrowed down so that gradually the buffer or file you want will be
82;; at the top of the list. Alternatively, you can use C-s and C-r (or
83;; the right and left arrow keys) to rotate buffer or file names in the
84;; list until the one you want is at the top of the list.
85;;
86;; Completion is also available so that you can see what is common to
87;; all of the matching buffers or files as you type.
88;;
89;; Example:
90;;
91;; If I have two buffers called "123456" and "123", with "123456" the
92;; most recent, when I use ido-switch-buffer, I first of all get
93;; presented with the list of all the buffers
94;;
71296446 95;; Buffer: {123456,123}
789d1bf0
KS
96;;
97;; If I then press 2:
98;; Buffer: 2[3]{123456,123}
99;;
100;; The list in {...} are the matching buffers, most recent first
101;; (buffers visible in the current frame are put at the end of the
102;; list by default). At any time I can select the item at the head of
103;; the list by pressing RET. I can also bring the put the first
104;; element at the end of the list by pressing C-s or [right], or put
105;; the last element at the head of the list by pressing C-r or [left].
106;;
107;; The item in [...] indicates what can be added to my input by
108;; pressing TAB. In this case, I will get "3" added to my input.
109
110;; So, I press TAB:
111;; Buffer: 23{123456,123}
112;;
113;; At this point, I still have two matching buffers.
114;; If I want the first buffer in the list, I simply press RET. If I
115;; wanted the second in the list, I could press C-s to move it to the
116;; top of the list and then RET to select it.
117;;
118;; However, if I type 4, I only have one match left:
119;; Buffer: 234[123456] [Matched]
120;;
121;; Since there is only one matching buffer left, it is given in [] and we
122;; see the text [Matched] afterwards. I can now press TAB or RET to go
123;; to that buffer.
124;;
125;; If however, I now type "a":
126;; Buffer: 234a [No match]
127;; There are no matching buffers. If I press RET or TAB, I can be
128;; prompted to create a new buffer called "234a".
129;;
130;; Of course, where this function comes in really useful is when you
131;; can specify the buffer using only a few keystrokes. In the above
132;; example, the quickest way to get to the "123456" file would be
133;; just to type 4 and then RET (assuming there isn't any newer buffer
134;; with 4 in its name).
135
136;; Likewise, if you use C-x C-f (ido-find-file), the list of files and
137;; directories in the current directory is provided in the same
138;; fashion as the buffers above. The files and directories are
139;; normally sorted in alphabetical order, but the most recently
140;; visited directory is placed first to speed up navigating to
141;; directories that you have visited recently.
142;;
143;; In addition to scrolling through the list using [right] and [left],
144;; you can use [up] and [down] to quickly scroll the list to the next
145;; or previous subdirectory.
146;;
147;; To go down into a subdirectory, and continue the file selection on
148;; the files in that directory, simply move the directory to the head
149;; of the list and hit RET.
150;;
151;; To go up to the parent directory, delete any partial file name
152;; already specified (e.g. using [backspace]) and hit [backspace].
153;;
154;; To go to the root directory (on the current drive), enter two
155;; slashes. On MS-DOS or Windows, to select the root of another
156;; drive, enter X:/ where X is the drive letter. You can also visit
157;; files on other hosts using the ange-ftp notations `/host:' and
158;; `/user@host:'. See the variable `ido-slow-ftp-hosts' if you want
71296446 159;; to inhibit the ido substring matching for ftp access.
789d1bf0
KS
160;;
161;; If for some reason you cannot specify the proper file using
162;; ido-find-file, you can press C-f to enter the normal find-file.
163;; You can also press C-b to drop into ido-switch-buffer.
164
165;; See the doc string of ido-switch-buffer and ido-find-file for full
166;; keybindings and features.
167;; (describe-function 'ido-find-file)
168
169;; Hidden buffers and files
170;; ------------------------
171;;
172;; Normally, ido does not include hidden buffers (whose name starts
173;; with a space) and hidden files and directories (whose name starts
174;; with `.') in the list of possible completions. However, if the
175;; substring you enter does not match any of the visible buffers or
176;; files, ido will automatically look for completions among the hidden
177;; buffers or files.
178;;
179;; You can toggle display of the hidden buffers and files with C-a.
180
181;; Additional functionality
182;; ------------------------
183;;
184;; After C-x b, the buffer at the head of the list can be killed by
185;; pressing C-k. If the buffer needs saving, you will be queried
186;; before the buffer is killed.
187;;
188;; Likewise, after C-x C-f, you can delete (i.e. physically remove)
189;; the file at the head of the list with C-k. You will always be
190;; asked for confirmation before the file is deleted.
191;;
192;; If you enter C-x b to switch to a buffer visiting a given file, and
193;; you find that the file you are after is not in any buffer, you can
194;; press C-f to immediately drop into ido-find-file. And you can
195;; switch back to buffer selection with C-b.
196
197;; Prefix matching
198;; ---------------
199;;
200;; The standard way of completion with Unix-shells and Emacs is to insert a
201;; PREFIX and then hitting TAB (or another completion key). Cause of this
202;; behavior has become second nature to a lot of emacs users `ido' offers in
203;; addition to the default substring-matching-method (look above) also the
204;; prefix-matching-method. The kind of matching is the only difference to
205;; the description of the substring-matching above.
206;;
207;; You can toggle prefix matching with C-p.
208;;
209;; Example:
210;;
211;; If you have again two Buffers "123456" and "123" then hitting "2" does
212;; not match because "2" is not a PREFIX in any of the buffer-names. This
213;; is the only difference between the substring and prefix matching.
214
215;; Flexible matching
216;; -----------------
217;;
218;; If you set ido-enable-flex-matching, ido will do a more flexible
219;; matching (unless regexp matching is active) to find possible matches
220;; among the available buffer or file names if no matches are found using
221;; the normal prefix or substring matching.
222;;
223;; The flexible matching implies that any item which simply contains all
224;; of the entered characters in the specified sequence will match.
225;;
226;; Example:
227;;
228;; If you have four files "alpha", "beta", "gamma", and "delta",
229;; entering "aa" will match "alpha" and "gamma", while "ea" matches
230;; "beta" and "delta". If prefix matching is also active, "aa" only
231;; matches "alpha", while "ea" does not match any files.
232
233;; Regexp matching
234;; ---------------
235;;
236;; There is limited provision for regexp matching within ido,
237;; enabled through `ido-enable-regexp' (toggle with C-t).
238;; This allows you to type `c$' for example and see all file names
239;; ending in `c'. This facility is quite limited though in two
240;; respects. First, you can't currently type in expressions like
241;; `[0-9]' directly -- you have to type them in when ido-enable-regexp
242;; is nil and then toggle on the regexp functionality. Likewise,
243;; don't enter an expression containing `\' in regexp mode. If you
244;; try, ido gets confused, so just hit C-g and try again. Secondly,
245;; no completion mechanism is currently offered with regexp searching.
246
247
248;; Customization
249;; -------------
250;;
251;; Customize the `ido' group to change the `ido' functionality.
252;;
253;; To modify the keybindings, use the hook provided. For example:
254;;(add-hook 'ido-define-mode-map-hook 'ido-my-keys)
255;;
256;;(defun ido-my-keys ()
257;; "Add my keybindings for ido."
258;; (define-key ido-mode-map " " 'ido-next-match)
259;; )
260
261;; Seeing all the matching buffers or files
262;; ----------------------------------------
263;;
264;; If you have many matching files, they may not all fit onto one
265;; line of the minibuffer. Normally, the minibuffer window will grow
266;; to show you more of the matching files (depending on the setting
267;; of the variables `resize-mini-windows' and `max-mini-window-height').
268;; If you want ido to behave differently from the default minibuffer
269;; resizing behaviour, set the variable `ido-max-window-height'.
270;;
271;; Also, to improve the responsiveness of ido, the maximum number of
272;; matching items is limited to 12, but you can increase or removed
273;; this limit via the `ido-max-prospects' variable.
274
275;; To see a full list of all matching buffers in a separate buffer,
276;; hit ? or press TAB when there are no further completions to the
277;; substring. Repeated TAB presses will scroll you through this
278;; separate buffer.
279
280;; Changing the list of files
281;; --------------------------
282
283;; By default, the list of current files is most recent first,
284;; oldest last, with the exception that the files visible in the
285;; current frame are put at the end of the list. A hook exists to
286;; allow other functions to order the list. For example, if you add:
287;;
288;; (add-hook 'ido-make-buffer-list-hook 'ido-summary-buffers-to-end)
289;;
290;; then all files matching "Summary" are moved to the end of the
291;; list. (I find this handy for keeping the INBOX Summary and so on
292;; out of the way.) It also moves files matching "output\*$" to the
293;; end of the list (these are created by AUC TeX when compiling.)
294;; Other functions could be made available which alter the list of
295;; matching files (either deleting or rearranging elements.)
296
297;; Highlighting
298;; ------------
299
300;; The highlighting of matching items is controlled via ido-use-faces.
301;; The faces used are ido-first-match-face, ido-only-match-face and
302;; ido-subdir-face.
303;; Colouring of the matching item was suggested by
304;; Carsten Dominik (dominik@strw.leidenuniv.nl).
305
306;; Replacement for read-buffer and read-file-name
307;; ----------------------------------------------
308
309;; ido-read-buffer and ido-read-file-name have been written to be drop
310;; in replacements for the normal buffer and file name reading
311;; functions `read-buffer' and `read-file-name'.
312
313;; To use ido for all buffer and file selections in Emacs, customize the
314;; variable `ido-everywhere'.
315
316;; Using ido-like behaviour in other lisp packages
317;; -----------------------------------------------
318
319;; If you don't want to rely on the `ido-everywhere' functionality,
320;; ido-read-buffer, ido-read-file-name, and ido-read-directory-name
321;; can be used by other packages to read a buffer name, a file name,
322;; or a directory name in the `ido' way.
323
324
325;;; Code:
326
327(provide 'ido)
328
329;;; User Variables
330;;
331;; These are some things you might want to change.
332
333(defun ido-fractionp (n)
334 (and (numberp n) (> n 0.0) (<= n 1.0)))
335
336(defgroup ido nil
337 "Switch between files using substrings."
338 :group 'extensions
339 :group 'convenience
340 :link '(emacs-commentary-link :tag "Commentary" "ido.el")
341 :link '(emacs-library-link :tag "Lisp File" "ido.el"))
342
343;;;###autoload
344(defcustom ido-mode nil
345 "Determines for which functional group \(buffer and files) ido behavior
346should be enabled. The following values are possible:
337d2b66 347- `buffer': Turn only on ido buffer behavior \(switching, killing,
71296446 348 displaying...)
337d2b66
RS
349- `file': Turn only on ido file behavior \(finding, writing, inserting...)
350- `both': Turn on ido buffer and file behavior.
351- `nil': Turn off any ido switching.
789d1bf0
KS
352
353Setting this variable directly does not take effect;
354use either \\[customize] or the function `ido-mode'."
355 :set #'(lambda (symbol value)
356 (ido-mode value))
357 :initialize 'custom-initialize-default
358 :require 'ido
359 :link '(emacs-commentary-link "ido.el")
360 :set-after '(ido-save-directory-list-file)
361 :version "21.4"
71296446 362 :type '(choice (const :tag "Turn on only buffer" buffer)
789d1bf0
KS
363 (const :tag "Turn on only file" file)
364 (const :tag "Turn on both buffer and file" both)
365 (const :tag "Switch off all" nil))
366 :group 'ido)
367
368(defcustom ido-everywhere nil
369 "Use ido everywhere for reading file names and directories.
370Setting this variable directly does not work. Use `customize' or
371call the function `ido-everywhere'."
372 :set #'(lambda (symbol value)
373 (ido-everywhere value))
374 :initialize 'custom-initialize-default
375 :type 'boolean
376 :group 'ido)
377
378(defcustom ido-case-fold case-fold-search
379 "*Non-nil if searching of buffer and file names should ignore case."
380 :type 'boolean
381 :group 'ido)
382
383(defcustom ido-ignore-buffers
384 '("\\` ")
385 "*List of regexps or functions matching buffer names to ignore.
386For example, traditional behavior is not to list buffers whose names begin
387with a space, for which the regexp is `\\` '. See the source file for
388example functions that filter buffernames."
389 :type '(repeat (choice regexp function))
390 :group 'ido)
391
392(defcustom ido-ignore-files
393 '("\\`CVS/" "\\`#" "\\`.#" "\\`\\.\\./" "\\`\\./")
394 "*List of regexps or functions matching file names to ignore.
395For example, traditional behavior is not to list files whose names begin
396with a #, for which the regexp is `\\`#'. See the source file for
397example functions that filter filenames."
398 :type '(repeat (choice regexp function))
399 :group 'ido)
400
401(defcustom ido-ignore-extensions t
402 "*Non-nil means ignore files in completion-ignored-extensions list."
403 :type 'boolean
404 :group 'ido)
405
406(defcustom ido-show-dot-for-dired nil
407 "*Non-nil means to always put . as the first item in file name lists.
408This allows the current directory to be opened immediate with `dired'."
409 :type 'boolean
410 :group 'ido)
411
412(defcustom ido-ignore-directories
413 '("\\`CVS/" "\\`\\.\\./" "\\`\\./")
414 "*List of regexps or functions matching sub-directory names to ignore."
415 :type '(repeat (choice regexp function))
416 :group 'ido)
417
418(defcustom ido-ignore-directories-merge nil
362cdb61
KS
419 "*List of regexps or functions matching directory names to ignore during merge.
420Directory names matched by one of the regexps in this list are not inserted
789d1bf0
KS
421in merged file and directory lists."
422 :type '(repeat (choice regexp function))
423 :group 'ido)
424
425;;; Examples for setting the value of ido-ignore-buffers
426;(defun ido-ignore-c-mode (name)
427; "Ignore all c mode buffers -- example function for ido."
428; (save-excursion
429; (set-buffer name)
430; (string-match "^C$" mode-name)))
431;
432;(setq ido-ignore-buffers '("^ " ido-ignore-c-mode))
433
434;;; Examples for setting the value of ido-ignore-files
435;(setq ido-ignore-files '("^ " "\\.c$" "\\.h$"))
436
437(defcustom ido-default-file-method 'always-frame
438 "*How to switch to new file when using `ido-find-file'.
439Possible values:
440`samewindow' Show new file in same window
441`otherwindow' Show new file in another window (same frame)
442`display' Display file in another window without switching to it
443`otherframe' Show new file in another frame
444`maybe-frame' If a file is visible in another frame, prompt to ask if you
445 you want to see the file in the same window of the current
446 frame or in the other frame.
447`always-frame' If a file is visible in another frame, raise that
448 frame. Otherwise, visit the file in the same window."
71296446 449 :type '(choice (const samewindow)
789d1bf0
KS
450 (const otherwindow)
451 (const display)
71296446 452 (const otherframe)
789d1bf0
KS
453 (const maybe-frame)
454 (const always-frame))
455 :group 'ido)
456
457(defcustom ido-default-buffer-method 'always-frame
458 "*How to switch to new buffer when using `ido-switch-buffer'.
459See ido-default-file-method for details."
71296446 460 :type '(choice (const samewindow)
789d1bf0
KS
461 (const otherwindow)
462 (const display)
71296446 463 (const otherframe)
789d1bf0
KS
464 (const maybe-frame)
465 (const always-frame))
466 :group 'ido)
467
468(defcustom ido-enable-flex-matching nil
469 "*Non-nil means that `ido' will do flexible string matching.
470Flexible matching means that if the entered string does not
471match any item, any item containing the entered characters
472in the given sequence will match."
473 :type 'boolean
474 :group 'ido)
475
476
477(defcustom ido-enable-regexp nil
478 "*Non-nil means that `ido' will do regexp matching.
479Value can be toggled within `ido' using `ido-toggle-regexp'."
480 :type 'boolean
481 :group 'ido)
482
483(defcustom ido-enable-prefix nil
484 "*Nil means that `ido' will match if the inserted text is an
485arbitrary substring (default). If non-nil `ido' will only match if the inserted
486text is a prefix \(this behavior is like the standard unix- or
487emacs-completion works).
488Value can be toggled within `ido' using `ido-toggle-prefix'."
489 :type 'boolean
490 :group 'ido)
491
d1a0acac
KS
492(defcustom ido-cannot-complete-command 'ido-completion-help
493 "*Command run when `ido-complete' can't complete any more.
494The most useful values are `ido-completion-help', which pops up a
495window with completion alternatives, or `ido-next-match' or
496`ido-prev-match', which cycle the buffer list."
497 :type 'function
498 :group 'ido)
499
500
789d1bf0
KS
501(defcustom ido-record-commands t
502 "*Non-nil means that `ido' will record commands in command history.
503Note that the non-ido equivalent command is recorded."
504 :type 'boolean
505 :group 'ido)
506
507(defcustom ido-max-prospects 12
508 "*Non-zero means that the prospect list will be limited to than number of items.
509For a long list of prospects, building the full list for the minibuffer can take a
510non-negletable amount of time; setting this variable reduces that time."
511 :type 'integer
512 :group 'ido)
513
a42e9704 514(defcustom ido-max-file-prompt-width 0.35
789d1bf0
KS
515 "*Non-zero means that the prompt string be limited to than number of characters.
516If value is a floating point number, it specifies a fraction of the frame width."
517 :type '(choice
518 (integer :tag "Characters" :value 20)
519 (restricted-sexp :tag "Fraction of frame width"
520 :value 0.35
521 :match-alternatives (ido-fractionp)))
522 :group 'ido)
523
524(defcustom ido-max-window-height nil
525 "*Non-nil specifies a value to override `max-mini-window-height'."
526 :type '(choice
527 (const :tag "Don't override" nil)
528 (integer :tag "Number of lines" :value 1)
529 (restricted-sexp
530 :tag "Fraction of window height"
531 :value 0.25
532 :match-alternatives (ido-fractionp)))
533 :group 'ido)
534
535(defcustom ido-enable-last-directory-history t
362cdb61 536 "*Non-nil means that `ido' will remember latest selected directory names.
789d1bf0
KS
537See `ido-last-directory-list' and `ido-save-directory-list-file'."
538 :type 'boolean
539 :group 'ido)
540
541(defcustom ido-max-work-directory-list 50
542 "*Maximum number of working directories to record.
543This is the list of directories where files have most recently been opened.
544See `ido-work-directory-list' and `ido-save-directory-list-file'."
545 :type 'integer
546 :group 'ido)
547
548(defcustom ido-work-directory-list-ignore-regexps nil
549 "*List of regexps matching directories which should not be recorded.
362cdb61 550Directory names matched by one of the regexps in this list are not inserted in
789d1bf0
KS
551the `ido-work-directory-list' list."
552 :type '(repeat regexp)
553 :group 'ido)
554
bad111c2 555
310682e6
KS
556(defcustom ido-use-filename-at-point nil
557 "*Non-nil means that ido shall look for a filename at point.
558If found, use that as the starting point for filename selection."
559 :type 'boolean
560 :group 'ido)
561
562
563(defcustom ido-use-url-at-point nil
564 "*Non-nil means that ido shall look for a URL at point.
565If found, call `find-file-at-point' to visit it."
566 :type 'boolean
567 :group 'ido)
568
569
bad111c2
KS
570(defcustom ido-enable-tramp-completion t
571 "*Non-nil means that ido shall perform tramp method and server name completion.
362cdb61 572A tramp file name uses the following syntax: /method:user@host:filename."
bad111c2
KS
573 :type 'boolean
574 :group 'ido)
575
789d1bf0 576(defcustom ido-record-ftp-work-directories t
337d2b66 577 "*Non-nil means record ftp file names in the work directory list."
789d1bf0
KS
578 :type 'boolean
579 :group 'ido)
580
581(defcustom ido-merge-ftp-work-directories nil
337d2b66 582 "*If nil means merging ignores ftp file names in the work directory list."
789d1bf0
KS
583 :type 'boolean
584 :group 'ido)
585
586(defcustom ido-cache-ftp-work-directory-time 1.0
587 "*Maximum time to cache contents of an ftp directory (in hours).
588If zero, ftp directories are not cached."
589 :type 'number
590 :group 'ido)
591
592(defcustom ido-slow-ftp-hosts nil
593 "*List of slow ftp hosts where ido prompting should not be used.
594If an ftp host is on this list, ido automatically switches to the non-ido
595equivalent function, e.g. find-file rather than ido-find-file."
596 :type '(repeat string)
597 :group 'ido)
598
599(defcustom ido-slow-ftp-host-regexps nil
600 "*List of regexps matching slow ftp hosts (see `ido-slow-ftp-hosts')."
601 :type '(repeat regexp)
602 :group 'ido)
603
604(defcustom ido-max-work-file-list 10
605 "*Maximum number of names of recently opened files to record.
606This is the list the file names (sans directory) which have most recently
607been opened. See `ido-work-file-list' and `ido-save-directory-list-file'."
608 :type 'integer
609 :group 'ido)
610
611(defcustom ido-work-directory-match-only t
612 "*Non-nil means to skip non-matching directories in the directory history.
613When some text is already entered at the `ido-find-file' prompt, using
614\\[ido-prev-work-directory] or \\[ido-next-work-directory] will skip directories
615without any matching entries."
616 :type 'boolean
617 :group 'ido)
618
619(defcustom ido-auto-merge-work-directories-length 0
620 "*Automatically switch to merged work directories during file name input.
621The value is number of characters to type before switching to merged mode.
622If zero, the switch happens when no matches are found in the current directory.
623Automatic merging is disabled if the value is negative."
624 :type 'integer
625 :group 'ido)
626
627(defcustom ido-auto-merge-delay-time 0.70
628 "*Delay in seconds to wait for more input before doing auto merge."
629 :type 'number
630 :group 'ido)
631
632(defcustom ido-auto-merge-inhibit-characters-regexp "[][*?~]"
633 "*Regexp matching characters which should inhibit automatic merging.
634When a (partial) file name matches this regexp, merging is inhibited."
635 :type 'regexp
636 :group 'ido)
637
638(defcustom ido-merged-indicator "^"
639 "The string appended to first choice if it has multiple directory choices."
640 :type 'string
641 :group 'ido)
642
643(defcustom ido-max-dir-file-cache 100
644 "*Maximum number of working directories to be cached.
645This is the size of the cache of file-name-all-completions results.
646Each cache entry is time stamped with the modification time of the
647directory. Some systems, like Windows, have unreliable directory
648modification times, so you may choose to disable caching on such
649systems, or explicitly refresh the cache contents using the command
650`ido-reread-directory' command (C-l) in the minibuffer.
651See also `ido-dir-file-cache' and `ido-save-directory-list-file'."
652 :type 'integer
653 :group 'ido)
654
655(defcustom ido-rotate-file-list-default nil
656 "*Non-nil means that `ido' will always rotate file list to get default in front."
657 :type 'boolean
658 :group 'ido)
659
bad111c2 660(defcustom ido-enter-single-matching-directory 'slash
789d1bf0
KS
661 "*Automatically enter sub-directory if it is the only matching item, if non-nil.
662If value is 'slash, only enter if typing final slash, else do it always."
71296446 663 :type '(choice (const :tag "Never" nil)
789d1bf0
KS
664 (const :tag "When typing /" slash)
665 (other :tag "Always" t))
666 :group 'ido)
667
789d1bf0
KS
668(defcustom ido-create-new-buffer 'prompt
669 "*Specify whether a new buffer is created if no buffer matches substring.
670Choices are 'always to create new buffers unconditionally, 'prompt to
671ask user whether to create buffer, or 'never to never create new buffer."
71296446 672 :type '(choice (const always)
789d1bf0
KS
673 (const prompt)
674 (const never))
675 :group 'ido)
676
677(defcustom ido-define-mode-map-hook nil
678 "*Hook to define keys in `ido-mode-map' for extra keybindings."
679 :type 'hook
680 :group 'ido)
681
682(defcustom ido-separator nil
683 "*String used by ido to separate the alternatives in the minibuffer.
684Obsolete. Set 3rd element of `ido-decorations' instead."
610a4f64 685 :type '(choice string (const nil))
789d1bf0
KS
686 :group 'ido)
687
688(defcustom ido-decorations '( "{" "}" " | " " | ..." "[" "]" " [No match]" " [Matched]")
689 "*List of strings used by ido to display the alternatives in the minibuffer.
690There are 8 elements in this list, each is a pair of strings:
6911st and 2nd elements are used as brackets around the prospect list,
6923rd element is the separator between prospects (ignored if ido-separator is set),
6934th element is the string inserted at the end of a truncated list of prospects,
6945th and 6th elements are used as brackets around the common match string which
695can be completed using TAB,
71296446 6967th element is the string displayed when there are a no matches, and
789d1bf0
KS
6978th element displayed if there is a single match (and faces are not used)."
698 :type '(repeat string)
699 :group 'ido)
700
701(defcustom ido-use-faces t
702 "*Non-nil means use ido faces to highlighting first match, only match and
703subdirs in the alternatives."
704 :type 'boolean
705 :group 'ido)
706
707(defface ido-first-match-face '((t (:bold t)))
708 "*Font used by ido for highlighting first match."
709 :group 'ido)
710
71296446 711(defface ido-only-match-face '((((class color))
789d1bf0
KS
712 (:foreground "ForestGreen"))
713 (t (:italic t)))
714 "*Font used by ido for highlighting only match."
715 :group 'ido)
716
71296446 717(defface ido-subdir-face '((((class color))
789d1bf0
KS
718 (:foreground "red"))
719 (t (:underline t)))
720 "*Font used by ido for highlighting subdirs in the alternatives."
721 :group 'ido)
722
71296446 723(defface ido-indicator-face '((((class color))
789d1bf0
KS
724 (:foreground "yellow"
725 :background "red"
726 :width condensed))
727 (t (:inverse-video t)))
728 "*Font used by ido for highlighting its indicators."
729 :group 'ido)
730
731(defcustom ido-make-file-list-hook nil
732 "*List of functions to run when the list of matching files is created.
733Each function on the list may modify the dynamically bound variable
734`ido-temp-list' which contains the current list of matching files."
735 :type 'hook
736 :group 'ido)
737
738(defcustom ido-make-dir-list-hook nil
739 "*List of functions to run when the list of matching directories is created.
740Each function on the list may modify the dynamically bound variable
741`ido-temp-list' which contains the current list of matching directories."
742 :type 'hook
743 :group 'ido)
744
745(defcustom ido-make-buffer-list-hook nil
746 "*List of functions to run when the list of matching buffers is created.
747Each function on the list may modify the dynamically bound variable
748`ido-temp-list' which contains the current list of matching buffer names."
749 :type 'hook
750 :group 'ido)
751
362cdb61 752(defcustom ido-rewrite-file-prompt-functions nil
789d1bf0
KS
753 "*List of functions to run when the find-file prompt is created.
754Each function on the list may modify the following dynamically bound
755variables:
337d2b66
RS
756 dirname - the (abbreviated) directory name
757 to be modified by the hook functions
758 max-width - the max width of the resulting dirname; nil means no limit
759 prompt - the basic prompt (e.g. \"Find File: \")
760 literal - the string shown if doing \"literal\" find; set to nil to omit
761 vc-off - the string shown if version control is inhibited; set to nit to omit
762 prefix - either nil or a fixed prefix for the dirname
763
789d1bf0 764The following variables are available, but should not be changed:
362cdb61 765 ido-current-directory - the unabbreviated directory name
337d2b66 766 item - equals `file' or `dir' depending on the current mode."
789d1bf0
KS
767 :type 'hook
768 :group 'ido)
769
362cdb61
KS
770(defvar ido-rewrite-file-prompt-rules nil
771 "*Alist of rewriting rules for directory names in ido prompts.
772A list of elements of the form (FROM . TO) or (FROM . FUNC), each
773meaning to rewrite the directory name if matched by FROM by either
774substituting the matched string by TO or calling the function FUNC
775with the current directory name as its only argument and using the
776return value as the new directory name. In addition, each FUNC may
777also modify the dynamic variables described for the variable
778`ido-rewrite-file-prompt-functions'.")
789d1bf0
KS
779
780(defcustom ido-completion-buffer "*Ido Completions*"
781 "*Name of completion buffer used by ido.
782Set to nil to disable completion buffers popping up."
783 :type 'string
784 :group 'ido)
785
786(defcustom ido-completion-buffer-all-completions nil
787 "*Non-nil means to show all completions in completion buffer.
788Otherwise, only the current list of matches is shown."
789 :type 'boolean
790 :group 'ido)
791
792(defvar ido-all-frames 'visible
793 "*Argument to pass to `walk-windows' when finding visible files.
794See documentation of `walk-windows' for useful values.")
795
796(defcustom ido-minibuffer-setup-hook nil
797 "*Ido-specific customization of minibuffer setup.
798
799This hook is run during minibuffer setup iff `ido' will be active.
800It is intended for use in customizing ido for interoperation
801with other packages. For instance:
802
71296446 803 \(add-hook 'ido-minibuffer-setup-hook
789d1bf0
KS
804 \(function
805 \(lambda ()
319a586a
JB
806 \(make-local-variable 'max-mini-window-height)
807 \(setq max-mini-window-height 3))))
789d1bf0 808
319a586a 809will constrain Emacs to a maximum minibuffer height of 3 lines when
789d1bf0
KS
810ido is running. Copied from `icomplete-minibuffer-setup-hook'."
811 :type 'hook
812 :group 'ido)
813
814(defcustom ido-save-directory-list-file "~/.ido.last"
815 "File in which the ido state is saved between invocations.
816Variables stored are: `ido-last-directory-list', `ido-work-directory-list',
817`ido-work-file-list', and `ido-dir-file-cache'.
818Must be set before enabling ido mode."
819 :type 'string
820 :group 'ido)
821
822(defcustom ido-read-file-name-as-directory-commands '()
362cdb61 823 "List of commands which uses read-file-name to read a directory name.
789d1bf0
KS
824When `ido-everywhere' is non-nil, the commands in this list will read
825the directory using ido-read-directory-name."
826 :type '(repeat symbol)
827 :group 'ido)
828
829(defcustom ido-read-file-name-non-ido '()
830 "List of commands which shall not read file names the ido way.
831When `ido-everywhere' is non-nil, the commands in this list will read
832the file name using normal read-file-name style."
833 :type '(repeat symbol)
834 :group 'ido)
835
836;;; Internal Variables
837
838;; Persistent variables
839
840(defvar ido-mode-map nil
841 "Keymap for `ido-find-file' and `ido-switch-buffer'.")
842
843(defvar ido-file-history nil
844 "History of files selected using `ido-find-file'.")
845
846(defvar ido-buffer-history nil
847 "History of buffers selected using `ido-switch-buffer'.")
848
789d1bf0 849(defvar ido-last-directory-list nil
362cdb61 850 "List of last selected directory names.
789d1bf0
KS
851See `ido-enable-last-directory-history' for details.")
852
853(defvar ido-work-directory-list nil
362cdb61 854 "List of actual working directory names.
789d1bf0
KS
855The current directory is inserted at the front of this list whenever a
856file is opened with ido-find-file and family.")
857
858(defvar ido-work-file-list nil
859 "List of actual work file names.
337d2b66
RS
860Opening a file with `ido-find-file' and similar functions
861inserts the current file name (relative to its containing directory)
862at the front of this list.")
789d1bf0
KS
863
864(defvar ido-dir-file-cache nil
337d2b66
RS
865 "List of `file-name-all-completions' results.
866Each element in the list is of the form (DIR (MTIME) FILE...).")
789d1bf0 867
69beb26d
KS
868(defvar ido-ignore-item-temp-list nil
869 "List of items to ignore in current ido invocation.
870Intended to be let-bound by functions which calls ido repeatedly.
871Should never be set permanently.")
872
789d1bf0
KS
873;; Temporary storage
874
875(defvar ido-eoinput 1
876 "Point where minibuffer input ends and completion info begins.
877Copied from `icomplete-eoinput'.")
878(make-variable-buffer-local 'ido-eoinput)
879
880(defvar ido-common-match-string nil
881 "Stores the string that is common to all matching files.")
882
883(defvar ido-rescan nil
884 "Non-nil means we need to regenerate the list of matching items.")
885
886(defvar ido-rotate nil
887 "Non-nil means we are rotating list of matches.")
888
889(defvar ido-text nil
890 "Stores the users string as it is typed in.")
891
892(defvar ido-text-init nil
893 "The initial string for the users string it is typed in.")
894
895(defvar ido-matches nil
896 "List of files currently matching `ido-text'.")
897
898(defvar ido-report-no-match t
899 "Report [No Match] when no completions matches ido-text.")
900
71296446
JB
901(defvar ido-exit nil
902 "Flag to monitor how `ido-find-file' exits.
789d1bf0
KS
903If equal to `takeprompt', we use the prompt as the file name to be
904selected.")
905
906(defvar ido-current-directory nil
907 "Current directory for ido-find-file.")
908
909(defvar ido-auto-merge-timer nil
910 "Delay timer for auto merge.")
911
912(defvar ido-use-mycompletion-depth 0
71296446 913 "Non-nil means use `ido' completion feedback.
789d1bf0
KS
914Is set by ido functions to the current minibuffer-depth, so that
915it doesn't interfere with other minibuffer usage.")
916
917
918;;; Variables with dynamic bindings.
919;;; Declared here to keep the byte compiler quiet.
920
921;; Stores the current ido item type ('file, 'dir or 'buffer).
922(defvar ido-cur-item)
923
924;; Stores the current list of items that will be searched through.
925;; The list is ordered, so that the most interesting item comes first,
926;; although by default, the files visible in the current frame are put
927;; at the end of the list. Created by `ido-make-item-list'.
928(defvar ido-cur-list)
929
930;; Stores the list of items which are ignored when building
931;; `ido-cur-list'. It is in no specific order.
932(defvar ido-ignored-list)
933
934;; Keep current item list if non-nil.
935(defvar ido-keep-item-list)
936
937;; Process ido-ignore-* lists.
938(defvar ido-process-ignore-lists)
939
940;; Don't process ido-ignore- lists once.
941(defvar ido-process-ignore-lists-inhibit)
942
943;; Buffer from which ido was entered.
944(defvar ido-entry-buffer)
945
946;; Non-nil if matching file must be selected.
947(defvar ido-require-match)
948
949;; Stores a temporary version of the file list being created.
950(defvar ido-temp-list)
951
952;; Non-nil if default list element should be rotated into place.
953(defvar ido-rotate-temp)
954
955;; Stores current index in ido-work-directory-list.
956(defvar ido-work-directory-index)
957
958;; Stores current index in ido-work-file-list.
959(defvar ido-work-file-index)
960
961;; Set when merged work directory list is in use.
962(defvar ido-use-merged-list)
963
964;; Set when merged work directory list not yet built.
965(defvar ido-try-merged-list)
966
967;; Saved state prior to last work directory merge.
968;; Value is a list (ido-text dir cur-list ignored-list matches).
969(defvar ido-pre-merge-state)
970
310682e6
KS
971;; Original value of vc-handled-backends for use in ido-toggle-vc.
972(defvar ido-saved-vc-hb)
789d1bf0
KS
973
974;; Stores temporary state of literal find file.
975(defvar ido-find-literal)
976
977
978;;; FUNCTIONS
979
980(defun ido-active (&optional merge)
981 (if merge
982 ido-use-merged-list
983 (and (boundp 'ido-completing-read) (= ido-use-mycompletion-depth (minibuffer-depth)))))
984
985(defvar ido-trace-enable nil)
986
987(defun ido-trace (p &optional s retval)
988 (if ido-trace-enable
989 (let ((b (get-buffer-create " *IDO Trace*"))
990 (deactivate-mark deactivate-mark))
991 (save-excursion
992 (save-restriction
993 (set-buffer b)
994 (insert p ": " (if (stringp s) s (format "%S" s)) "\n")))))
995 retval)
996
997(defun ido-toggle-trace (arg)
998 (interactive "P")
999 (setq ido-trace-enable (or arg (not ido-trace-enable)))
bad111c2
KS
1000 (if ido-trace-enable
1001 (message "IDO trace on"))
789d1bf0
KS
1002 (let ((b (get-buffer " *IDO Trace*")))
1003 (if b
1004 (if ido-trace-enable
1005 (kill-buffer b)
bad111c2
KS
1006 (pop-to-buffer b t t)
1007 (setq truncate-lines t)))))
1008
1009(defun ido-is-tramp-root (&optional dir)
1010 (setq dir (or dir ido-current-directory))
1011 (and ido-enable-tramp-completion
1012 (string-match "\\`/[^/][^/]+:\\([^/:@]+@\\)?\\'" dir)))
789d1bf0
KS
1013
1014(defun ido-is-root-directory (&optional dir)
1015 (setq dir (or dir ido-current-directory))
bad111c2
KS
1016 (or
1017 (string-equal "/" dir)
1018 (and (memq system-type '(windows-nt ms-dos))
1019 (string-match "\\`[a-zA-Z]:[/\\]\\'" dir))
1020 (if ido-enable-tramp-completion
1021 (ido-is-tramp-root dir)
1022 (string-match "\\`/[^:/][^:/]+:\\'" dir))))
789d1bf0
KS
1023
1024(defun ido-is-ftp-directory (&optional dir)
71296446 1025 (string-match
bad111c2
KS
1026 (if ido-enable-tramp-completion
1027 "\\`/[^/:][^/:]+:" ;; like tramp-file-name-regexp-unified, but doesn't match single drive letters
1028 "\\`/[^/:][^/:]+:/")
1029 (or dir ido-current-directory)))
789d1bf0
KS
1030
1031(defun ido-is-slow-ftp-host (&optional dir)
1032 (and (or ido-slow-ftp-hosts ido-slow-ftp-host-regexps)
1033 (setq dir (or dir ido-current-directory))
1034 ;; (featurep 'ange-ftp)
1035 ;; (ange-ftp-ftp-name dir)
71296446 1036 (string-match
bad111c2
KS
1037 (if ido-enable-tramp-completion
1038 "\\`/\\([^/]+[@:]\\)*\\([^@/:][^@/:]+\\):"
1039 "\\`/\\([^/:]*@\\)?\\([^@/:][^@/:]+\\):/")
1040 dir)
789d1bf0
KS
1041 (let ((host (substring dir (match-beginning 2) (match-end 2))))
1042 (or (member host ido-slow-ftp-hosts)
1043 (let ((re ido-slow-ftp-host-regexps))
1044 (while (and re (not (string-match (car re) host)))
1045 (setq re (cdr re)))
1046 re)))))
1047
1048(defun ido-time-stamp (&optional time)
1049 ;; Time is a floating point number (fractions of 1 hour)
1050 (setq time (or time (current-time)))
1051 (/ (+ (* (car time) 65536.0) (car (cdr time))) 3600.0))
1052
1053(defun ido-cache-ftp-valid (&optional time)
1054 (and (numberp ido-cache-ftp-work-directory-time)
1055 (> ido-cache-ftp-work-directory-time 0)
1056 (or (not time)
1057 (< (- (ido-time-stamp) time) ido-cache-ftp-work-directory-time))))
1058
1059(defun ido-may-cache-directory (&optional dir)
1060 (setq dir (or dir ido-current-directory))
bad111c2
KS
1061 (cond
1062 ((and (ido-is-root-directory dir)
1063 (or ido-enable-tramp-completion
1064 (memq system-type '(windows-nt ms-dos))))
1065 nil)
1066 ((not (ido-is-ftp-directory dir))
1067 t)
1068 ((ido-cache-ftp-valid)
1069 t)))
789d1bf0
KS
1070
1071(defun ido-pp (list &optional sep)
1072 (let ((print-level nil) (eval-expression-print-level nil)
1073 (print-length nil) (eval-expression-print-length nil))
1074 (insert "\n;; ----- " (symbol-name list) " -----\n(\n ")
1075 (setq list (symbol-value list))
1076 (while list
1077 (let* ((elt (car list))
1078 (s (if (consp elt) (car elt) elt)))
1079 (if (and (stringp s) (= (length s) 0))
1080 (setq s nil))
1081 (if s
1082 (prin1 elt (current-buffer)))
1083 (if (and (setq list (cdr list)) s)
1084 (insert (or sep "\n ")))))
1085 (insert "\n)\n")))
1086
1087(defun ido-save-history ()
1088 "Save ido history and cache information between sessions."
1089 (interactive)
1090 (if (and ido-last-directory-list ido-save-directory-list-file)
1091 (save-excursion
1092 (save-window-excursion
1093 (if (find-buffer-visiting ido-save-directory-list-file)
1094 (kill-buffer (find-buffer-visiting ido-save-directory-list-file)))
1095 (if (file-exists-p ido-save-directory-list-file)
1096 (delete-file ido-save-directory-list-file))
1097 (set-buffer (let ((enable-local-variables nil))
1098 (find-file-noselect ido-save-directory-list-file t)))
1099 (goto-char (point-min))
1100 (delete-region (point-min) (point-max))
1101 (ido-pp 'ido-last-directory-list)
1102 (ido-pp 'ido-work-directory-list)
1103 (ido-pp 'ido-work-file-list)
1104 (ido-pp 'ido-dir-file-cache "\n\n ")
1105 (insert "\n")
1106 (let ((version-control 'never))
1107 (write-file ido-save-directory-list-file nil))
1108 (kill-buffer (current-buffer))))))
1109
1110(defun ido-load-history (&optional arg)
1111 "Load ido history and cache information from previous session.
1112With prefix argument, reload history unconditionally."
1113 (interactive "P")
1114 (if (or arg (and ido-save-directory-list-file (not ido-last-directory-list)))
1115 (let ((file (expand-file-name ido-save-directory-list-file))
1116 buf)
1117 (when (file-readable-p file)
1118 (save-excursion
1119 (save-window-excursion
1120 (setq buf (set-buffer (let ((enable-local-variables nil))
1121 (find-file-noselect file))))
1122 (goto-char (point-min))
1123 (condition-case nil
1124 (setq ido-last-directory-list (read (current-buffer))
1125 ido-work-directory-list (read (current-buffer))
1126 ido-work-file-list (read (current-buffer))
1127 ido-dir-file-cache (read (current-buffer)))
1128 (error nil))))
1129 (kill-buffer buf))))
1130 (ido-wash-history))
1131
1132(defun ido-wash-history ()
1133 "Clean-up ido history and cache information.
1134Removes badly formatted data and ignored directories."
1135 (interactive)
1136 ;; Check format of each of our lists, discard bogus elements
1137 (setq ido-last-directory-list
1138 (and (listp ido-last-directory-list)
1139 (let ((l ido-last-directory-list) r)
1140 (while l
1141 (if (and (consp (car l))
1142 (stringp (car (car l)))
1143 (stringp (cdr (car l))))
1144 (setq r (cons (car l) r)))
1145 (setq l (cdr l)))
1146 (nreverse r))))
71296446 1147 (setq ido-work-directory-list
789d1bf0
KS
1148 (and (listp ido-work-directory-list)
1149 (let ((l ido-work-directory-list) r)
1150 (while l
1151 (if (and (stringp (car l))
1152 (or ido-record-ftp-work-directories
1153 (not (ido-is-ftp-directory (car l)))))
1154 (setq r (cons (car l) r)))
1155 (setq l (cdr l)))
1156 (nreverse r))))
71296446 1157 (setq ido-work-file-list
789d1bf0
KS
1158 (and (listp ido-work-file-list)
1159 (let ((l ido-work-file-list) r)
1160 (while l
1161 (if (stringp (car l))
1162 (setq r (cons (car l) r)))
1163 (setq l (cdr l)))
1164 (nreverse r))))
71296446 1165 (setq ido-dir-file-cache
789d1bf0
KS
1166 (and (listp ido-dir-file-cache)
1167 (let ((l ido-dir-file-cache) r)
1168 (while l
1169 (if (and (listp (car l))
1170 (> (length (car l)) 2)
1171 (let ((dir (car (car l)))
1172 (time (car (cdr (car l))))
1173 (files (cdr (cdr (car l)))))
1174 (and
1175 (stringp dir)
1176 (consp time)
1177 (if (integerp (car time))
1178 (and (/= (car time) 0)
1179 (integerp (car (cdr time)))
1180 (/= (car (cdr time)) 0)
1181 (ido-may-cache-directory dir))
1182 (and (eq (car time) 'ftp)
1183 (numberp (cdr time))
1184 (ido-is-ftp-directory dir)
1185 (ido-cache-ftp-valid (cdr time))))
1186 (let ((s files) (ok t))
1187 (while s
1188 (if (stringp (car s))
1189 (setq s (cdr s))
1190 (setq s nil ok nil)))
1191 ok))))
1192 (setq r (cons (car l) r)))
1193 (setq l (cdr l)))
1194 (nreverse r))))
1195
1196 ;; Remove ignored directories from work directory list
1197 ;; according to ido-work-directory-list-ignore-regexps
1198 (if ido-work-directory-list
1199 (let ((dirs (reverse ido-work-directory-list)))
1200 (setq ido-work-directory-list nil)
1201 (while dirs
1202 (ido-record-work-directory (car dirs))
1203 (setq dirs (cdr dirs)))))
1204 ;; Get rid of text properties
1205 (let ((l ido-last-directory-list) e)
1206 (while l
1207 (setq e (car l) l (cdr l))
1208 (set-text-properties 0 (length (car e)) nil (car e))
1209 (set-text-properties 0 (length (cdr e)) nil (cdr e))))
1210 (let ((l ido-work-directory-list) e)
1211 (while l
1212 (setq e (car l) l (cdr l))
1213 (set-text-properties 0 (length e) nil e)))
1214 (let ((l ido-work-file-list) e)
1215 (while l
1216 (setq e (car l) l (cdr l))
1217 (set-text-properties 0 (length e) nil e)))
1218 (let ((l ido-dir-file-cache) e d)
1219 (while l
1220 (setq e (car l) l (cdr l))
1221 (if (listp e)
1222 (while e
1223 (setq d (car e) e (cdr e))
1224 (if (not (consp d))
1225 (set-text-properties 0 (length d) nil d))))))
1226)
1227
1228
1229(defun ido-kill-emacs-hook ()
1230 ;; ido kill emacs hook
1231 (ido-save-history))
1232
1233(defvar ido-minor-mode-map-entry nil)
1234
1235;;;###autoload
b0df3884 1236(defun ido-mode (&optional arg)
789d1bf0
KS
1237 "Toggle ido speed-ups on or off.
1238With ARG, turn ido speed-up on if arg is positive, off otherwise.
b0df3884
KS
1239Turning on ido-mode will remap (via a minor-mode keymap) the default
1240keybindings for the `find-file' and `switch-to-buffer' families of
1241commands to the ido versions of these functions.
1242However, if ARG arg equals 'files, remap only commands for files, or
1243if it equals 'buffers, remap only commands for buffer switching.
789d1bf0
KS
1244This function also adds a hook to the minibuffer."
1245 (interactive "P")
1246 (setq ido-mode
71296446 1247 (cond
789d1bf0
KS
1248 ((null arg) (if ido-mode nil 'both))
1249 ((eq arg t) 'both)
1250 ((eq arg 'files) 'file)
1251 ((eq arg 'buffers) 'buffer)
1252 ((memq arg '(file buffer both)) arg)
1253 ((> (prefix-numeric-value arg) 0) 'both)
1254 (t nil)))
1255
1256 (ido-everywhere (if ido-everywhere 1 -1))
1257
1258 (when ido-mode
1259 (add-hook 'minibuffer-setup-hook 'ido-minibuffer-setup)
1260 (add-hook 'choose-completion-string-functions 'ido-choose-completion-string)
1261 (ido-load-history)
1262
1263 (add-hook 'kill-emacs-hook 'ido-kill-emacs-hook)
1264
1265 (unless ido-minor-mode-map-entry
1266 (setq ido-minor-mode-map-entry (cons 'ido-mode (make-sparse-keymap)))
1267 (add-to-list 'minor-mode-map-alist ido-minor-mode-map-entry))
1268
1269 (let ((map (cdr ido-minor-mode-map-entry)))
1270 (when (memq ido-mode '(file both))
1271 (define-key map [remap find-file] 'ido-find-file)
1272 (define-key map [remap find-file-read-only] 'ido-find-file-read-only)
1273 (define-key map [remap find-alternate-file] 'ido-find-alternate-file)
1274 (define-key map [remap write-file] 'ido-write-file)
1275 (define-key map [remap insert-file] 'ido-insert-file)
1276 (define-key map [remap list-directory] 'ido-list-directory)
1277 (define-key map [remap dired] 'ido-dired)
1278 (define-key map [remap find-file-other-window] 'ido-find-file-other-window)
1279 (define-key map [remap find-file-read-only-other-window] 'ido-find-file-read-only-other-window)
1280 (define-key map [remap find-file-other-frame] 'ido-find-file-other-frame)
1281 (define-key map [remap find-file-read-only-other-frame] 'ido-find-file-read-only-other-frame))
1282
1283 (when (memq ido-mode '(buffer both))
1284 (define-key map [remap switch-to-buffer] 'ido-switch-buffer)
1285 (define-key map [remap switch-to-buffer-other-window] 'ido-switch-buffer-other-window)
1286 (define-key map [remap switch-to-buffer-other-frame] 'ido-switch-buffer-other-frame)
1287 (define-key map [remap insert-buffer] 'ido-insert-buffer)
1288 (define-key map [remap kill-buffer] 'ido-kill-buffer)
1289 (define-key map [remap display-buffer] 'ido-display-buffer)))))
1290
1291(defun ido-everywhere (arg)
1292 "Enable ido everywhere file and directory names are read."
1293 (interactive "P")
1294 (setq ido-everywhere (if arg
71296446 1295 (> (prefix-numeric-value arg) 0)
789d1bf0 1296 (not ido-everywhere)))
71296446 1297 (setq read-file-name-function
789d1bf0
KS
1298 (and ido-everywhere (memq ido-mode '(both file))
1299 'ido-read-file-name))
1300 (setq read-buffer-function
1301 (and ido-everywhere (memq ido-mode '(both buffer))
1302 'ido-read-buffer)))
1303
1304
71296446 1305;;; IDO KEYMAP
789d1bf0
KS
1306(defun ido-define-mode-map ()
1307 "Set up the keymap for `ido'."
1308 (let (map)
1309 ;; generated every time so that it can inherit new functions.
1310
1311 (setq map (copy-keymap minibuffer-local-map))
1312 (define-key map "\C-a" 'ido-toggle-ignore)
1313 (define-key map "\C-c" 'ido-toggle-case)
1314 (define-key map "\C-e" 'ido-edit-input)
1315 (define-key map "\t" 'ido-complete)
030fa15b 1316 (define-key map " " 'ido-complete-space)
789d1bf0
KS
1317 (define-key map "\C-j" 'ido-select-text)
1318 (define-key map "\C-m" 'ido-exit-minibuffer)
1319 (define-key map "\C-p" 'ido-toggle-prefix)
1320 (define-key map "\C-r" 'ido-prev-match)
1321 (define-key map "\C-s" 'ido-next-match)
1322 (define-key map "\C-t" 'ido-toggle-regexp)
1323 (define-key map "\C-z" 'ido-undo-merge-work-directory)
08bfde76
KS
1324 (define-key map [(control ? )] 'ido-restrict-to-matches)
1325 (define-key map [(control ?@)] 'ido-restrict-to-matches)
789d1bf0
KS
1326 (define-key map [right] 'ido-next-match)
1327 (define-key map [left] 'ido-prev-match)
1328 (define-key map "?" 'ido-completion-help)
1329
1330 (when (memq ido-cur-item '(file dir))
1331 (define-key map "\C-b" 'ido-enter-switch-buffer)
1332 (define-key map "\C-d" 'ido-enter-dired)
1333 (define-key map "\C-f" 'ido-fallback-command)
1334 (define-key map [down] 'ido-next-match-dir)
1335 (define-key map [up] 'ido-prev-match-dir)
1336 (define-key map [(meta up)] 'ido-prev-work-directory)
1337 (define-key map [(meta down)] 'ido-next-work-directory)
1338 (define-key map [backspace] 'ido-delete-backward-updir)
1339 (define-key map "\d" 'ido-delete-backward-updir)
1340 (define-key map [(meta backspace)] 'ido-delete-backward-word-updir)
1341 (define-key map [(control backspace)] 'ido-up-directory)
b0df3884 1342 (define-key map "\C-l" 'ido-reread-directory)
789d1bf0
KS
1343 (define-key map [(meta ?b)] 'ido-next-work-file)
1344 (define-key map [(meta ?d)] 'ido-wide-find-dir)
1345 (define-key map [(meta ?f)] 'ido-wide-find-file)
1346 (define-key map [(meta ?k)] 'ido-forget-work-directory)
1347 (define-key map [(meta ?m)] 'ido-make-directory)
1348 (define-key map [(meta ?n)] 'ido-next-work-directory)
1349 (define-key map [(meta ?o)] 'ido-prev-work-file)
1350 (define-key map [(meta ?p)] 'ido-prev-work-directory)
1351 (define-key map [(meta ?s)] 'ido-merge-work-directories)
1352 )
1353
1354 (when (eq ido-cur-item 'file)
1355 (define-key map "\C-k" 'ido-delete-file-at-head)
1356 (define-key map "\C-o" 'ido-copy-current-word)
789d1bf0
KS
1357 (define-key map "\C-w" 'ido-copy-current-file-name)
1358 (define-key map [(meta ?l)] 'ido-toggle-literal)
1359 (define-key map "\C-v" 'ido-toggle-vc)
1360 )
1361
1362 (when (eq ido-cur-item 'buffer)
1363 (define-key map "\C-b" 'ido-fallback-command)
1364 (define-key map "\C-f" 'ido-enter-find-file)
1365 (define-key map "\C-k" 'ido-kill-buffer-at-head)
1366 )
1367
f0a73ccc 1368 (when (if (boundp 'viper-mode) viper-mode)
9f781d7e
KS
1369 (define-key map [remap viper-intercept-ESC-key] 'ignore)
1370 (when (memq ido-cur-item '(file dir))
1371 (define-key map [remap viper-backward-char] 'ido-delete-backward-updir)
1372 (define-key map [remap viper-del-backward-char-in-insert] 'ido-delete-backward-updir)
1373 (define-key map [remap viper-delete-backward-word] 'ido-delete-backward-word-updir)))
f0a73ccc 1374
789d1bf0
KS
1375 (setq ido-mode-map map)
1376 (run-hooks 'ido-define-mode-map-hook)))
1377
1378(defun ido-final-slash (dir &optional fix-it)
1379 ;; return DIR if DIR has final slash.
1380 ;; else if FIX-IT is non-nil, return DIR/
1381 ;; else return nil.
1382 (setq dir (ido-name dir))
1383 (cond
1384 ((string-match "/\\'" dir) dir)
bad111c2 1385 ((ido-is-tramp-root dir) dir)
789d1bf0
KS
1386 (fix-it (concat dir "/"))
1387 (t nil)))
1388
310682e6
KS
1389(defun ido-no-final-slash (s)
1390 ;; Remove optional final slash from string S
1391 (let ((l (1- (length s))))
1392 (if (and (> l 0) (eq (aref s l) ?/))
1393 (substring s 0 l)
1394 s)))
1395
789d1bf0
KS
1396(defun ido-set-current-directory (dir &optional subdir no-merge)
1397 ;; Set ido's current directory to DIR or DIR/SUBDIR
1398 (setq dir (ido-final-slash dir t))
1399 (setq ido-use-merged-list nil
1400 ido-try-merged-list (not no-merge))
1401 (if subdir
1402 (setq dir (ido-final-slash (concat dir subdir) t)))
1403 (if (equal dir ido-current-directory)
1404 nil
1405 (ido-trace "cd" dir)
1406 (setq ido-current-directory dir)
1407 (if (get-buffer ido-completion-buffer)
1408 (kill-buffer ido-completion-buffer))
1409 t))
1410
1411(defun ido-set-current-home (&optional dir)
1412 ;; Set ido's current directory to user's home directory
1413 (ido-set-current-directory (expand-file-name (or dir "~/"))))
1414
1415(defun ido-record-command (command arg)
1416 ;; Add (command arg) to command-history if ido-record-commands is t
1417 (if ido-record-commands
1418 (let ((cmd (list command arg)))
1419 (if (or (not command-history)
1420 (not (equal cmd (car command-history))))
1421 (setq command-history (cons cmd command-history))))))
1422
1423(defun ido-make-prompt (item prompt)
1424 ;; Make the prompt for ido-read-internal
1425 (cond
1426 ((and (memq item '(file dir)) ido-current-directory)
362cdb61 1427 (let ((dirname (abbreviate-file-name ido-current-directory))
a42e9704
KS
1428 (max-width (if (and ido-max-file-prompt-width (floatp ido-max-file-prompt-width))
1429 (floor (* (frame-width) ido-max-file-prompt-width))
1430 ido-max-file-prompt-width))
789d1bf0 1431 (literal (and (boundp 'ido-find-literal) ido-find-literal "(literal) "))
310682e6 1432 (vc-off (and ido-saved-vc-hb (not vc-handled-backends) "[-VC] "))
789d1bf0 1433 (prefix nil)
362cdb61 1434 (rule ido-rewrite-file-prompt-rules))
789d1bf0
KS
1435 (let ((case-fold-search nil))
1436 (while rule
1437 (if (and (consp (car rule))
362cdb61
KS
1438 (string-match (car (car rule)) dirname))
1439 (setq dirname
789d1bf0 1440 (if (stringp (cdr (car rule)))
362cdb61
KS
1441 (replace-match (cdr (car rule)) t nil dirname)
1442 (funcall (cdr (car rule)) dirname))))
789d1bf0 1443 (setq rule (cdr rule))))
362cdb61 1444 (run-hooks 'ido-rewrite-file-prompt-functions)
71296446 1445 (concat prompt
789d1bf0
KS
1446 ; (if ido-process-ignore-lists "" "&")
1447 (or literal "")
1448 (or vc-off "")
1449 (or prefix "")
362cdb61 1450 (let ((l (length dirname)))
789d1bf0 1451 (if (and max-width (> max-width 0) (> l max-width))
71296446 1452 (let* ((s (substring dirname (- max-width)))
789d1bf0
KS
1453 (i (string-match "/" s)))
1454 (concat "..." (if i (substring s i) s)))
362cdb61 1455 dirname)))))
789d1bf0
KS
1456 (t prompt)))
1457
1458;; Here is very briefly how ido-find-file works:
1459;;
1460;; (ido-find-file)
1461;; (ido-file-internal method)
1462;; set ido-current-directory
1463;; (ido-read-internal 'file ...)
1464;; (while ...
1465;; (ido-make-item-list ...)
1466;; (ido-set-matches)
1467;; (completing-read ... ido-text-init ...)
1468;;
1469;; ... here user is allowed to type characters and commands
1470;; a command may set ido-exit and call (exit-minibuffer)
1471;; to make ido-read-internal do advanced tasks (or return)
1472;;
1473;; ... ido-tidy and ido-exhibit are pre- and post-hooks
1474;; which are run before and after each user command.
1475;;
1476;; return value from completing-read is stored in ido-final-text
1477;; - ido-exit may cause further actions to be taken:
1478;; 'refresh - repeat loop (make-item-list, set-matches)
1479;; 'edit - edit the prompt string, then repeat loop
1480;; 'keep - repeat loop but don't (re)make-item-list
1481;; 'updir - go up one directory, repeat loop
1482;; else set ido-selected based on ido-final-text,
1483;; optionally update ido-current-directory and repeat loop, or
1484;; exit with the return value of ido-selected (file name)
1485;; selected file name is returned from ido-read-internal,
1486;; ido-exit and method determines what action is taken
1487;; e.g. the file name may be ignored or joined with ido-current-directory, and
1488;; the relevant function is called (find-file, write-file, etc).
1489
1490(defun ido-read-internal (item prompt history &optional default require-match initial)
1491 "Perform the ido-read-buffer and ido-read-file-name functions.
71296446 1492Return the name of a buffer or file selected.
789d1bf0
KS
1493PROMPT is the prompt to give to the user.
1494DEFAULT if given is the default directory to start with.
1495If REQUIRE-MATCH is non-nil, an existing file must be selected.
1496If INITIAL is non-nil, it specifies the initial input string."
1497 (let
1498 ((ido-cur-item item)
1499 (ido-entry-buffer (current-buffer))
1500 (ido-process-ignore-lists t)
1501 (ido-process-ignore-lists-inhibit nil)
1502 (ido-set-default-item t)
1503 ido-default-item
1504 ido-selected
1505 ido-final-text
1506 (done nil)
1507 (icomplete-mode nil) ;; prevent icomplete starting up
1508 ;; Exported dynamic variables:
1509 ido-cur-list
1510 ido-ignored-list
1511 (ido-rotate-temp nil)
1512 (ido-keep-item-list nil)
1513 (ido-use-merged-list nil)
1514 (ido-try-merged-list t)
1515 (ido-pre-merge-state nil)
1516 (ido-case-fold ido-case-fold)
1517 (ido-enable-prefix ido-enable-prefix)
1518 (ido-enable-regexp ido-enable-regexp)
1519 )
1520
1521 (ido-define-mode-map)
1522 (setq ido-text-init initial)
1523 (while (not done)
bad111c2 1524 (ido-trace "\n_LOOP_" ido-text-init)
789d1bf0
KS
1525 (setq ido-exit nil)
1526 (setq ido-rescan t)
1527 (setq ido-rotate nil)
1528 (setq ido-text "")
69beb26d
KS
1529 (when ido-set-default-item
1530 (setq ido-default-item
1531 (cond
1532 ((eq item 'buffer)
1533 (if (bufferp default) (buffer-name default) default))
1534 ((stringp default) default)
1535 ((eq item 'file)
71296446 1536 (and ido-enable-last-directory-history
69beb26d
KS
1537 (let ((d (assoc ido-current-directory ido-last-directory-list)))
1538 (and d (cdr d)))))))
1539 (if (member ido-default-item ido-ignore-item-temp-list)
1540 (setq ido-default-item nil))
1541 (setq ido-set-default-item nil))
789d1bf0
KS
1542
1543 (if ido-process-ignore-lists-inhibit
1544 (setq ido-process-ignore-lists nil))
1545
1546 (if (and ido-use-merged-list (memq ido-try-merged-list '(t wide)) (not ido-keep-item-list))
1547 (let ((olist ido-cur-list)
1548 (oign ido-ignored-list)
1549 (omat ido-matches)
1550 (l (ido-make-merged-file-list ido-text-init
1551 (eq ido-use-merged-list 'auto)
1552 (eq ido-try-merged-list 'wide))))
1553 (cond
1554 ((not l)
1555 (if (eq ido-try-merged-list 'wide)
1556 (setq ido-pre-merge-state
1557 (list "" ido-current-directory olist oign omat)
1558 ido-cur-list nil
1559 ido-ignored-list nil
1560 ido-matches nil
1561 ido-keep-item-list t
1562 ido-try-merged-list (if (eq ido-use-merged-list 'auto) 'auto nil)
1563 ido-use-merged-list nil)
1564 (setq ido-cur-list olist
1565 ido-ignored-list oign
1566 ido-matches omat
1567 ido-keep-item-list t
1568 ido-try-merged-list (if (eq ido-use-merged-list 'auto) 'auto nil)
1569 ido-use-merged-list nil)))
1570 ((eq l t)
1571 (setq ido-use-merged-list nil))
1572 (t
1573 (setq ido-pre-merge-state
1574 (list ido-text-init ido-current-directory olist oign omat))
1575 (ido-set-current-directory (car (cdr (car l))))
1576 (if (ido-final-slash ido-text-init)
1577 (setq ido-text-init ""))
1578 (setq ido-cur-list l
1579 ido-ignored-list nil
1580 ido-matches l
1581 ido-rescan nil
1582 ido-keep-item-list t
1583 ido-use-merged-list t)
1584 (ido-trace "Merged" t)
1585 ))))
71296446 1586
789d1bf0
KS
1587 (cond
1588 (ido-keep-item-list
1589 (setq ido-keep-item-list nil
1590 ido-rescan nil))
1591 ((eq ido-cur-item 'file)
1592 (setq ido-ignored-list nil
1593 ido-cur-list (ido-make-file-list ido-default-item)))
1594 ((eq ido-cur-item 'dir)
1595 (setq ido-ignored-list nil
1596 ido-cur-list (ido-make-dir-list ido-default-item)))
1597 ((eq ido-cur-item 'buffer)
1598 (setq ido-ignored-list nil
1599 ido-cur-list (ido-make-buffer-list ido-default-item)))
1600 (t nil))
1601 (setq ido-rotate-temp nil)
1602
1603 (if ido-process-ignore-lists-inhibit
1604 (setq ido-process-ignore-lists t
1605 ido-process-ignore-lists-inhibit nil))
1606
1607 (ido-set-matches)
1608 (if (and ido-matches (eq ido-try-merged-list 'auto))
1609 (setq ido-try-merged-list t))
71296446 1610 (let
789d1bf0
KS
1611 ((minibuffer-local-completion-map ido-mode-map)
1612 (max-mini-window-height (or ido-max-window-height
1613 (and (boundp 'max-mini-window-height) max-mini-window-height)))
1614 (ido-completing-read t)
1615 (ido-require-match require-match)
1616 (ido-use-mycompletion-depth (1+ (minibuffer-depth)))
1617 (show-paren-mode nil))
1618 ;; prompt the user for the file name
1619 (setq ido-exit nil)
1620 (setq ido-final-text
1621 (catch 'ido
71296446 1622 (completing-read
789d1bf0 1623 (ido-make-prompt item prompt)
9066a4d0 1624 '(("dummy" . 1)) nil nil ; table predicate require-match
789d1bf0
KS
1625 (prog1 ido-text-init (setq ido-text-init nil)) ;initial-contents
1626 history))))
1627 (ido-trace "completing-read" ido-final-text)
1628 (if (get-buffer ido-completion-buffer)
1629 (kill-buffer ido-completion-buffer))
1630
1631 (ido-trace "\n_EXIT_" ido-exit)
1632
1633 (cond
1634 ((eq ido-exit 'refresh)
71296446 1635 (if (and (eq ido-use-merged-list 'auto)
789d1bf0
KS
1636 (or (input-pending-p)))
1637 (setq ido-use-merged-list nil
1638 ido-keep-item-list t))
1639 nil)
1640
1641 ((eq ido-exit 'done)
1642 (setq done t
1643 ido-selected ido-text
1644 ido-exit nil))
1645
1646 ((memq ido-exit '(edit chdir))
71296446 1647 (cond
789d1bf0
KS
1648 ((memq ido-cur-item '(file dir))
1649 (let* ((process-environment (cons "HOME=/" process-environment)) ;; cheat read-file-name
1650 (read-file-name-function nil)
1651 (edit (eq ido-exit 'edit))
1652 (d ido-current-directory)
1653 (f ido-text-init)
84f6c6d0 1654 (new t))
789d1bf0 1655 (setq ido-text-init "")
84f6c6d0
KS
1656 (while new
1657 (setq new (if edit
789d1bf0
KS
1658 (read-file-name (concat prompt "[EDIT] ") d (concat d f) nil f)
1659 f)
84f6c6d0
KS
1660 d (or (file-name-directory new) "/")
1661 f (file-name-nondirectory new)
789d1bf0 1662 edit t)
71296446 1663 (if (or
789d1bf0
KS
1664 (file-directory-p d)
1665 (and (yes-or-no-p (format "Create directory %s? " d))
71296446 1666 (condition-case nil
789d1bf0
KS
1667 (progn (make-directory d t) t)
1668 (error
1669 (message "Could not create directory")
1670 (sit-for 1)
1671 nil))))
1672 (progn
1673 (ido-set-current-directory d nil (eq ido-exit 'chdir))
1674 (setq ido-text-init f
84f6c6d0 1675 new nil))))))
789d1bf0 1676 (t
789d1bf0
KS
1677 (setq ido-text-init (read-string (concat prompt "[EDIT] ") ido-final-text))))
1678 nil)
1679
1680 ((eq ido-exit 'keep)
1681 (setq ido-keep-item-list t))
1682
1683 ((memq ido-exit '(dired fallback findfile findbuffer))
1684 (setq done t))
1685
1686 ((eq ido-exit 'updir)
1687 ;; cannot go up if already at the root-dir (Unix) or at the
1688 ;; root-dir of a certain drive (Windows or MS-DOS).
bad111c2
KS
1689 (if (ido-is-tramp-root)
1690 (when (string-match "\\`\\(/\\([^/]+[:@]\\)*\\)\\([^/]+\\)[:@]\\'" ido-current-directory)
1691 (setq ido-text-init (match-string 3 ido-current-directory))
1692 (ido-set-current-directory (match-string 1 ido-current-directory))
1693 (setq ido-set-default-item t))
1694 (unless (ido-is-root-directory)
1695 (ido-set-current-directory (file-name-directory (substring ido-current-directory 0 -1)))
1696 (setq ido-set-default-item t))))
789d1bf0
KS
1697
1698 ;; Handling the require-match must be done in a better way.
1699 ((and require-match (not (ido-existing-item-p)))
1700 (error "must specify valid item"))
1701
1702 (t
1703 (setq ido-selected
69beb26d
KS
1704 (if (or (eq ido-exit 'takeprompt)
1705 (null ido-matches))
1706 ido-final-text
1707 ;; else take head of list
1708 (ido-name (car ido-matches))))
789d1bf0
KS
1709
1710 (cond
1711 ((eq item 'buffer)
1712 (setq done t))
1713
1714 ((string-equal "./" ido-selected)
1715 nil)
1716
1717 ((string-equal "../" ido-selected)
1718 ;; cannot go up if already at the root-dir (Unix) or at the
1719 ;; root-dir of a certain drive (Windows or MS-DOS).
1720 (or (ido-is-root-directory)
1721 (ido-set-current-directory (file-name-directory (substring ido-current-directory 0 -1))))
1722 (setq ido-set-default-item t))
bad111c2
KS
1723
1724 ((and (string-match (if ido-enable-tramp-completion "..[:@]\\'" "..:\\'") ido-selected)
1725 (ido-is-root-directory)) ;; Ange-ftp or Tramp
1726 (ido-set-current-directory ido-current-directory ido-selected)
1727 (ido-trace "tramp prefix" ido-selected)
789d1bf0
KS
1728 (if (ido-is-slow-ftp-host)
1729 (setq ido-exit 'fallback
1730 done t)
1731 (setq ido-set-default-item t)))
789d1bf0
KS
1732 ((or (string-match "[/\\][^/\\]" ido-selected)
1733 (and (memq system-type '(windows-nt ms-dos))
1734 (string-match "\\`.:" ido-selected)))
1735 (ido-set-current-directory (file-name-directory ido-selected))
1736 (setq ido-set-default-item t))
1737
1738 ((string-match "\\`~" ido-selected)
1739 (ido-set-current-home ido-selected))
1740
1741 ((ido-final-slash ido-selected)
1742 (if ido-enable-last-directory-history
1743 (let ((x (assoc ido-current-directory ido-last-directory-list)))
1744 (if x
1745 (setcdr x ido-selected)
1746 (setq ido-last-directory-list
1747 (cons (cons ido-current-directory ido-selected) ido-last-directory-list)))))
1748 (ido-set-current-directory ido-current-directory ido-selected)
1749 (setq ido-set-default-item t))
1750
1751 (t
1752 (setq done t))))))
1753 ido-selected))
1754
1755(defun ido-edit-input ()
362cdb61 1756 "Edit absolute file name entered so far with ido; terminate by RET."
789d1bf0
KS
1757 (interactive)
1758 (setq ido-text-init ido-text)
1759 (setq ido-exit 'edit)
1760 (exit-minibuffer))
1761
1762;;; MAIN FUNCTIONS
1763(defun ido-buffer-internal (method &optional fallback prompt default initial)
1764 ;; Internal function for ido-switch-buffer and friends
1765 (if (not ido-mode)
1766 (call-interactively (or fallback 'switch-to-buffer))
1767 (let ((buf (ido-read-buffer (or prompt "Buffer: ") default nil initial)))
1768
1769 ;; Choose the buffer name: either the text typed in, or the head
1770 ;; of the list of matches
1771
71296446 1772 (cond
789d1bf0
KS
1773 ((eq ido-exit 'findfile)
1774 (ido-file-internal ido-default-file-method nil nil nil nil ido-text))
1775
1776 ((eq ido-exit 'fallback)
1777 (let ((read-buffer-function nil))
1778 (call-interactively (or fallback 'switch-to-buffer))))
1779
1780 ;; Check buf is non-nil.
1781 ((not buf) nil)
69beb26d 1782 ((= (length buf) 0) nil)
789d1bf0
KS
1783
1784 ;; View buffer if it exists
1785 ((get-buffer buf)
1786 (if (eq method 'insert)
1787 (progn
1788 (ido-record-command 'insert-buffer buf)
1789 (insert-buffer buf))
1790 (ido-visit-buffer buf method t)))
1791
1792 ;; buffer doesn't exist
1793 ((eq ido-create-new-buffer 'never)
1794 (message "no buffer matching `%s'" buf))
1795
1796 ((and (eq ido-create-new-buffer 'prompt)
1797 (not (y-or-n-p (format "No buffer matching `%s', create one? " buf))))
1798 nil)
1799
1800 ;; create a new buffer
1801 (t
1802 (setq buf (get-buffer-create buf))
1803 (if (fboundp 'set-buffer-major-mode)
1804 (set-buffer-major-mode buf))
1805 (ido-visit-buffer buf method t))))))
1806
1807;;;###autoload
1808(defun ido-read-buffer (prompt &optional default require-match initial)
1809 "Replacement for the built-in `read-buffer'.
71296446 1810Return the name of a buffer selected.
789d1bf0
KS
1811PROMPT is the prompt to give to the user. DEFAULT if given is the default
1812buffer to be selected, which will go to the front of the list.
1813If REQUIRE-MATCH is non-nil, an existing-buffer must be selected.
1814If INITIAL is non-nil, it specifies the initial input string."
1815 (let ((ido-current-directory nil))
1816 (ido-read-internal 'buffer prompt 'ido-buffer-history default require-match initial)))
1817
1818(defun ido-record-work-directory (&optional dir)
1819 (when (and (numberp ido-max-work-directory-list) (> ido-max-work-directory-list 0))
1820 (if (and (setq dir (or dir ido-current-directory)) (> (length dir) 0))
1821 (let ((items ido-work-directory-list-ignore-regexps)
1822 (case-fold-search nil))
1823 (while (and items dir)
1824 (if (string-match (car items) dir)
1825 (setq dir nil))
1826 (setq items (cdr items)))
1827 (if dir
1828 (setq ido-work-directory-list (cons dir (delete dir ido-work-directory-list))))))
1829 (if (> (length ido-work-directory-list) ido-max-work-directory-list)
1830 (setcdr (nthcdr (1- ido-max-work-directory-list) ido-work-directory-list) nil))))
1831
1832(defun ido-forget-work-directory ()
1833 (interactive)
1834 (when (and ido-current-directory ido-work-directory-list)
1835 (setq ido-work-directory-list (delete ido-current-directory ido-work-directory-list))
1836 (when ido-use-merged-list
1837 (ido-undo-merge-work-directory)
1838 (setq ido-exit 'refresh
1839 ido-try-merged-list t
1840 ido-use-merged-list t
1841 ido-text-init ido-text
1842 ido-rotate-temp t)
1843 (exit-minibuffer))))
71296446 1844
789d1bf0
KS
1845(defun ido-record-work-file (name)
1846 ;; Save NAME in ido-work-file-list
1847 (when (and (numberp ido-max-work-file-list) (> ido-max-work-file-list 0))
1848 (or
1849 (and ido-work-file-list (equal (car ido-work-file-list) name))
1850 (setq ido-work-file-list (cons name (delete name ido-work-file-list))))
1851 (if (> (length ido-work-file-list) ido-max-work-file-list)
1852 (setcdr (nthcdr (1- ido-max-work-file-list) ido-work-file-list) nil))))
1853
1854(defun ido-file-internal (method &optional fallback default prompt item initial)
1855 ;; Internal function for ido-find-file and friends
310682e6
KS
1856 (unless item
1857 (setq item 'file))
789d1bf0
KS
1858 (let ((ido-current-directory (expand-file-name (or default default-directory)))
1859 filename)
1860
310682e6
KS
1861 (cond
1862 ((or (not ido-mode) (ido-is-slow-ftp-host))
1863 (setq filename t
1864 ido-exit 'fallback))
1865
1866 ((and (eq item 'file)
1867 (or ido-use-url-at-point ido-use-filename-at-point))
1868 (let (fn d)
1869 (require 'ffap)
1870 ;; Duplicate code from ffap-guesser as we want different behaviour for files and URLs.
1871 (cond
1872 ((and ido-use-url-at-point
1873 ffap-url-regexp
1874 (ffap-fixup-url (or (ffap-url-at-point)
1875 (ffap-gopher-at-point))))
1876 (setq ido-exit 'ffap
1877 filename t))
1878
1879 ((and ido-use-filename-at-point
1880 (setq fn (ffap-string-at-point))
1881 (not (string-match "^http:/" fn))
1882 (setq d (file-name-directory fn))
1883 (file-directory-p d))
1884 (setq ido-current-directory d)
1885 (setq initial (file-name-nondirectory fn)))))))
1886
1887 (let (ido-saved-vc-hb
1888 (vc-handled-backends (and (boundp 'vc-handled-backends) vc-handled-backends))
789d1bf0
KS
1889 (ido-work-directory-index -1)
1890 (ido-work-file-index -1)
1891 (ido-find-literal nil))
1892
1893 (unless filename
310682e6
KS
1894 (setq ido-saved-vc-hb vc-handled-backends)
1895 (setq filename (ido-read-internal item
789d1bf0
KS
1896 (or prompt "Find file: ")
1897 'ido-file-history nil nil initial)))
1898
1899 ;; Choose the file name: either the text typed in, or the head
1900 ;; of the list of matches
1901
1902 (cond
1903 ((eq ido-exit 'fallback)
1904 ;; Need to guard setting of default-directory here, since
1905 ;; we don't want to change directory of current buffer.
1906 (let ((default-directory ido-current-directory)
1907 (read-file-name-function nil))
1908 (call-interactively (or fallback 'find-file))))
1909
1910 ((eq ido-exit 'findbuffer)
1911 (ido-buffer-internal ido-default-buffer-method nil nil nil ido-text))
1912
1913 ((eq ido-exit 'dired)
1914 (dired (concat ido-current-directory (or ido-text ""))))
1915
310682e6
KS
1916 ((eq ido-exit 'ffap)
1917 (find-file-at-point))
1918
789d1bf0
KS
1919 ((eq method 'alt-file)
1920 (ido-record-work-file filename)
1921 (setq default-directory ido-current-directory)
1922 (ido-record-work-directory)
1923 (find-alternate-file filename))
1924
1925 ((memq method '(dired list-directory))
1926 (if (equal filename ".")
1927 (setq filename ""))
84f6c6d0
KS
1928 (let* ((dirname (ido-final-slash (concat ido-current-directory filename) t))
1929 (file (substring dirname 0 -1)))
789d1bf0 1930 (cond
84f6c6d0
KS
1931 ((file-directory-p dirname)
1932 (ido-record-command method dirname)
1933 (ido-record-work-directory dirname)
1934 (funcall method dirname))
789d1bf0
KS
1935 ((file-directory-p ido-current-directory)
1936 (cond
1937 ((file-exists-p file)
1938 (ido-record-command method ido-current-directory)
1939 (ido-record-work-directory)
1940 (funcall method ido-current-directory)
1941 (if (eq method 'dired)
1942 (dired-goto-file (expand-file-name file))))
1943 ((string-match "[[*?]" filename)
84f6c6d0
KS
1944 (setq dirname (concat ido-current-directory filename))
1945 (ido-record-command method dirname)
789d1bf0 1946 (ido-record-work-directory)
84f6c6d0 1947 (funcall method dirname))
789d1bf0 1948 ((y-or-n-p (format "Directory %s does not exist. Create it " filename))
84f6c6d0
KS
1949 (ido-record-command method dirname)
1950 (ido-record-work-directory dirname)
1951 (make-directory-internal dirname)
1952 (funcall method dirname))
789d1bf0
KS
1953 (t
1954 ;; put make-directory command on history
84f6c6d0 1955 (ido-record-command 'make-directory dirname))))
789d1bf0
KS
1956 (t (error "No such directory")))))
1957
1958 ((eq method 'write)
1959 (ido-record-work-file filename)
1960 (setq default-directory ido-current-directory)
1961 (ido-record-command 'write-file (concat ido-current-directory filename))
1962 (ido-record-work-directory)
1963 (write-file filename))
1964
1965 ((eq method 'read-only)
1966 (ido-record-work-file filename)
1967 (setq filename (concat ido-current-directory filename))
1968 (ido-record-command fallback filename)
1969 (ido-record-work-directory)
1970 (funcall fallback filename))
1971
1972 ((eq method 'insert)
1973 (ido-record-work-file filename)
1974 (setq filename (concat ido-current-directory filename))
71296446 1975 (ido-record-command
789d1bf0
KS
1976 (if ido-find-literal 'insert-file-literally 'insert-file)
1977 filename)
1978 (ido-record-work-directory)
1979 (if ido-find-literal
1980 (insert-file-contents-literally filename)
1981 (insert-file-contents filename)))
1982
1983 (filename
1984 (ido-record-work-file filename)
1985 (setq filename (concat ido-current-directory filename))
1986 (ido-record-command 'find-file filename)
1987 (ido-record-work-directory)
1988 (ido-visit-buffer (find-file-noselect filename nil ido-find-literal) method))))))
1989
1990(defun ido-existing-item-p ()
1991 ;; Return non-nil if there is a matching item
1992 (not (null ido-matches)))
1993
1994;;; COMPLETION CODE
1995
1996(defun ido-set-common-completion ()
1997 ;; Find common completion of `ido-text' in `ido-matches'
1998 ;; The result is stored in `ido-common-match-string'
1999 (let* (val)
2000 (setq ido-common-match-string nil)
2001 (if (and ido-matches
2002 (not ido-enable-regexp) ;; testing
2003 (stringp ido-text)
2004 (> (length ido-text) 0))
2005 (if (setq val (ido-find-common-substring ido-matches ido-text))
2006 (setq ido-common-match-string val)))
2007 val))
2008
2009(defun ido-complete ()
2010 "Try and complete the current pattern amongst the file names."
2011 (interactive)
2012 (let (res)
71296446 2013 (cond
789d1bf0
KS
2014 ((and (memq ido-cur-item '(file dir))
2015 (string-match "[$]" ido-text))
2016 (let ((evar (substitute-in-file-name (concat ido-current-directory ido-text))))
2017 (if (not (file-exists-p (file-name-directory evar)))
337d2b66 2018 (message "Expansion generates non-existing directory name")
789d1bf0
KS
2019 (if (file-directory-p evar)
2020 (ido-set-current-directory evar)
2021 (let ((d (or (file-name-directory evar) "/"))
2022 (f (file-name-nondirectory evar)))
2023 (when (file-directory-p d)
2024 (ido-set-current-directory d)
2025 (setq ido-text-init f))))
2026 (setq ido-exit 'refresh)
2027 (exit-minibuffer))))
2028
2029 ((not ido-matches)
2030 (when ido-completion-buffer
d1a0acac 2031 (call-interactively (setq this-command ido-cannot-complete-command))))
71296446 2032
bad111c2
KS
2033 ((and (= 1 (length ido-matches))
2034 (not (and ido-enable-tramp-completion
2035 (string-equal ido-current-directory "/")
2036 (string-match "..[@:]\\'" (car ido-matches)))))
789d1bf0
KS
2037 ;; only one choice, so select it.
2038 (exit-minibuffer))
71296446 2039
789d1bf0
KS
2040 (t ;; else there could be some completions
2041 (setq res ido-common-match-string)
2042 (if (and (not (memq res '(t nil)))
2043 (not (equal res ido-text)))
2044 ;; found something to complete, so put it in the minibuffer.
2045 (progn
2046 ;; move exact match to front if not in prefix mode
2047 (setq ido-rescan (not ido-enable-prefix))
2048 (delete-region (minibuffer-prompt-end) (point))
2049 (insert res))
2050 ;; else nothing to complete
d1a0acac 2051 (call-interactively (setq this-command ido-cannot-complete-command))
789d1bf0
KS
2052 )))))
2053
030fa15b
KS
2054(defun ido-complete-space ()
2055 "Try completion unless inserting the space makes sense."
2056 (interactive)
2057 (if (and (stringp ido-common-match-string)
2058 (stringp ido-text)
2059 (cond
2060 ((> (length ido-common-match-string) (length ido-text))
2061 (= (aref ido-common-match-string (length ido-text)) ? ))
2062 (ido-matches
2063 (let (insert-space
2064 (re (concat (regexp-quote ido-text) " "))
2065 (comp ido-matches))
2066 (while comp
2067 (if (string-match re (ido-name (car comp)))
2068 (setq comp nil insert-space t)
2069 (setq comp (cdr comp))))
2070 insert-space))
2071 (t nil)))
2072 (insert " ")
2073 (ido-complete)))
2074
789d1bf0
KS
2075(defun ido-undo-merge-work-directory (&optional text try refresh)
2076 "Undo or redo last ido directory merge operation.
2077If no merge has yet taken place, toggle automatic merging option."
2078 (interactive)
2079 (cond
2080 (ido-pre-merge-state
2081 (ido-set-current-directory (nth 1 ido-pre-merge-state))
2082 (setq ido-text-init (or text (car ido-pre-merge-state))
2083 ido-cur-list (nth 2 ido-pre-merge-state)
2084 ido-ignored-list (nth 3 ido-pre-merge-state)
2085 ido-matches (nth 4 ido-pre-merge-state)
2086 ido-use-merged-list nil
2087 ido-try-merged-list try
2088 ido-keep-item-list (not refresh)
2089 ido-rescan nil
2090 ido-exit 'refresh
2091 ido-pre-merge-state nil)
2092 (exit-minibuffer))
2093 (text
2094 nil)
2095 (ido-try-merged-list
2096 (setq ido-try-merged-list nil))
2097 (ido-matches
2098 (setq ido-try-merged-list t))
2099 ((not ido-use-merged-list)
2100 (ido-merge-work-directories))))
71296446 2101
789d1bf0
KS
2102;;; TOGGLE FUNCTIONS
2103
2104(defun ido-toggle-case ()
2105 "Toggle the value of `ido-case-fold'."
2106 (interactive)
2107 (setq ido-case-fold (not ido-case-fold))
2108 ;; ask for list to be regenerated.
2109 (setq ido-rescan t))
2110
2111(defun ido-toggle-regexp ()
2112 "Toggle the value of `ido-enable-regexp'."
2113 (interactive)
2114 (setq ido-enable-regexp (not ido-enable-regexp))
2115 ;; ask for list to be regenerated.
2116 (setq ido-rescan t))
2117
2118(defun ido-toggle-prefix ()
2119 "Toggle the value of `ido-enable-prefix'."
2120 (interactive)
2121 (setq ido-enable-prefix (not ido-enable-prefix))
2122 ;; ask for list to be regenerated.
2123 (setq ido-rescan t))
2124
2125(defun ido-toggle-ignore ()
2126 "Toggle ignoring files specified with `ido-ignore-files'."
2127 (interactive)
2128 (setq ido-process-ignore-lists (not ido-process-ignore-lists))
2129 (setq ido-text-init ido-text)
2130 (setq ido-exit 'refresh)
2131 (exit-minibuffer))
2132
2133(defun ido-toggle-vc ()
2134 "Disable version control for this file."
2135 (interactive)
2136 (if (and ido-mode (eq ido-cur-item 'file))
2137 (progn
310682e6
KS
2138 (setq vc-handled-backends
2139 (if vc-handled-backends nil ido-saved-vc-hb))
789d1bf0
KS
2140 (setq ido-text-init ido-text)
2141 (setq ido-exit 'keep)
2142 (exit-minibuffer))))
2143
2144(defun ido-toggle-literal ()
2145 "Toggle literal reading of this file."
2146 (interactive)
2147 (if (and ido-mode (eq ido-cur-item 'file))
2148 (progn
2149 (setq ido-find-literal (not ido-find-literal))
2150 (setq ido-text-init ido-text)
2151 (setq ido-exit 'keep)
2152 (exit-minibuffer))))
2153
2154(defun ido-reread-directory ()
2155 "Read current directory again.
2156May be useful if cached version is no longer valid, but directory
2157timestamp has not changed (e.g. with ftp or on Windows)."
2158 (interactive)
2159 (if (and ido-mode (eq ido-cur-item 'file))
2160 (progn
2161 (ido-remove-cached-dir ido-current-directory)
2162 (setq ido-text-init ido-text)
2163 (setq ido-rotate-temp t)
2164 (setq ido-exit 'refresh)
2165 (exit-minibuffer))))
2166
2167(defun ido-exit-minibuffer ()
2168 "Exit minibuffer, but make sure we have a match if one is needed."
2169 (interactive)
2170 (if (or (not ido-require-match)
2171 (ido-existing-item-p))
2172 (throw 'exit nil)))
2173
2174(defun ido-select-text ()
2175 "Select the buffer or file named by the prompt.
2176If no buffer or file exactly matching the prompt exists, maybe create a new one."
2177 (interactive)
2178 (setq ido-exit 'takeprompt)
2179 (exit-minibuffer))
2180
2181(defun ido-fallback-command ()
2182 "Fallback to non-ido version of current command."
2183 (interactive)
2184 (setq ido-exit 'fallback)
2185 (exit-minibuffer))
2186
2187(defun ido-enter-find-file ()
2188 "Drop into find-file from buffer switching."
2189 (interactive)
2190 (setq ido-exit 'findfile)
2191 (exit-minibuffer))
2192
2193(defun ido-enter-switch-buffer ()
2194 "Drop into ido-switch-buffer from file switching."
2195 (interactive)
2196 (setq ido-exit 'findbuffer)
2197 (exit-minibuffer))
2198
2199(defun ido-enter-dired ()
2200 "Drop into dired from file switching."
2201 (interactive)
2202 (setq ido-exit 'dired)
2203 (exit-minibuffer))
2204
2205
2206(defun ido-up-directory (&optional clear)
2207 "Go up one directory level."
2208 (interactive "P")
2209 (setq ido-text-init (if clear nil ido-text))
2210 (setq ido-exit 'updir)
2211 (setq ido-rotate-temp t)
2212 (exit-minibuffer))
2213
2214(defun ido-delete-backward-updir (count)
2215 "Delete char backwards, or at beginning of buffer, go up one level."
2216 (interactive "P")
2217 (cond
2218 ((= (minibuffer-prompt-end) (point))
2219 (if (not count)
2220 (ido-up-directory t)))
2221 ((and ido-pre-merge-state (string-equal (car ido-pre-merge-state) ido-text))
2222 (ido-undo-merge-work-directory (substring ido-text 0 -1) t t))
f0a73ccc
KS
2223 ((eq this-original-command 'viper-backward-char)
2224 (funcall this-original-command (prefix-numeric-value count)))
2225 ((eq this-original-command 'viper-del-backward-char-in-insert)
2226 (funcall this-original-command))
789d1bf0
KS
2227 (t
2228 (delete-backward-char (prefix-numeric-value count)))))
2229
2230(defun ido-delete-backward-word-updir (count)
2231 "Delete all chars backwards, or at beginning of buffer, go up one level."
2232 (interactive "P")
2233 (if (= (minibuffer-prompt-end) (point))
2234 (if (not count)
2235 (ido-up-directory t))
f0a73ccc
KS
2236 (if (eq this-original-command 'viper-delete-backward-word)
2237 (funcall this-original-command (prefix-numeric-value count))
2238 (backward-kill-word (prefix-numeric-value count)))))
789d1bf0
KS
2239
2240(defun ido-get-work-directory (&optional incr must-match)
2241 (let ((n (length ido-work-directory-list))
2242 (i ido-work-directory-index)
2243 (j 0)
2244 dir)
2245 (if (or (not ido-text) (= (length ido-text) 0))
2246 (setq must-match nil))
2247 (while (< j n)
2248 (setq i (+ i incr)
2249 j (1+ j))
2250 (if (> incr 0)
2251 (if (>= i n) (setq i 0))
2252 (if (< i 0) (setq i (1- n))))
2253 (setq dir (nth i ido-work-directory-list))
2254 (if (and dir
2255 (not (equal dir ido-current-directory))
2256 (file-directory-p dir)
2257 (or (not must-match)
2258 (ido-set-matches1
2259 (if (eq ido-cur-item 'file)
2260 (ido-make-file-list1 dir)
2261 (ido-make-dir-list1 dir)))))
2262 (setq j n)
2263 (setq dir nil)))
2264 (if dir
2265 (setq ido-work-directory-index i))
2266 dir))
2267
2268(defun ido-prev-work-directory ()
2269 "Change to next working directory in list."
2270 (interactive)
2271 (let ((dir (ido-get-work-directory 1 ido-work-directory-match-only)))
2272 (when dir
2273 (ido-set-current-directory dir)
2274 (setq ido-exit 'refresh)
2275 (setq ido-text-init ido-text)
2276 (setq ido-rotate-temp t)
2277 (exit-minibuffer))))
2278
2279(defun ido-next-work-directory ()
2280 "Change to previous working directory in list."
2281 (interactive)
2282 (let ((dir (ido-get-work-directory -1 ido-work-directory-match-only)))
2283 (when dir
2284 (ido-set-current-directory dir)
2285 (setq ido-exit 'refresh)
2286 (setq ido-text-init ido-text)
2287 (setq ido-rotate-temp t)
2288 (exit-minibuffer))))
2289
2290(defun ido-merge-work-directories ()
2291 "Search (and merge) work directories for files matching the current input string."
2292 (interactive)
2293 (setq ido-use-merged-list t ido-try-merged-list t)
2294 (setq ido-exit 'refresh)
2295 (setq ido-text-init ido-text)
2296 (setq ido-rotate-temp t)
2297 (exit-minibuffer))
2298
2299(defun ido-wide-find-file (&optional file)
2300 "Prompt for FILE to search for using find, starting from current directory."
2301 (interactive)
2302 (unless file
b0df3884
KS
2303 (let ((enable-recursive-minibuffers t))
2304 (setq file
2305 (read-string (concat "Wide find file: " ido-current-directory) ido-text))))
789d1bf0
KS
2306 (when (> (length file) 0)
2307 (setq ido-use-merged-list t ido-try-merged-list 'wide)
2308 (setq ido-exit 'refresh)
2309 (setq ido-text-init file)
2310 (setq ido-rotate-temp t)
2311 (exit-minibuffer)))
2312
2313(defun ido-wide-find-dir (&optional dir)
2314 "Prompt for DIR to search for using find, starting from current directory."
2315 (interactive)
2316 (unless dir
b0df3884
KS
2317 (let ((enable-recursive-minibuffers t))
2318 (setq dir
2319 (read-string (concat "Wide find directory: " ido-current-directory) ido-text))))
789d1bf0
KS
2320 (when (> (length dir) 0)
2321 (setq ido-use-merged-list t ido-try-merged-list 'wide)
2322 (setq ido-exit 'refresh)
2323 (setq ido-text-init (ido-final-slash dir t))
2324 (setq ido-rotate-temp t)
2325 (exit-minibuffer)))
2326
2327(defun ido-make-directory (&optional dir)
2328 "Prompt for DIR to create in current directory."
2329 (interactive)
2330 (unless dir
b0df3884
KS
2331 (let ((enable-recursive-minibuffers t))
2332 (setq dir
2333 (read-string (concat "Make directory: " ido-current-directory) ido-text))))
789d1bf0
KS
2334 (when (> (length dir) 0)
2335 (setq dir (concat ido-current-directory dir))
2336 (unless (file-exists-p dir)
2337 (make-directory dir t)
2338 (ido-set-current-directory dir)
2339 (setq ido-exit 'refresh)
2340 (setq ido-text-init nil)
2341 (setq ido-rotate-temp t)
2342 (exit-minibuffer))))
2343
2344(defun ido-get-work-file (incr)
2345 (let ((n (length ido-work-file-list))
2346 (i (+ ido-work-file-index incr))
2347 name)
2348 (if (> incr 0)
2349 (if (>= i n) (setq i 0))
2350 (if (< i 0) (setq i (1- n))))
2351 (setq name (nth i ido-work-file-list))
2352 (setq ido-work-file-index i)
2353 name))
2354
2355(defun ido-prev-work-file ()
2356 "Change to next working file name in list."
2357 (interactive)
2358 (let ((name (ido-get-work-file 1)))
2359 (when name
2360 (setq ido-text-init name)
2361 (setq ido-exit 'refresh)
2362 (exit-minibuffer))))
2363
2364(defun ido-next-work-file ()
2365 "Change to previous working file name in list."
2366 (interactive)
2367 (let ((name (ido-get-work-file -1)))
2368 (when name
2369 (setq ido-text-init name)
2370 (setq ido-exit 'refresh)
2371 (exit-minibuffer))))
2372
2373(defun ido-copy-current-file-name (all)
2374 "Insert file name of current buffer.
2375If repeated, insert text from buffer instead."
2376 (interactive "P")
84f6c6d0
KS
2377 (let* ((bfname (buffer-file-name ido-entry-buffer))
2378 (name (and bfname (file-name-nondirectory bfname))))
789d1bf0 2379 (when name
71296446
JB
2380 (setq ido-text-init
2381 (if (or all
84f6c6d0 2382 (not (equal (file-name-directory bfname) ido-current-directory))
789d1bf0
KS
2383 (not (string-match "\\.[^.]*\\'" name)))
2384 name
2385 (substring name 0 (1+ (match-beginning 0)))))
2386 (setq ido-exit 'refresh
2387 ido-try-merged-list nil)
2388 (exit-minibuffer))))
71296446 2389
789d1bf0 2390(defun ido-copy-current-word (all)
362cdb61 2391 "Insert current word (file or directory name) from current buffer."
789d1bf0
KS
2392 (interactive "P")
2393 (let ((word (save-excursion
2394 (set-buffer ido-entry-buffer)
2395 (let ((p (point)) start-line end-line start-name name)
2396 (beginning-of-line)
2397 (setq start-line (point))
2398 (end-of-line)
2399 (setq end-line (point))
2400 (goto-char p)
2401 (if (re-search-backward "[^-_a-zA-Z0-9:./\\~@]" start-line 1)
2402 (forward-char 1))
2403 (setq start-name (point))
2404 (re-search-forward "[-_a-zA-Z0-9:./\\~@]*" end-line 1)
2405 (if (= start-name (point))
2406 nil
2407 (buffer-substring-no-properties start-name (point)))))))
2408 (if (cond
2409 ((not word) nil)
2410 ((string-match "\\`[~/]" word)
2411 (setq ido-text-init word
2412 ido-try-merged-list nil
2413 ido-exit 'chdir))
2414 ((string-match "/" word)
2415 (setq ido-text-init (concat ido-current-directory word)
2416 ido-try-merged-list nil
2417 ido-exit 'chdir))
2418 (t
2419 (setq ido-text-init word
2420 ido-try-merged-list nil
2421 ido-exit 'refresh)))
2422 (exit-minibuffer))))
2423
71296446 2424(defun ido-next-match ()
789d1bf0
KS
2425 "Put first element of `ido-matches' at the end of the list."
2426 (interactive)
2427 (if ido-matches
2428 (let ((next (cadr ido-matches)))
2429 (setq ido-cur-list (ido-chop ido-cur-list next))
2430 (setq ido-rescan t)
2431 (setq ido-rotate t))))
2432
71296446 2433(defun ido-prev-match ()
789d1bf0
KS
2434 "Put last element of `ido-matches' at the front of the list."
2435 (interactive)
2436 (if ido-matches
2437 (let ((prev (car (last ido-matches))))
2438 (setq ido-cur-list (ido-chop ido-cur-list prev))
2439 (setq ido-rescan t)
2440 (setq ido-rotate t))))
2441
71296446 2442(defun ido-next-match-dir ()
789d1bf0
KS
2443 "Find next directory in match list.
2444If work directories have been merged, cycle through directories for
2445first matching file."
2446 (interactive)
2447 (if ido-use-merged-list
2448 (if ido-matches
2449 (let* ((elt (car ido-matches))
2450 (dirs (cdr elt)))
2451 (when (> (length dirs) 1)
2452 (setcdr elt (ido-chop dirs (cadr dirs))))
2453 (setq ido-rescan nil)))
2454 (let ((cnt (length ido-matches))
2455 (i 1))
2456 (while (and (< i cnt) (not (ido-final-slash (nth i ido-matches))))
2457 (setq i (1+ i)))
2458 (if (< i cnt)
2459 (setq ido-cur-list (ido-chop ido-cur-list (nth i ido-matches)))))))
2460
71296446 2461(defun ido-prev-match-dir ()
789d1bf0
KS
2462 "Find previous directory in match list.
2463If work directories have been merged, cycle through directories
2464for first matching file."
2465 (interactive)
2466 (if ido-use-merged-list
2467 (if ido-matches
2468 (let* ((elt (car ido-matches))
2469 (dirs (cdr elt)))
2470 (when (> (length dirs) 1)
2471 (setcdr elt (ido-chop dirs (car (last dirs)))))
2472 (setq ido-rescan nil)))
2473 (let* ((cnt (length ido-matches))
2474 (i (1- cnt)))
2475 (while (and (> i 0) (not (ido-final-slash (nth i ido-matches))))
2476 (setq i (1- i)))
2477 (if (> i 0)
2478 (setq ido-cur-list (ido-chop ido-cur-list (nth i ido-matches)))))))
2479
71296446 2480(defun ido-restrict-to-matches ()
08bfde76
KS
2481 "Set current item list to the currently matched items."
2482 (interactive)
2483 (when ido-matches
2484 (setq ido-cur-list ido-matches
2485 ido-text-init ""
2486 ido-rescan nil
2487 ido-exit 'keep)
2488 (exit-minibuffer)))
2489
789d1bf0
KS
2490(defun ido-chop (items elem)
2491 "Remove all elements before ELEM and put them at the end of ITEMS."
2492 (let ((ret nil)
2493 (next nil)
2494 (sofar nil))
2495 (while (not ret)
2496 (setq next (car items))
2497 (if (equal next elem)
2498 (setq ret (append items (nreverse sofar)))
2499 ;; else
2500 (progn
2501 (setq items (cdr items))
2502 (setq sofar (cons next sofar)))))
2503 ret))
2504
2505(defun ido-name (item)
2506 ;; Return file name for current item, whether in a normal list
2507 ;; or a merged work directory list.
2508 (if (consp item) (car item) item))
2509
2510
2511;;; CREATE LIST OF ALL CURRENT FILES
2512
2513(defun ido-all-completions ()
2514 ;; Return unsorted list of all competions.
2515 (let ((ido-process-ignore-lists nil))
2516 (cond
2517 ((eq ido-cur-item 'file)
2518 (ido-make-file-list1 ido-current-directory))
2519 ((eq ido-cur-item 'dir)
2520 (ido-make-dir-list1 ido-current-directory))
2521 ((eq ido-cur-item 'buffer)
2522 (ido-make-buffer-list1))
2523 (t nil))))
2524
2525
2526(defun ido-sort-list (items)
2527 ;; Simple list of file or buffer names
310682e6
KS
2528 (sort items (lambda (a b) (string-lessp (ido-no-final-slash a)
2529 (ido-no-final-slash b)))))
789d1bf0
KS
2530
2531(defun ido-sort-merged-list (items promote)
2532 ;; Input is list of ("file" . "dir") cons cells.
2533 ;; Output is sorted list of ("file "dir" ...) lists
2534 (let ((l (sort items (lambda (a b) (string-lessp (car b) (car a)))))
2535 res a cur dirs)
2536 (while l
2537 (setq a (car l)
2538 l (cdr l))
2539 (if (and res (string-equal (car (car res)) (car a)))
2540 (progn
2541 (setcdr (car (if cur (cdr res) res)) (cons (cdr a) (cdr (car res))))
2542 (if (and promote (string-equal ido-current-directory (cdr a)))
2543 (setq cur t)))
2544 (setq res (cons (list (car a) (cdr a)) res)
2545 cur nil)))
2546 res))
2547
2548(defun ido-wide-find-dirs-or-files (dir file &optional prefix finddir)
2549 ;; As ido-run-find-command, but returns a list of cons pairs ("file" . "dir")
71296446
JB
2550 (let ((filenames
2551 (split-string
789d1bf0
KS
2552 (shell-command-to-string
2553 (concat "find " dir " -name \"" (if prefix "" "*") file "*\" -type " (if finddir "d" "f") " -print"))))
84f6c6d0 2554 filename d f
789d1bf0 2555 res)
84f6c6d0
KS
2556 (while filenames
2557 (setq filename (car filenames)
2558 filenames (cdr filenames))
2559 (if (and (string-match "^/" filename)
2560 (file-exists-p filename))
2561 (setq d (file-name-directory filename)
2562 f (file-name-nondirectory filename)
789d1bf0
KS
2563 res (cons (cons (if finddir (ido-final-slash f t) f) d) res))))
2564 res))
2565
2566(defun ido-flatten-merged-list (items)
362cdb61 2567 ;; Create a list of directory names based on a merged directory list.
789d1bf0
KS
2568 (let (res)
2569 (while items
2570 (let* ((item (car items))
2571 (file (car item))
2572 (dirs (cdr item)))
2573 (while dirs
2574 (setq res (cons (concat (car dirs) file) res)
2575 dirs (cdr dirs))))
2576 (setq items (cdr items)))
2577 res))
2578
2579(defun ido-make-merged-file-list (text auto wide)
2580 (let (res)
2581 (message "Searching for `%s'...." text)
2582 (if (and (ido-final-slash text) ido-dir-file-cache)
2583 (if wide
2584 (setq res (ido-wide-find-dirs-or-files
2585 ido-current-directory (substring text 0 -1) ido-enable-prefix t))
2586 ;; Use list of cached directories
2587 (let ((re (concat (regexp-quote (substring text 0 -1)) "[^/:]*/\\'"))
2588 (dirs ido-dir-file-cache)
2589 dir b d f)
2590 (if nil ;; simple
2591 (while dirs
2592 (setq dir (car (car dirs))
2593 dirs (cdr dirs))
2594 (when (and (string-match re dir)
2595 (not (ido-ignore-item-p dir ido-ignore-directories-merge))
2596 (file-directory-p dir))
2597 (setq b (substring dir 0 -1)
2598 f (concat (file-name-nondirectory b) "/")
2599 d (file-name-directory b)
2600 res (cons (cons f d) res))))
2601 (while dirs
2602 (setq dir (car dirs)
2603 d (car dir)
2604 dirs (cdr dirs))
2605 (when (not (ido-ignore-item-p d ido-ignore-directories-merge))
2606 (setq dir (cdr (cdr dir)))
2607 (while dir
2608 (setq f (car dir)
2609 dir (cdr dir))
2610 (if (and (string-match re f)
2611 (not (ido-ignore-item-p f ido-ignore-directories)))
2612 (setq res (cons (cons f d) res)))))
2613 (if (and auto (input-pending-p))
2614 (setq dirs nil
2615 res t))))))
2616 (if wide
2617 (setq res (ido-wide-find-dirs-or-files
2618 ido-current-directory text ido-enable-prefix nil))
2619 (let ((ido-text text)
2620 (dirs ido-work-directory-list)
2621 (must-match (and text (> (length text) 0)))
2622 dir fl)
2623 (if (and auto (not (member ido-current-directory dirs)))
2624 (setq dirs (cons ido-current-directory dirs)))
2625 (while dirs
2626 (setq dir (car dirs)
2627 dirs (cdr dirs))
2628 (when (and dir (stringp dir)
2629 (or ido-merge-ftp-work-directories
2630 (not (ido-is-ftp-directory dir)))
2631 (file-directory-p dir)
2632 (setq fl (if (eq ido-cur-item 'file)
2633 (ido-make-file-list1 dir t)
2634 (ido-make-dir-list1 dir t))))
2635 (if must-match
2636 (setq fl (ido-set-matches1 fl)))
2637 (if fl
2638 (setq res (nconc fl res))))
2639 (if (and auto (input-pending-p))
2640 (setq dirs nil
2641 res t))))))
2642 (if (and res (not (eq res t)))
2643 (setq res (ido-sort-merged-list res auto)))
9a08196a 2644 (when (and (or ido-rotate-temp ido-rotate-file-list-default)
e20b3173 2645 (listp res)
9a08196a
KS
2646 (> (length text) 0))
2647 (let ((elt (assoc text res)))
4e85a733 2648 (when (and elt (not (eq elt (car res))))
9a08196a
KS
2649 (setq res (delq elt res))
2650 (setq res (cons elt res)))))
789d1bf0
KS
2651 (message nil)
2652 res))
2653
2654(defun ido-make-buffer-list1 (&optional frame visible)
2655 ;; Return list of non-ignored buffer names
71296446 2656 (delq nil
789d1bf0
KS
2657 (mapcar
2658 (lambda (x)
2659 (let ((name (buffer-name x)))
69beb26d 2660 (if (not (or (ido-ignore-item-p name ido-ignore-buffers) (member name visible)))
789d1bf0
KS
2661 name)))
2662 (buffer-list frame))))
2663
2664(defun ido-make-buffer-list (default)
2665 ;; Return the current list of buffers.
2666 ;; Currently visible buffers are put at the end of the list.
71296446 2667 ;; The hook `ido-make-buflist-hook' is run after the list has been
789d1bf0
KS
2668 ;; created to allow the user to further modify the order of the buffer names
2669 ;; in this list. If DEFAULT is non-nil, and corresponds to an existing buffer,
2670 ;; it is put to the start of the list.
2671 (let* ((ido-current-buffers (ido-get-buffers-in-frames 'current))
2672 (ido-temp-list (ido-make-buffer-list1 (selected-frame) ido-current-buffers)))
2673 (if ido-temp-list
2674 (nconc ido-temp-list ido-current-buffers)
2675 (setq ido-temp-list ido-current-buffers))
2676 (if default
2677 (progn
71296446 2678 (setq ido-temp-list
789d1bf0 2679 (delete default ido-temp-list))
71296446 2680 (setq ido-temp-list
789d1bf0
KS
2681 (cons default ido-temp-list))))
2682 (run-hooks 'ido-make-buffer-list-hook)
2683 ido-temp-list))
2684
2685(defun ido-to-end (items)
2686 ;; Move the elements from ITEMS to the end of `ido-temp-list'
71296446
JB
2687 (mapcar
2688 (lambda (elem)
789d1bf0
KS
2689 (setq ido-temp-list (delq elem ido-temp-list)))
2690 items)
2691 (if ido-temp-list
2692 (nconc ido-temp-list items)
2693 (setq ido-temp-list items)))
2694
bad111c2
KS
2695(defun ido-file-name-all-completions1 (dir)
2696 (if (and ido-enable-tramp-completion
2697 (string-match "\\`/\\([^/:]+:\\([^/:@]+@\\)?\\)\\'" dir))
2698
2699 ;; Trick tramp's file-name-all-completions handler to DTRT, as it
2700 ;; has some pretty obscure requirements. This seems to work...
2701 ;; /ftp: => (f-n-a-c "/ftp:" "")
2702 ;; /ftp:kfs: => (f-n-a-c "" "/ftp:kfs:")
2703 ;; /ftp:kfs@ => (f-n-a-c "ftp:kfs@" "/")
2704 ;; /ftp:kfs@kfs: => (f-n-a-c "" "/ftp:kfs@kfs:")
2705 ;; Currently no attempt is made to handle multi: stuff.
2706
2707 (let* ((prefix (match-string 1 dir))
2708 (user-flag (match-beginning 2))
2709 (len (and prefix (length prefix)))
2710 compl)
2711 (if user-flag
2712 (setq dir (substring dir 1)))
2713 (require 'tramp nil t)
2714 (ido-trace "tramp complete" dir)
2715 (setq compl (file-name-all-completions dir (if user-flag "/" "")))
2716 (if (> len 0)
2717 (mapcar (lambda (c) (substring c len)) compl)
2718 compl))
2719 (file-name-all-completions "" dir)))
2720
789d1bf0
KS
2721(defun ido-file-name-all-completions (dir)
2722 ;; Return name of all files in DIR
2723 ;; Uses and updates ido-dir-file-cache
2724 (if (and (numberp ido-max-dir-file-cache) (> ido-max-dir-file-cache 0)
2725 (stringp dir) (> (length dir) 0)
2726 (ido-may-cache-directory dir))
2727 (let* ((cached (assoc dir ido-dir-file-cache))
71296446 2728 (ctime (nth 1 cached))
789d1bf0
KS
2729 (ftp (ido-is-ftp-directory dir))
2730 (attr (if ftp nil (file-attributes dir)))
2731 (mtime (nth 5 attr))
2732 valid)
2733 (when cached ; should we use the cached entry ?
2734 (if ftp
2735 (setq valid (and (eq (car ctime) 'ftp)
2736 (ido-cache-ftp-valid (cdr ctime))))
2737 (if attr
2738 (setq valid (and (= (car ctime) (car mtime))
2739 (= (car (cdr ctime)) (car (cdr mtime)))))))
2740 (if (not valid)
2741 (setq ido-dir-file-cache (delq cached ido-dir-file-cache)
2742 cached nil)))
2743 (unless cached
2744 (if (and ftp (file-readable-p dir))
2745 (setq mtime (cons 'ftp (ido-time-stamp))))
2746 (if mtime
bad111c2 2747 (setq cached (cons dir (cons mtime (ido-file-name-all-completions1 dir)))
789d1bf0
KS
2748 ido-dir-file-cache (cons cached ido-dir-file-cache)))
2749 (if (> (length ido-dir-file-cache) ido-max-dir-file-cache)
2750 (setcdr (nthcdr (1- ido-max-dir-file-cache) ido-dir-file-cache) nil)))
2751 (and cached
2752 (cdr (cdr cached))))
bad111c2 2753 (ido-file-name-all-completions1 dir)))
789d1bf0
KS
2754
2755(defun ido-remove-cached-dir (dir)
2756 ;; Remove dir from ido-dir-file-cache
2757 (if (and ido-dir-file-cache
2758 (stringp dir) (> (length dir) 0))
2759 (let ((cached (assoc dir ido-dir-file-cache)))
2760 (if cached
2761 (setq ido-dir-file-cache (delq cached ido-dir-file-cache))))))
2762
2763
2764(defun ido-make-file-list1 (dir &optional merged)
2765 ;; Return list of non-ignored files in DIR
2766 ;; If MERGED is non-nil, each file is cons'ed with DIR
bad111c2 2767 (and (or (ido-is-tramp-root dir) (file-directory-p dir))
71296446 2768 (delq nil
789d1bf0
KS
2769 (mapcar
2770 (lambda (name)
2771 (if (not (ido-ignore-item-p name ido-ignore-files t))
2772 (if merged (cons name dir) name)))
2773 (ido-file-name-all-completions dir)))))
2774
2775(defun ido-make-file-list (default)
2776 ;; Return the current list of files.
2777 ;; Currently visible files are put at the end of the list.
71296446 2778 ;; The hook `ido-make-file-list-hook' is run after the list has been
789d1bf0
KS
2779 ;; created to allow the user to further modify the order of the file names
2780 ;; in this list.
2781 (let ((ido-temp-list (ido-make-file-list1 ido-current-directory)))
2782 (setq ido-temp-list (ido-sort-list ido-temp-list))
2783 (let ((default-directory ido-current-directory))
2784 (ido-to-end ;; move ftp hosts and visited files to end
71296446
JB
2785 (delq nil (mapcar
2786 (lambda (x) (if (or (string-match "..:\\'" x)
4d80e3ae
KS
2787 (and (not (ido-final-slash x))
2788 (get-file-buffer x))) x))
789d1bf0
KS
2789 ido-temp-list))))
2790 (ido-to-end ;; move . files to end
71296446 2791 (delq nil (mapcar
789d1bf0
KS
2792 (lambda (x) (if (string-equal (substring x 0 1) ".") x))
2793 ido-temp-list)))
2794 (if (and default (member default ido-temp-list))
2795 (if (or ido-rotate-temp ido-rotate-file-list-default)
2796 (unless (equal default (car ido-temp-list))
2797 (let ((l ido-temp-list) k)
2798 (while (and l (cdr l) (not (equal default (car (cdr l)))))
2799 (setq l (cdr l)))
2800 (setq k (cdr l))
2801 (setcdr l nil)
2802 (nconc k ido-temp-list)
2803 (setq ido-temp-list k)))
71296446 2804 (setq ido-temp-list
789d1bf0 2805 (delete default ido-temp-list))
71296446 2806 (setq ido-temp-list
789d1bf0
KS
2807 (cons default ido-temp-list))))
2808 (when ido-show-dot-for-dired
2809 (setq ido-temp-list (delete "." ido-temp-list))
2810 (setq ido-temp-list (cons "." ido-temp-list)))
2811 (run-hooks 'ido-make-file-list-hook)
2812 ido-temp-list))
2813
2814(defun ido-make-dir-list1 (dir &optional merged)
2815 ;; Return list of non-ignored subdirs in DIR
2816 ;; If MERGED is non-nil, each subdir is cons'ed with DIR
bad111c2 2817 (and (or (ido-is-tramp-root dir) (file-directory-p dir))
71296446 2818 (delq nil
789d1bf0
KS
2819 (mapcar
2820 (lambda (name)
2821 (and (ido-final-slash name) (not (ido-ignore-item-p name ido-ignore-directories))
2822 (if merged (cons name dir) name)))
2823 (ido-file-name-all-completions dir)))))
2824
2825(defun ido-make-dir-list (default)
2826 ;; Return the current list of directories.
71296446 2827 ;; The hook `ido-make-dir-list-hook' is run after the list has been
789d1bf0
KS
2828 ;; created to allow the user to further modify the order of the
2829 ;; directory names in this list.
2830 (let ((ido-temp-list (ido-make-dir-list1 ido-current-directory)))
2831 (setq ido-temp-list (ido-sort-list ido-temp-list))
789d1bf0 2832 (ido-to-end ;; move . files to end
71296446 2833 (delq nil (mapcar
789d1bf0
KS
2834 (lambda (x) (if (string-equal (substring x 0 1) ".") x))
2835 ido-temp-list)))
2836 (if (and default (member default ido-temp-list))
2837 (if (or ido-rotate-temp ido-rotate-file-list-default)
2838 (unless (equal default (car ido-temp-list))
2839 (let ((l ido-temp-list) k)
2840 (while (and l (cdr l) (not (equal default (car (cdr l)))))
2841 (setq l (cdr l)))
2842 (setq k (cdr l))
2843 (setcdr l nil)
2844 (nconc k ido-temp-list)
2845 (setq ido-temp-list k)))
71296446 2846 (setq ido-temp-list
789d1bf0 2847 (delete default ido-temp-list))
71296446 2848 (setq ido-temp-list
789d1bf0
KS
2849 (cons default ido-temp-list))))
2850 (setq ido-temp-list (delete "." ido-temp-list))
2851 (setq ido-temp-list (cons "." ido-temp-list))
2852 (run-hooks 'ido-make-dir-list-hook)
2853 ido-temp-list))
2854
2855;; List of the files visible in the current frame.
2856(defvar ido-bufs-in-frame)
2857
2858(defun ido-get-buffers-in-frames (&optional current)
2859 ;; Return the list of buffers that are visible in the current frame.
2860 ;; If optional argument `current' is given, restrict searching to the
2861 ;; current frame, rather than all frames, regardless of value of
2862 ;; `ido-all-frames'.
2863 (let ((ido-bufs-in-frame nil))
2864 (walk-windows 'ido-get-bufname nil
71296446 2865 (if current
789d1bf0
KS
2866 nil
2867 ido-all-frames))
2868 ido-bufs-in-frame))
2869
2870(defun ido-get-bufname (win)
2871 ;; Used by `ido-get-buffers-in-frames' to walk through all windows
2872 (let ((buf (buffer-name (window-buffer win))))
69beb26d
KS
2873 (unless (or (member buf ido-bufs-in-frame)
2874 (member buf ido-ignore-item-temp-list))
2875 ;; Only add buf if it is not already in list.
2876 ;; This prevents same buf in two different windows being
2877 ;; put into the list twice.
2878 (setq ido-bufs-in-frame
2879 (cons buf ido-bufs-in-frame)))))
789d1bf0
KS
2880
2881;;; FIND MATCHING ITEMS
2882
2883(defun ido-set-matches1 (items &optional do-full)
2884 ;; Return list of matches in items
2885 (let* ((case-fold-search ido-case-fold)
bad111c2
KS
2886 (slash (and (not ido-enable-prefix) (ido-final-slash ido-text)))
2887 (text (if slash (substring ido-text 0 -1) ido-text))
2888 (rexq (concat (if ido-enable-regexp text (regexp-quote text)) (if slash ".*/" "")))
789d1bf0
KS
2889 (re (if ido-enable-prefix (concat "\\`" rexq) rexq))
2890 (full-re (and do-full (not ido-enable-regexp) (not (string-match "\$\\'" re))
2891 (concat "\\`" re "\\'")))
2892 (prefix-re (and full-re (not ido-enable-prefix)
2893 (concat "\\`" rexq)))
2894 full-matches
2895 prefix-matches
2896 matches)
2897 (mapcar
2898 (lambda (item)
2899 (let ((name (ido-name item)))
2900 (if (string-match re name)
2901 (cond
2902 ((and full-re (string-match full-re name))
2903 (setq full-matches (cons item full-matches)))
2904 ((and prefix-re (string-match prefix-re name))
2905 (setq prefix-matches (cons item prefix-matches)))
2906 (t (setq matches (cons item matches))))))
2907 t)
2908 items)
2909 (if prefix-matches
2910 (setq matches (nconc prefix-matches matches)))
2911 (if full-matches
2912 (setq matches (nconc full-matches matches)))
2913 (when (and (null matches)
2914 ido-enable-flex-matching
2915 (> (length ido-text) 1)
2916 (not ido-enable-regexp))
9066a4d0 2917 (setq re (mapconcat #'regexp-quote (split-string ido-text "") ".*"))
789d1bf0
KS
2918 (if ido-enable-prefix
2919 (setq re (concat "\\`" re)))
2920 (mapcar
2921 (lambda (item)
2922 (let ((name (ido-name item)))
2923 (if (string-match re name)
2924 (setq matches (cons item matches)))))
2925 items))
2926 matches))
71296446 2927
789d1bf0
KS
2928
2929(defun ido-set-matches ()
2930 ;; Set `ido-matches' to the list of items matching prompt
2931 (when ido-rescan
2932 (setq ido-matches (ido-set-matches1 (reverse ido-cur-list) (not ido-rotate))
2933 ido-rotate nil)))
71296446 2934
789d1bf0
KS
2935(defun ido-ignore-item-p (name re-list &optional ignore-ext)
2936 ;; Return t if the buffer or file NAME should be ignored.
69beb26d
KS
2937 (or (member name ido-ignore-item-temp-list)
2938 (and
2939 ido-process-ignore-lists re-list
789d1bf0
KS
2940 (let ((data (match-data))
2941 (ext-list (and ignore-ext ido-ignore-extensions
2942 completion-ignored-extensions))
71296446 2943 ignorep nextstr
789d1bf0
KS
2944 (flen (length name)) slen)
2945 (while ext-list
2946 (setq nextstr (car ext-list))
2947 (if (cond
2948 ((stringp nextstr)
2949 (and (>= flen (setq slen (length nextstr)))
2950 (string-equal (substring name (- flen slen)) nextstr)))
2951 ((fboundp nextstr) (funcall nextstr name))
2952 (t nil))
2953 (setq ignorep t
2954 ext-list nil
2955 re-list nil)
2956 (setq ext-list (cdr ext-list))))
2957 (while re-list
2958 (setq nextstr (car re-list))
2959 (if (cond
2960 ((stringp nextstr) (string-match nextstr name))
2961 ((fboundp nextstr) (funcall nextstr name))
2962 (t nil))
2963 (setq ignorep t
2964 re-list nil)
2965 (setq re-list (cdr re-list))))
2966 ;; return the result
2967 (if ignorep
2968 (setq ido-ignored-list (cons name ido-ignored-list)))
2969 (set-match-data data)
69beb26d 2970 ignorep))))
789d1bf0
KS
2971
2972
2973;; Private variable used by `ido-word-matching-substring'.
2974(defvar ido-change-word-sub)
2975
2976(defun ido-find-common-substring (items subs)
2977 ;; Return common string following SUBS in each element of ITEMS.
2978 (let (res
2979 alist
2980 ido-change-word-sub)
2981 (setq ido-change-word-sub
2982 (if ido-enable-regexp
2983 subs
2984 (regexp-quote subs)))
9066a4d0 2985 (setq res (mapcar #'ido-word-matching-substring items))
789d1bf0 2986 (setq res (delq nil res)) ;; remove any nil elements (shouldn't happen)
9066a4d0 2987 (setq alist (mapcar #'ido-makealist res)) ;; could use an OBARRAY
789d1bf0
KS
2988
2989 ;; try-completion returns t if there is an exact match.
9066a4d0
KS
2990 (let* ((completion-ignore-case ido-case-fold)
2991 (comp (try-completion subs alist)))
2992 (if (eq comp t)
2993 subs
2994 comp))))
789d1bf0
KS
2995
2996(defun ido-word-matching-substring (word)
2997 ;; Return part of WORD before 1st match to `ido-change-word-sub'.
2998 ;; If `ido-change-word-sub' cannot be found in WORD, return nil.
71296446 2999 (let ((case-fold-search ido-case-fold))
789d1bf0
KS
3000 (let ((m (string-match ido-change-word-sub (ido-name word))))
3001 (if m
3002 (substring (ido-name word) m)
3003 ;; else no match
3004 nil))))
3005
3006(defun ido-makealist (res)
3007 ;; Return dotted pair (RES . 1).
3008 (cons res 1))
3009
3010(defun ido-choose-completion-string (choice buffer mini-p base-size)
3011 (when (ido-active)
3012 ;; Insert the completion into the buffer where completion was requested.
3013 (if (get-buffer ido-completion-buffer)
3014 (kill-buffer ido-completion-buffer))
3015 (cond
3016 ((ido-active t) ;; ido-use-merged-list
3017 (setq ido-current-directory ""
3018 ido-text choice
3019 ido-exit 'done))
3020 ((not (ido-final-slash choice))
3021 (setq ido-text choice
3022 ido-exit 'done))
3023 (t
3024 (ido-set-current-directory ido-current-directory choice)
3025 (setq ido-exit 'refresh)))
3026 (exit-minibuffer)
3027 t))
3028
3029(defun ido-completion-help ()
3030 "Show possible completions in a *File Completions* buffer."
3031 (interactive)
3032 (setq ido-rescan nil)
3033 (let ((temp-buf (get-buffer ido-completion-buffer))
3034 display-it full-list)
3035 (if (and (eq last-command this-command) temp-buf)
3036 ;; scroll buffer
3037 (let (win (buf (current-buffer)))
3038 (display-buffer temp-buf nil nil)
3039 (set-buffer temp-buf)
3040 (setq win (get-buffer-window temp-buf))
3041 (if (pos-visible-in-window-p (point-max) win)
3042 (if (or ido-completion-buffer-all-completions (boundp 'ido-completion-buffer-full))
3043 (set-window-start win (point-min))
3044 (set (make-local-variable 'ido-completion-buffer-full) t)
3045 (setq full-list t
3046 display-it t))
3047 (scroll-other-window))
3048 (set-buffer buf))
3049 (setq display-it t))
3050 (if display-it
3051 (with-output-to-temp-buffer ido-completion-buffer
3052 (let ((completion-list (ido-sort-list
3053 (cond
3054 (ido-use-merged-list
3055 (ido-flatten-merged-list (or ido-matches ido-cur-list)))
3056 ((or full-list ido-completion-buffer-all-completions)
3057 (ido-all-completions))
3058 (t
3059 (copy-sequence (or ido-matches ido-cur-list)))))))
1518d6e3 3060 (if (featurep 'xemacs)
789d1bf0
KS
3061 ;; XEmacs extents are put on by default, doesn't seem to be
3062 ;; any way of switching them off.
0fe826e9 3063 ;; This obscure code avoids a byte compiler warning in Emacs.
6c1bc246
KS
3064 (let ((f 'display-completion-list))
3065 (funcall f completion-list
3066 :help-string "ido "
71296446 3067 :activate-callback
6c1bc246 3068 '(lambda (x y z) (message "doesn't work yet, sorry!"))))
789d1bf0
KS
3069 ;; else running Emacs
3070 ;;(add-hook 'completion-setup-hook 'completion-setup-function)
3071 (display-completion-list completion-list)))))))
3072
3073;;; KILL CURRENT BUFFER
3074(defun ido-kill-buffer-at-head ()
3075 "Kill the buffer at the head of `ido-matches'."
3076 (interactive)
3077 (let ((enable-recursive-minibuffers t)
3078 (buf (car ido-matches)))
3079 (when buf
3080 (kill-buffer buf)
3081 ;; Check if buffer still exists.
3082 (if (get-buffer buf)
3083 ;; buffer couldn't be killed.
71296446 3084 (setq ido-rescan t)
789d1bf0
KS
3085 ;; else buffer was killed so remove name from list.
3086 (setq ido-cur-list (delq buf ido-cur-list))))))
3087
3088;;; DELETE CURRENT FILE
3089(defun ido-delete-file-at-head ()
3090 "Delete the file at the head of `ido-matches'."
3091 (interactive)
3092 (let ((enable-recursive-minibuffers t)
3093 (file (car ido-matches)))
3094 (if file
3095 (setq file (concat ido-current-directory file)))
3096 (when (and file
3097 (file-exists-p file)
3098 (not (file-directory-p file))
3099 (file-writable-p ido-current-directory)
3100 (yes-or-no-p (concat "Delete " file " ")))
3101 (delete-file file)
3102 ;; Check if file still exists.
3103 (if (file-exists-p file)
3104 ;; file could not be deleted
71296446 3105 (setq ido-rescan t)
789d1bf0
KS
3106 ;; else file was killed so remove name from list.
3107 (setq ido-cur-list (delq (car ido-matches) ido-cur-list))))))
3108
3109
3110;;; VISIT CHOSEN BUFFER
3111(defun ido-visit-buffer (buffer method &optional record)
3112 "Visit file named FILE according to METHOD.
3113Record command in command-history if optional RECORD is non-nil."
3114
3115 (let (win newframe)
3116 (cond
3117 ((eq method 'kill)
3118 (if record
3119 (ido-record-command 'kill-buffer buffer))
3120 (kill-buffer buffer))
3121
3122 ((eq method 'samewindow)
3123 (if record
3124 (ido-record-command 'switch-to-buffer buffer))
3125 (switch-to-buffer buffer))
3126
3127 ((memq method '(always-frame maybe-frame))
3128 (cond
3129 ((and window-system
3130 (setq win (ido-window-buffer-p buffer))
3131 (or (eq method 'always-frame)
3132 (y-or-n-p "Jump to frame? ")))
3133 (setq newframe (window-frame win))
3134 (if (fboundp 'select-frame-set-input-focus)
3135 (select-frame-set-input-focus newframe)
3136 (raise-frame newframe)
3137 (select-frame newframe)
1518d6e3 3138 (unless (featurep 'xemacs)
789d1bf0
KS
3139 (set-mouse-position (selected-frame) (1- (frame-width)) 0)))
3140 (select-window win))
3141 (t
3142 ;; No buffer in other frames...
3143 (if record
3144 (ido-record-command 'switch-to-buffer buffer))
3145 (switch-to-buffer buffer)
3146 )))
3147
3148 ((eq method 'otherwindow)
3149 (if record
3150 (ido-record-command 'switch-to-buffer buffer))
3151 (switch-to-buffer-other-window buffer))
3152
3153 ((eq method 'display)
3154 (display-buffer buffer))
3155
3156 ((eq method 'otherframe)
1518d6e3
KS
3157 (switch-to-buffer-other-frame buffer)
3158 (unless (featurep 'xemacs)
3159 (select-frame-set-input-focus (selected-frame)))
3160 ))))
789d1bf0
KS
3161
3162
3163(defun ido-window-buffer-p (buffer)
3164 ;; Return window pointer if BUFFER is visible in another frame.
3165 ;; If BUFFER is visible in the current frame, return nil.
3166 (let ((blist (ido-get-buffers-in-frames 'current)))
3167 ;;If the buffer is visible in current frame, return nil
69beb26d 3168 (if (member buffer blist)
789d1bf0
KS
3169 nil
3170 ;; maybe in other frame or icon
3171 (get-buffer-window buffer 0) ; better than 'visible
3172 )))
3173
3174
3175;;; ----------- IDONIZED FUNCTIONS ------------
3176
3177;;;###autoload
3178(defun ido-switch-buffer ()
3179 "Switch to another buffer.
3180The buffer is displayed according to `ido-default-buffer-method' -- the
3181default is to show it in the same window, unless it is already visible
3182in another frame.
3183
3184As you type in a string, all of the buffers matching the string are
3185displayed if substring-matching is used \(default). Look at
3186`ido-enable-prefix' and `ido-toggle-prefix'. When you have found the
3187buffer you want, it can then be selected. As you type, most keys have their
3188normal keybindings, except for the following: \\<ido-mode-map>
3189
3190RET Select the buffer at the front of the list of matches. If the
3191list is empty, possibly prompt to create new buffer.
3192
3193\\[ido-select-text] Select the current prompt as the buffer.
3194If no buffer is found, prompt for a new one.
3195
3196\\[ido-next-match] Put the first element at the end of the list.
3197\\[ido-prev-match] Put the last element at the start of the list.
71296446 3198\\[ido-complete] Complete a common suffix to the current string that
789d1bf0
KS
3199matches all buffers. If there is only one match, select that buffer.
3200If there is no common suffix, show a list of all matching buffers
3201in a separate window.
3202\\[ido-edit-input] Edit input string.
3203\\[ido-fallback-command] Fallback to non-ido version of current command.
3204\\[ido-toggle-regexp] Toggle regexp searching.
3205\\[ido-toggle-prefix] Toggle between substring and prefix matching.
3206\\[ido-toggle-case] Toggle case-sensitive searching of buffer names.
3207\\[ido-completion-help] Show list of matching buffers in separate window.
3208\\[ido-enter-find-file] Drop into ido-find-file.
3209\\[ido-kill-buffer-at-head] Kill buffer at head of buffer list.
3210\\[ido-toggle-ignore] Toggle ignoring buffers listed in `ido-ignore-buffers'."
3211 (interactive)
3212 (ido-buffer-internal ido-default-buffer-method))
3213
3214;;;###autoload
3215(defun ido-switch-buffer-other-window ()
3216 "Switch to another buffer and show it in another window.
3217The buffer name is selected interactively by typing a substring.
3218For details of keybindings, do `\\[describe-function] ido'."
3219 (interactive)
3220 (ido-buffer-internal 'otherwindow 'switch-to-buffer-other-window))
3221
3222;;;###autoload
3223(defun ido-display-buffer ()
3224 "Display a buffer in another window but don't select it.
3225The buffer name is selected interactively by typing a substring.
3226For details of keybindings, do `\\[describe-function] ido'."
3227 (interactive)
3228 (ido-buffer-internal 'display 'display-buffer))
3229
3230;;;###autoload
3231(defun ido-kill-buffer ()
3232 "Kill a buffer.
3233The buffer name is selected interactively by typing a substring.
3234For details of keybindings, do `\\[describe-function] ido'."
3235 (interactive)
3236 (ido-buffer-internal 'kill 'kill-buffer "Kill buffer: " (buffer-name (current-buffer))))
3237
3238;;;###autoload
3239(defun ido-insert-buffer ()
3240 "Insert contents of a buffer in current buffer after point.
3241The buffer name is selected interactively by typing a substring.
3242For details of keybindings, do `\\[describe-function] ido'."
3243 (interactive)
3244 (ido-buffer-internal 'insert 'insert-buffer "Insert buffer: "))
3245
3246;;;###autoload
3247(defun ido-switch-buffer-other-frame ()
3248 "Switch to another buffer and show it in another frame.
3249The buffer name is selected interactively by typing a substring.
3250For details of keybindings, do `\\[describe-function] ido'."
3251 (interactive)
3252 (if ido-mode
3253 (ido-buffer-internal 'otherframe)
3254 (call-interactively 'switch-to-buffer-other-frame)))
3255
3256;;;###autoload
3257(defun ido-find-file-in-dir (dir)
3258 "Switch to another file starting from DIR."
3259 (interactive "DDir: ")
3260 (if (not (equal (substring dir -1) "/"))
3261 (setq dir (concat dir "/")))
3262 (ido-file-internal ido-default-file-method nil dir))
3263
3264;;;###autoload
3265(defun ido-find-file ()
3266 "Edit file with name obtained via minibuffer.
3267The file is displayed according to `ido-default-file-method' -- the
3268default is to show it in the same window, unless it is already
3269visible in another frame.
3270
3271The file name is selected interactively by typing a substring. As you type
3272in a string, all of the filenames matching the string are displayed if
3273substring-matching is used \(default). Look at `ido-enable-prefix' and
3274`ido-toggle-prefix'. When you have found the filename you want, it can
3275then be selected. As you type, most keys have their normal keybindings,
3276except for the following: \\<ido-mode-map>
3277
3278RET Select the file at the front of the list of matches. If the
3279list is empty, possibly prompt to create new file.
3280
3281\\[ido-select-text] Select the current prompt as the buffer or file.
3282If no buffer or file is found, prompt for a new one.
3283
3284\\[ido-next-match] Put the first element at the end of the list.
3285\\[ido-prev-match] Put the last element at the start of the list.
71296446 3286\\[ido-complete] Complete a common suffix to the current string that
789d1bf0
KS
3287matches all files. If there is only one match, select that file.
3288If there is no common suffix, show a list of all matching files
3289in a separate window.
362cdb61 3290\\[ido-edit-input] Edit input string (including directory).
789d1bf0
KS
3291\\[ido-prev-work-directory] or \\[ido-next-work-directory] go to previous/next directory in work directory history.
3292\\[ido-merge-work-directories] search for file in the work directory history.
3293\\[ido-forget-work-directory] removes current directory from the work directory history.
3294\\[ido-prev-work-file] or \\[ido-next-work-file] cycle through the work file history.
3295\\[ido-wide-find-file] and \\[ido-wide-find-dir] prompts and uses find to locate files or directories.
3296\\[ido-make-directory] prompts for a directory to create in current directory.
3297\\[ido-fallback-command] Fallback to non-ido version of current command.
3298\\[ido-toggle-regexp] Toggle regexp searching.
3299\\[ido-toggle-prefix] Toggle between substring and prefix matching.
3300\\[ido-toggle-case] Toggle case-sensitive searching of file names.
3301\\[ido-toggle-vc] Toggle version control for this file.
3302\\[ido-toggle-literal] Toggle literal reading of this file.
3303\\[ido-completion-help] Show list of matching files in separate window.
3304\\[ido-toggle-ignore] Toggle ignoring files listed in `ido-ignore-files'."
3305
3306 (interactive)
3307 (ido-file-internal ido-default-file-method))
3308
3309;;;###autoload
3310(defun ido-find-file-other-window ()
3311 "Switch to another file and show it in another window.
3312The file name is selected interactively by typing a substring.
3313For details of keybindings, do `\\[describe-function] ido-find-file'."
3314 (interactive)
3315 (ido-file-internal 'otherwindow 'find-file-other-window))
3316
3317;;;###autoload
3318(defun ido-find-alternate-file ()
3319 "Switch to another file and show it in another window.
3320The file name is selected interactively by typing a substring.
3321For details of keybindings, do `\\[describe-function] ido-find-file'."
3322 (interactive)
3323 (ido-file-internal 'alt-file 'find-alternate-file nil "Find alternate file: "))
3324
3325;;;###autoload
3326(defun ido-find-file-read-only ()
3327 "Edit file read-only with name obtained via minibuffer.
3328The file name is selected interactively by typing a substring.
3329For details of keybindings, do `\\[describe-function] ido-find-file'."
3330 (interactive)
3331 (ido-file-internal 'read-only 'find-file-read-only nil "Find file read-only: "))
3332
3333;;;###autoload
3334(defun ido-find-file-read-only-other-window ()
3335 "Edit file read-only in other window with name obtained via minibuffer.
3336The file name is selected interactively by typing a substring.
3337For details of keybindings, do `\\[describe-function] ido-find-file'."
3338 (interactive)
3339 (ido-file-internal 'read-only 'find-file-read-only-other-window nil "Find file read-only other window: "))
3340
3341;;;###autoload
3342(defun ido-find-file-read-only-other-frame ()
3343 "Edit file read-only in other frame with name obtained via minibuffer.
3344The file name is selected interactively by typing a substring.
3345For details of keybindings, do `\\[describe-function] ido-find-file'."
3346 (interactive)
3347 (ido-file-internal 'read-only 'find-file-read-only-other-frame nil "Find file read-only other frame: "))
3348
3349;;;###autoload
3350(defun ido-display-file ()
3351 "Display a file in another window but don't select it.
3352The file name is selected interactively by typing a substring.
3353For details of keybindings, do `\\[describe-function] ido-find-file'."
3354 (interactive)
3355 (ido-file-internal 'display))
3356
3357;;;###autoload
3358(defun ido-find-file-other-frame ()
3359 "Switch to another file and show it in another frame.
3360The file name is selected interactively by typing a substring.
3361For details of keybindings, do `\\[describe-function] ido-find-file'."
3362 (interactive)
3363 (ido-file-internal 'otherframe 'find-file-other-frame))
3364
3365;;;###autoload
3366(defun ido-write-file ()
3367 "Write current buffer to a file.
3368The file name is selected interactively by typing a substring.
3369For details of keybindings, do `\\[describe-function] ido-find-file'."
3370 (interactive)
3371 (let ((ido-process-ignore-lists t)
3372 (ido-work-directory-match-only nil)
3373 (ido-ignore-files (cons "[^/]\\'" ido-ignore-files))
3374 (ido-report-no-match nil)
3375 (ido-auto-merge-work-directories-length -1))
3376 (ido-file-internal 'write 'write-file nil "Write file: ")))
3377
3378;;;###autoload
3379(defun ido-insert-file ()
3380 "Insert contents of file in current buffer.
3381The file name is selected interactively by typing a substring.
3382For details of keybindings, do `\\[describe-function] ido-find-file'."
3383 (interactive)
3384 (ido-file-internal 'insert 'insert-file nil "Insert file: "))
3385
3386;;;###autoload
3387(defun ido-dired ()
3388 "Call dired the ido way.
3389The directory is selected interactively by typing a substring.
3390For details of keybindings, do `\\[describe-function] ido-find-file'."
3391 (interactive)
3392 (let ((ido-report-no-match nil)
3393 (ido-auto-merge-work-directories-length -1))
3394 (ido-file-internal 'dired 'dired nil "Dired: " 'dir)))
3395
3396(defun ido-list-directory ()
3397 "Call list-directory the ido way.
3398The directory is selected interactively by typing a substring.
3399For details of keybindings, do `\\[describe-function] ido-find-file'."
3400 (interactive)
3401 (let ((ido-report-no-match nil)
3402 (ido-auto-merge-work-directories-length -1))
3403 (ido-file-internal 'list-directory 'list-directory nil "List directory: " 'dir)))
3404
3405;;; XEmacs hack for showing default buffer
3406
3407;; The first time we enter the minibuffer, Emacs puts up the default
3408;; buffer to switch to, but XEmacs doesn't -- presumably there is a
3409;; subtle difference in the two versions of post-command-hook. The
3410;; default is shown for both whenever we delete all of our text
3411;; though, indicating its just a problem the first time we enter the
3412;; function. To solve this, we use another entry hook for emacs to
3413;; show the default the first time we enter the minibuffer.
3414
3415
3416;;; ICOMPLETE TYPE CODE
3417
3418(defun ido-initiate-auto-merge (buffer)
3419 (ido-trace "\n*merge timeout*" buffer)
3420 (setq ido-auto-merge-timer nil)
3421 (when (and (buffer-live-p buffer)
3422 (= ido-use-mycompletion-depth (minibuffer-depth))
3423 (boundp 'ido-eoinput) ido-eoinput)
3424 (let ((contents (buffer-substring-no-properties (minibuffer-prompt-end) ido-eoinput)))
3425 (ido-trace "request merge")
3426 (setq ido-use-merged-list 'auto
3427 ido-text-init contents
3428 ido-rotate-temp t
3429 ido-exit 'refresh)
3430 (save-excursion
3431 (set-buffer buffer)
3432 (ido-tidy))
3433 (throw 'ido contents))))
3434
3435(defun ido-exhibit ()
3436 "Post command hook for `ido'."
3437 ;; Find matching files and display a list in the minibuffer.
3438 ;; Copied from `icomplete-exhibit' with two changes:
3439 ;; 1. It prints a default file name when there is no text yet entered.
3440 ;; 2. It calls my completion routine rather than the standard completion.
3441
bad111c2
KS
3442 (when (= ido-use-mycompletion-depth (minibuffer-depth))
3443 (let ((contents (buffer-substring-no-properties (minibuffer-prompt-end) (point-max)))
3444 (buffer-undo-list t)
3445 try-single-dir-match
3446 refresh)
789d1bf0 3447
bad111c2
KS
3448 (ido-trace "\nexhibit" this-command)
3449 (ido-trace "dir" ido-current-directory)
3450 (ido-trace "contents" contents)
3451 (ido-trace "list" ido-cur-list)
3452 (ido-trace "matches" ido-matches)
3453 (ido-trace "rescan" ido-rescan)
789d1bf0 3454
bad111c2
KS
3455 (save-excursion
3456 (goto-char (point-max))
3457 ;; Register the end of input, so we know where the extra stuff (match-status info) begins:
3458 (unless (boundp 'ido-eoinput)
3459 ;; In case it got wiped out by major mode business:
3460 (make-local-variable 'ido-eoinput))
3461 (setq ido-eoinput (point))
3462
3463 ;; Handle explicit directory changes
3464 (cond
3465 ((eq ido-cur-item 'buffer)
3466 )
3467
3468 ((= (length contents) 0)
3469 )
3470
3471 ((= (length contents) 1)
3472 (when (and (ido-is-tramp-root) (string-equal contents "/"))
3473 (ido-set-current-directory ido-current-directory contents)
3474 (setq refresh t))
3475 )
3476
3477 ((and (string-match (if ido-enable-tramp-completion "..[:@]\\'" "..:\\'") contents)
3478 (ido-is-root-directory)) ;; Ange-ftp or tramp
3479 (ido-set-current-directory ido-current-directory contents)
3480 (when (ido-is-slow-ftp-host)
3481 (setq ido-exit 'fallback)
3482 (exit-minibuffer))
3483 (setq refresh t))
3484
3485 ((ido-final-slash contents) ;; xxx/
3486 (ido-trace "final slash" contents)
71296446 3487 (cond
bad111c2
KS
3488 ((string-equal contents "~/")
3489 (ido-set-current-home)
3490 (setq refresh t))
3491 ((string-equal contents "../")
3492 (ido-up-directory t)
3493 (setq refresh t))
3494 ((string-equal contents "./")
3495 (setq refresh t))
3496 ((string-match "\\`~[a-zA-Z0-9]+/\\'" contents)
3497 (ido-trace "new home" contents)
3498 (ido-set-current-home contents)
3499 (setq refresh t))
3500 ((string-match "[$][A-Za-z0-9_]+/\\'" contents)
3501 (let ((exp (condition-case ()
3502 (expand-file-name
3503 (substitute-in-file-name (substring contents 0 -1))
3504 ido-current-directory)
3505 (error nil))))
3506 (ido-trace contents exp)
3507 (when (and exp (file-directory-p exp))
3508 (ido-set-current-directory (file-name-directory exp))
3509 (setq ido-text-init (file-name-nondirectory exp))
3510 (setq refresh t))))
3511 ((and (memq system-type '(windows-nt ms-dos))
3512 (string-equal (substring contents 1) ":/"))
3513 (ido-set-current-directory (file-name-directory contents))
3514 (setq refresh t))
3515 ((string-equal (substring contents -2 -1) "/")
71296446 3516 (ido-set-current-directory
bad111c2
KS
3517 (if (memq system-type '(windows-nt ms-dos))
3518 (expand-file-name "/" ido-current-directory)
3519 "/"))
3520 (setq refresh t))
3521 (t
3522 (ido-trace "try single dir")
3523 (setq try-single-dir-match t))))
3524
3525 ((and (string-equal (substring contents -2 -1) "/")
3526 (not (string-match "[$]" contents)))
3527 (ido-set-current-directory
3528 (cond
3529 ((= (length contents) 2)
3530 "/")
3531 (ido-matches
789d1bf0 3532 (concat ido-current-directory (car ido-matches)))
bad111c2
KS
3533 (t
3534 (concat ido-current-directory (substring contents 0 -1)))))
3535 (setq ido-text-init (substring contents -1))
3536 (setq refresh t))
3537
3538 ((and (not ido-use-merged-list)
3539 (not (ido-final-slash contents))
3540 (eq ido-try-merged-list t)
3541 (numberp ido-auto-merge-work-directories-length)
3542 (> ido-auto-merge-work-directories-length 0)
3543 (= (length contents) ido-auto-merge-work-directories-length)
3544 (not (and ido-auto-merge-inhibit-characters-regexp
3545 (string-match ido-auto-merge-inhibit-characters-regexp contents)))
3546 (not (input-pending-p)))
3547 (setq ido-use-merged-list 'auto
3548 ido-text-init contents
3549 ido-rotate-temp t)
3550 (setq refresh t))
3551
3552 (t nil))
3553
3554 (when refresh
3555 (ido-trace "refresh on /" ido-text-init)
3556 (setq ido-exit 'refresh)
3557 (exit-minibuffer))
789d1bf0 3558
bad111c2
KS
3559 ;; Update the list of matches
3560 (setq ido-text contents)
3561 (ido-set-matches)
3562 (ido-trace "new " ido-matches)
3563
3564 (when (and ido-enter-single-matching-directory
3565 ido-matches
3566 (null (cdr ido-matches))
3567 (ido-final-slash (car ido-matches))
3568 (or try-single-dir-match
3569 (eq ido-enter-single-matching-directory t)))
3570 (ido-trace "single match" (car ido-matches))
71296446 3571 (ido-set-current-directory
bad111c2
KS
3572 (concat ido-current-directory (car ido-matches)))
3573 (setq ido-exit 'refresh)
3574 (exit-minibuffer))
3575
3576 (when (and (not ido-matches)
3577 ;; ido-rescan ?
789d1bf0
KS
3578 ido-process-ignore-lists
3579 ido-ignored-list)
bad111c2
KS
3580 (let ((ido-process-ignore-lists nil)
3581 (ido-rotate ido-rotate)
3582 (ido-cur-list ido-ignored-list))
3583 (ido-trace "try all" ido-ignored-list)
3584 (ido-set-matches))
3585 (when ido-matches
3586 (ido-trace "found " ido-matches)
3587 (setq ido-rescan t)
3588 (setq ido-process-ignore-lists-inhibit t)
3589 (setq ido-text-init ido-text)
3590 (setq ido-exit 'refresh)
3591 (exit-minibuffer)))
3592
3593 (when (and
3594 ido-rescan
3595 (not ido-matches)
3596 (memq ido-cur-item '(file dir))
3597 (not (ido-is-root-directory))
3598 (> (length contents) 1)
3599 (not (string-match "[$]" contents)))
3600 (ido-trace "merge?")
3601 (if ido-use-merged-list
3602 (ido-undo-merge-work-directory contents nil)
3603 (when (and (eq ido-try-merged-list t)
3604 (numberp ido-auto-merge-work-directories-length)
3605 (= ido-auto-merge-work-directories-length 0)
3606 (not (and ido-auto-merge-inhibit-characters-regexp
3607 (string-match ido-auto-merge-inhibit-characters-regexp contents)))
3608 (not (input-pending-p)))
3609 (ido-trace "\n*start timer*")
3610 (setq ido-auto-merge-timer
3611 (run-with-timer ido-auto-merge-delay-time nil 'ido-initiate-auto-merge (current-buffer))))))
71296446 3612
bad111c2 3613 (setq ido-rescan t)
789d1bf0 3614
71296446 3615 (if (and ido-use-merged-list
bad111c2
KS
3616 ido-matches
3617 (not (string-equal (car (cdr (car ido-matches))) ido-current-directory)))
3618 (progn
3619 (ido-set-current-directory (car (cdr (car ido-matches))))
3620 (setq ido-use-merged-list t
3621 ido-exit 'keep
3622 ido-text-init ido-text)
3623 (exit-minibuffer)))
3624
3625 ;; Insert the match-status information:
3626 (ido-set-common-completion)
71296446 3627 (let ((inf (ido-completions
bad111c2
KS
3628 contents
3629 minibuffer-completion-table
3630 minibuffer-completion-predicate
3631 (not minibuffer-completion-confirm))))
3632 (ido-trace "inf" inf)
3633 (insert inf))
3634 ))))
789d1bf0
KS
3635
3636(defun ido-completions (name candidates predicate require-match)
3637 ;; Return the string that is displayed after the user's text.
3638 ;; Modified from `icomplete-completions'.
71296446 3639
789d1bf0
KS
3640 (let* ((comps ido-matches)
3641 (ind (and (consp (car comps)) (> (length (cdr (car comps))) 1)
3642 ido-merged-indicator))
3643 first)
3644
3645 (if (and ind ido-use-faces)
3646 (put-text-property 0 1 'face 'ido-indicator-face ind))
71296446 3647
789d1bf0
KS
3648 (if (and ido-use-faces comps)
3649 (let* ((fn (ido-name (car comps)))
3650 (ln (length fn)))
3651 (setq first (format "%s" fn))
3652 (put-text-property 0 ln 'face
3653 (if (= (length comps) 1)
3654 'ido-only-match-face
3655 'ido-first-match-face)
3656 first)
3657 (if ind (setq first (concat first ind)))
3658 (setq comps (cons first (cdr comps)))))
3659
3660 (cond ((null comps)
3661 (if ido-report-no-match
3662 (nth 6 ido-decorations) ;; [No Match]
3663 ""))
3664
3665 ((null (cdr comps)) ;one match
3666 (concat (if (> (length (ido-name (car comps))) (length name))
3667 ;; when there is one match, show the matching file name in full
3668 (concat (nth 4 ido-decorations) ;; [ ... ]
3669 (ido-name (car comps))
3670 (nth 5 ido-decorations))
3671 "")
3672 (if (not ido-use-faces) (nth 7 ido-decorations)))) ;; [Matched]
3673 (t ;multiple matches
3674 (let* ((items (if (> ido-max-prospects 0) (1+ ido-max-prospects) 999))
3675 (alternatives
3676 (apply
71296446 3677 #'concat
789d1bf0 3678 (cdr (apply
9066a4d0
KS
3679 #'nconc
3680 (mapcar
3681 (lambda (com)
3682 (setq com (ido-name com))
3683 (setq items (1- items))
3684 (cond
3685 ((< items 0) ())
3686 ((= items 0) (list (nth 3 ido-decorations))) ; " | ..."
3687 (t
3688 (list (or ido-separator (nth 2 ido-decorations)) ; " | "
3689 (let ((str (substring com 0)))
3690 (if (and ido-use-faces
3691 (not (string= str first))
3692 (ido-final-slash str))
3693 (put-text-property 0 (length str) 'face 'ido-subdir-face str))
3694 str)))))
3695 comps))))))
789d1bf0
KS
3696
3697 (concat
3698 ;; put in common completion item -- what you get by pressing tab
9066a4d0
KS
3699 (if (and (stringp ido-common-match-string)
3700 (> (length ido-common-match-string) (length name)))
789d1bf0
KS
3701 (concat (nth 4 ido-decorations) ;; [ ... ]
3702 (substring ido-common-match-string (length name))
3703 (nth 5 ido-decorations)))
3704 ;; list all alternatives
3705 (nth 0 ido-decorations) ;; { ... }
3706 alternatives
3707 (nth 1 ido-decorations)))))))
3708
3709(defun ido-minibuffer-setup ()
3710 "Minibuffer setup hook for `ido'."
3711 ;; Copied from `icomplete-minibuffer-setup-hook'.
71296446 3712 (when (and (boundp 'ido-completing-read)
1518d6e3
KS
3713 (or (featurep 'xemacs)
3714 (= ido-use-mycompletion-depth (minibuffer-depth))))
789d1bf0
KS
3715 (add-hook 'pre-command-hook 'ido-tidy nil t)
3716 (add-hook 'post-command-hook 'ido-exhibit nil t)
3717 (setq cua-inhibit-cua-keys t)
1518d6e3 3718 (when (featurep 'xemacs)
789d1bf0
KS
3719 (ido-exhibit)
3720 (goto-char (point-min)))
3721 (run-hooks 'ido-minibuffer-setup-hook)))
3722
3723(defun ido-tidy ()
3724 "Pre command hook for `ido'."
3725 ;; Remove completions display, if any, prior to new user input.
3726 ;; Copied from `icomplete-tidy'."
3727
3728 (when ido-auto-merge-timer
3729 (ido-trace "\n*cancel timer*" this-command)
3730 (cancel-timer ido-auto-merge-timer)
3731 (setq ido-auto-merge-timer nil))
3732
3733 (if (and (boundp 'ido-use-mycompletion-depth)
3734 (= ido-use-mycompletion-depth (minibuffer-depth)))
3735 (if (and (boundp 'ido-eoinput)
3736 ido-eoinput)
71296446 3737
789d1bf0
KS
3738 (if (> ido-eoinput (point-max))
3739 ;; Oops, got rug pulled out from under us - reinit:
3740 (setq ido-eoinput (point-max))
3741 (let ((buffer-undo-list t))
3742 (delete-region ido-eoinput (point-max))))
71296446 3743
789d1bf0
KS
3744 ;; Reestablish the local variable 'cause minibuffer-setup is weird:
3745 (make-local-variable 'ido-eoinput)
3746 (setq ido-eoinput 1))))
3747
3748(defun ido-summary-buffers-to-end ()
3749 ;; Move the summaries to the end of the buffer list.
3750 ;; This is an example function which can be hooked on to
3751 ;; `ido-make-buffer-list-hook'. Any buffer matching the regexps
3752 ;; `Summary' or `output\*$'are put to the end of the list.
71296446
JB
3753 (let ((summaries (delq nil (mapcar
3754 (lambda (x)
3755 (if (or
789d1bf0
KS
3756 (string-match "Summary" x)
3757 (string-match "output\\*\\'" x))
3758 x))
3759 ido-temp-list))))
3760 (ido-to-end summaries)))
3761
3762;;; Helper functions for other programs
3763
3764;;;###autoload
3765(defun ido-read-file-name (prompt &optional dir default-filename mustmatch initial predicate)
3766 "Read file name, prompting with PROMPT and completing in directory DIR.
3767See `read-file-name' for additional parameters."
789d1bf0
KS
3768 (cond
3769 ((or (eq predicate 'file-directory-p)
3770 (memq this-command ido-read-file-name-as-directory-commands))
3771 (ido-read-directory-name prompt dir default-filename mustmatch initial))
3772 ((and (not (memq this-command ido-read-file-name-non-ido))
3773 (or (null predicate) (eq predicate 'file-exists-p)))
789d1bf0 3774 (let (filename
310682e6
KS
3775 ido-saved-vc-hb
3776 (vc-handled-backends (and (boundp 'vc-handled-backends) vc-handled-backends))
789d1bf0
KS
3777 (ido-current-directory (expand-file-name (or dir default-directory)))
3778 (ido-work-directory-index -1)
3779 (ido-work-file-index -1)
3780 (ido-find-literal nil))
3781 (setq filename
3782 (ido-read-internal 'file prompt 'ido-file-history default-filename mustmatch initial))
3783 (if filename
3784 (concat ido-current-directory filename))))
3785 (t
3786 (let ((read-file-name-function nil))
3787 (read-file-name prompt dir default-filename mustmatch initial predicate)))))
3788
3789;;;###autoload
3790(defun ido-read-directory-name (prompt &optional dir default-dirname mustmatch initial)
3791 "Read directory name, prompting with PROMPT and completing in directory DIR.
3792See `read-file-name' for additional parameters."
3793 (let (filename
310682e6 3794 ido-saved-vc-hb
789d1bf0
KS
3795 (ido-current-directory (expand-file-name (or dir default-directory)))
3796 (ido-work-directory-index -1)
3797 (ido-work-file-index -1))
3798 (setq filename
3799 (ido-read-internal 'dir prompt 'ido-file-history default-dirname mustmatch initial))
3800 (if filename
3801 (if (and (stringp filename) (string-equal filename "."))
3802 ido-current-directory
3803 (concat ido-current-directory filename)))))
3804
ab5796a9 3805;;; arch-tag: b63a3500-1735-41bd-8a01-05373f0864da
789d1bf0 3806;;; ido.el ends here