From e15fd924cbf55ece5912b7399dd0708c3319fd6d Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Tue, 8 Apr 2025 21:35:33 +0200 Subject: [PATCH] Drop ido.el and icomplete.el --- doc/misc/Makefile.in | 4 +- doc/misc/ido.texi | 790 ------ lisp/gnus/gnus-util.el | 14 +- lisp/icomplete.el | 1011 ------- lisp/ido.el | 4933 --------------------------------- lisp/misearch.el | 8 +- lisp/net/tramp-integration.el | 13 - lisp/replace.el | 26 +- test/lisp/ido-tests.el | 54 - 9 files changed, 10 insertions(+), 6843 deletions(-) delete mode 100644 doc/misc/ido.texi delete mode 100644 lisp/icomplete.el delete mode 100644 lisp/ido.el delete mode 100644 test/lisp/ido-tests.el diff --git a/doc/misc/Makefile.in b/doc/misc/Makefile.in index dfbe1200b3e..ea3dd251374 100644 --- a/doc/misc/Makefile.in +++ b/doc/misc/Makefile.in @@ -68,7 +68,7 @@ DOCMISC_W32 = @DOCMISC_W32@ INFO_COMMON = auth autotype calc ccmode cl dbus dired-x \ ediff efaq eglot eieio emacs-gnutls \ emacs-mime epa erc ert eshell eudc eww flymake forms gnus \ - htmlfontify ido info.info mairix-el message \ + htmlfontify info.info mairix-el message \ modus-themes newsticker nxml-mode octave-mode org pcl-cvs pgg \ rcirc reftex remember sasl sc ses sieve smtpmail \ speedbar todo-mode tramp transient url use-package \ @@ -184,7 +184,7 @@ $(foreach ifile,$(filter-out info.info,$(INFO_TARGETS)),$(eval $(call info_templ ## Extra dependencies. ## FIXME Updating this list manually is unreliable. -need_emacsver = calc cl dired-x efaq efaq-w32 erc forms ido \ +need_emacsver = calc cl dired-x efaq efaq-w32 erc forms \ newsticker reftex remember use-package woman need_emacsver_prefix = $(addprefix ${buildinfodir}/,${need_emacsver}) diff --git a/doc/misc/ido.texi b/doc/misc/ido.texi deleted file mode 100644 index ee9f933aace..00000000000 --- a/doc/misc/ido.texi +++ /dev/null @@ -1,790 +0,0 @@ -\input texinfo @c -*-texinfo-*- -@setfilename ../../info/ido.info -@settitle Interactive Do -@include docstyle.texi -@include emacsver.texi - -@copying -This file documents the Ido package for GNU Emacs. - -Copyright @copyright{} 2013--2025 Free Software Foundation, Inc. - -@quotation -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.3 or -any later version published by the Free Software Foundation; with no -Invariant Sections, with the Front-Cover Texts being ``A GNU Manual'', -and with the Back-Cover Texts as in (a) below. A copy of the license -is included in the section entitled ``GNU Free Documentation License''. - -(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and -modify this GNU manual.'' -@end quotation -@end copying - -@dircategory Emacs misc features -@direntry -* Ido: (ido). Interactively do things with buffers and files. -@end direntry - -@finalout - -@titlepage -@sp 6 -@center @titlefont{Interactive Do} -@sp 4 -@center For GNU Emacs -@sp 1 -@center as distributed with Emacs @value{EMACSVER} -@sp 5 -@center Kim F. Storm -@center storm@@cua.dk -@page -@vskip 0pt plus 1filll -@insertcopying -@end titlepage - -@contents - -@ifnottex -@node Top -@top Interactive Do - -@insertcopying -@end ifnottex - -@menu -* Overview:: Basics, activation. -* Matching:: Interactivity, matching, scrolling. -* Highlighting:: Highlighting of matching items. -* Hidden Buffers and Files:: Hidden buffers, files, and directories. -* Customization:: Change the Ido functionality. -* Misc:: Various other features. - -Appendices -* GNU Free Documentation License:: The license for this documentation. - -Indexes -* Function Index:: An entry for each documented function. -* Variable Index:: An entry for each documented variable. - -@detailmenu - --- The Detailed Node Listing --- - -Overview - -* Activation:: How to use this package. -* Working Directories:: Where files have most recently been opened. - -Matching - -* Interactive Substring Matching:: Interactivity, matching, scrolling. -* Prefix Matching:: Standard completion. -* Flexible Matching:: More flexible matching. -* Regexp Matching:: Matching using regular expression. - -Customization - -* Changing List Order:: Changing the list of files. -* Find File At Point:: Make Ido guess the context. -* Ignoring:: Ignorance is bliss. -* Misc Customization:: Miscellaneous customization for Ido. - -Miscellaneous - -* All Matching:: Seeing all the matching buffers or files. -* Replacement:: Replacement for @code{read-buffer} and @code{read-file-name}. -* Other Packages:: Don't want to depend on @code{ido-everywhere}? - -@end detailmenu -@end menu - -@node Overview -@chapter Overview -@cindex overview - -@noindent -This document describes a set of features that can interactively do -things with buffers and files. All the features are described here -in detail. - -The @dfn{Ido} package lets you switch between buffers and visit -files and directories with a minimum of keystrokes. It is a superset -of Iswitchb, the interactive buffer switching package by Stephen -Eglen. - -@cindex author of Ido -@cindex Iswitchb -This package was originally written by Kim F. Storm, based on the - @file{iswitchb.el} package by Stephen Eglen. - -@menu -* Activation:: How to use this package. -* Working Directories:: Where files have most recently been opened. -@end menu - -@node Activation -@section Activation -@cindex activation -@cindex installation - -@noindent -This package is distributed with Emacs, so there is no need to install -any additional files in order to start using it. To activate, use -@kbd{M-x ido-mode}. - -@noindent -You may wish to add the following expressions to your initialization -file (@pxref{Init File,,The Emacs Initialization File, emacs, GNU -Emacs Manual}), if you make frequent use of features from this -package. - -@example -(require 'ido) -(ido-mode t) -@end example - -@node Working Directories -@section Working Directories -@cindex working directories - -@vindex ido-work-directory-list -@noindent -@dfn{Working directories} are directories where files have most -recently been opened. The current directory is inserted at the front -of this @code{ido-work-directory-list} whenever a file is opened with -@code{ido-find-file} and other file-related functions. - -@c @cindex merge -@c or maybe a new node for ``merge'' - -@c @deffn Command ido-merge-work-directories - -@c @deffn Command ido-prev-work-directory - -@c @deffn Command ido-next-work-directory - -@c @deffn Command ido-forget-work-directory - -@c @defvar ido-use-merged-list -@c @defvar ido-try-merged-list -@c @defvar ido-pre-merge-state - -@defopt ido-max-work-directory-list -This user option specifies maximum number of working directories to -record. -@end defopt - -@c see (info "(elisp) File Name Completion") -@findex ido-reread-directory -@defopt ido-max-dir-file-cache -This user option specifies maximum number of working directories to be -cached. This is the size of the cache of -@code{file-name-all-completions} results. Each cache entry is time -stamped with the modification time of the directory. Some systems, -like MS-Windows, have unreliable directory modification times, so you -may choose to disable caching on such systems, or explicitly refresh -the cache contents using the command @code{ido-reread-directory} -(usually @kbd{C-l}) in the minibuffer. -@end defopt - -@node Matching -@chapter Matching -@cindex matching - -@noindent -This section describes features of this package that have to -do with various kinds of @emph{matching}: among buffers, files, and directories. - -@menu -* Interactive Substring Matching:: Interactivity, matching, scrolling. -* Prefix Matching:: Standard completion. -* Flexible Matching:: More flexible matching. -* Regexp Matching:: Matching using regular expression. -@end menu - -@node Interactive Substring Matching -@section Interactive Substring Matching -@cindex interactive substring matching -@cindex substring, interactive matching -@cindex matching, using substring - -@noindent -As you type in a substring, the list of buffers or files currently -matching the substring is displayed as you type. The list is -ordered so that the most recent buffers or files visited come at -the start of the list. - -The buffer or file at the start of the list will be the one visited -when you press @key{RET}. By typing more of the substring, the list -is narrowed down so that gradually the buffer or file you want will be -at the top of the list. Alternatively, you can use @kbd{C-s} and -@kbd{C-r} (or the right and left arrow keys) to rotate buffer or file -names in the list until the one you want is at the top of the list. - -Completion is also available so that you can see what is common to -all of the matching buffers or files as you type. - -For example, if there are two buffers called @file{123456} and -@file{123}, with @file{123456} the most recent, when using -@code{ido-switch-buffer}, you first of all get presented with the list -of all the buffers - -@example -Buffer: @{123456 | 123@} -@end example - -If you then press @kbd{2}: - -@example -Buffer: 2[3]@{123456 | 123@} -@end example - -The items listed in @{...@} are the matching buffers, most recent -first (buffers visible in the current frame are put at the end of the -list by default). At any time you can select the item at the head of -the list by pressing @key{RET}. You can also put the first element at -the end of the list by pressing @kbd{C-s} or @key{RIGHT}, or bring -the last element to the head of the list by pressing @kbd{C-r} or -@key{LEFT}. - -@findex ido-complete -The item in [...] indicates what can be added to your input by -pressing @key{TAB} (@code{ido-complete}). In this case, you will get -"3" added to your input. - -So, press @key{TAB}: - -@example -Buffer: 23@{123456 | 123@} -@end example - -At this point, you still have two matching buffers. If you want the -first buffer in the list, you can simply press @key{RET}. If you want -the second in the list, you can press @kbd{C-s} to move it to the top -of the list and then press @key{RET} to select it. - -However, if you type @kbd{4}, you'll only have one match left: - -@example -Buffer: 234[123456] -@end example - -Since there is only one matching buffer left, it is given in [] and it -is shown in the @code{ido-only-match} face (ForestGreen). You can now -press @key{TAB} or @key{RET} to go to that buffer. - -@findex ido-select-text -If you want to create a new buffer named @file{234}, you can press -@kbd{C-j} (@code{ido-select-text}) instead of @key{TAB} or @key{RET}. - -If instead, you type @kbd{a}: - -@example -Buffer: 234a [No match] -@end example - -There are no matching buffers. If you press @key{RET} or @key{TAB}, -you can be prompted to create a new buffer called @file{234a}. - -Of course, where this function really comes in handy is when you can -specify the buffer using only a few keystrokes. In the above example, -the quickest way to get to the @file{123456} file would be just to -type @kbd{4} and then @key{RET} (assuming there isn't any newer buffer -with @kbd{4} in its name). - -@findex ido-find-file -Likewise, if you use @kbd{C-x C-f} (@code{ido-find-file}), the list of -files and directories in the current directory is provided in the same -fashion as the buffers above. The files and directories are normally -sorted in alphabetical order, but the most recently visited directory -is placed first to speed up navigating to directories that you have -visited recently. - -In addition to scrolling through the list using @kbd{} and -@kbd{}, you can use @kbd{} and @kbd{} to quickly -scroll the list to the next or previous subdirectory. - -To go down into a subdirectory and continue the file selection on -the files in that directory, simply move the directory to the head -of the list and hit @key{RET}. - -To go up to the parent directory, delete any partial file name already -specified (e.g., using @key{DEL}) and hit @key{DEL}. - -@c @deffn Command ido-delete-backward-updir - -@cindex root directory -@cindex home directory -To go to the root directory (on the current drive), enter two slashes. -On MS-DOS or Windows, to select the root of another drive, enter -@samp{X:/} where @samp{X} is the drive letter. To go to the home -directory, enter @samp{~/}. To enter Dired for this directory, use -@kbd{C-d}. - -@c TODO: a new node for ftp hosts -@cindex ftp hosts -You can also visit files on other hosts using the ange-ftp -notations @samp{/host:} and @samp{/user@@host:}. -@c @defopt ido-record-ftp-work-directories -@c @defopt ido-merge-ftp-work-directories -@c @defopt ido-cache-ftp-work-directory-time -@c @defopt ido-slow-ftp-hosts -@c @defopt ido-slow-ftp-host-regexps - -You can type @kbd{M-p} and @kbd{M-n} to change to previous/next -directories from the history, @kbd{M-s} to search for a file matching -your input, and @kbd{M-k} to remove the current directory from the history. - -If for some reason you cannot specify the proper file using -@code{ido-find-file}, you can press @kbd{C-f} to enter the normal -@code{find-file}. You can also press @kbd{C-b} to drop into -@code{ido-switch-buffer}. - -@c @kindex C-x b -@c @deffn Command ido-switch-buffer -@c This command switch to another buffer interactively. -@c @end deffn - -@c @kindex C-x C-f -@c @deffn Command ido-find-file -@c Edit file with name obtained via minibuffer. -@c @end deffn - -@c @kindex C-x d -@c @findex ido-dired -@c @deffn Command ido-dired -@c Call Dired the Ido way. -@c @end deffn - -@node Prefix Matching -@section Prefix Matching -@cindex prefix matching -@cindex matching, using prefix -@cindex standard way of completion - -@noindent -The standard way of completion with *nix shells and Emacs is to insert -a @dfn{prefix} and then hitting @key{TAB} (or another completion key). -Because this behavior has become second nature to a lot of Emacs -users, Ido offers, in addition to the default substring matching method -(see above), also the prefix matching method. The kind of matching is -the only difference to the description of the substring matching -above. - -@findex ido-toggle-prefix -@cindex toggle prefix matching -You can toggle prefix matching with @kbd{C-p} -(@code{ido-toggle-prefix}). - -For example, if you have two buffers @file{123456} and @file{123} then -hitting @kbd{2} does not match because @kbd{2} is not a prefix in any -of the buffer names. - -@node Flexible Matching -@section Flexible Matching -@cindex flexible matching - -@defopt ido-enable-flex-matching -If non-@code{nil}, Ido will do flexible string matching. Flexible -matching means that if the entered string does not match any item, any -item containing the entered characters in the given sequence will -match. -@end defopt - -@noindent -If @code{ido-enable-flex-matching} is non-@code{nil}, Ido will do a -more flexible matching (unless regexp matching is active) to find -possible matches among the available buffer or file names if no -matches are found using the normal prefix or substring matching. - -The flexible matching implies that any item which simply contains all -of the entered characters in the specified sequence will match. - -For example, if you have four files @file{alpha}, @file{beta}, -@file{gamma}, and @file{delta}, entering @samp{aa} will match -@file{alpha} and @file{gamma}, while @samp{ea} matches @file{beta} and -@file{delta}. If prefix matching is also active, @samp{aa} only -matches @file{alpha}, while @samp{ea} does not match any files. - -@node Regexp Matching -@section Regular Expression Matching -@cindex regexp matching -@cindex matching, using regular expression - -@noindent -There is limited provision for regexp matching within Ido, enabled -through @code{ido-enable-regexp} (toggle with @kbd{C-t}). This allows -you to type @samp{[ch]$} for example and see all file names ending in -@samp{c} or @samp{h}. - -@defopt ido-enable-regexp -@findex ido-toggle-regexp -If the value of this user option is non-@code{nil}, Ido will do regexp -matching. The value of this user option can be toggled within -ido-mode using @code{ido-toggle-regexp}. -@end defopt - -@strong{Please note:} Ido-style completion is inhibited when you -enable regexp matching. - -@node Highlighting -@chapter Highlighting -@cindex highlighting - -@noindent -@vindex ido-use-faces -The highlighting of matching items is controlled via -@code{ido-use-faces}. The faces used are @code{ido-first-match}, -@code{ido-only-match} and @code{ido-subdir}. - -Coloring of the matching items was suggested by Carsten Dominik. - -@node Hidden Buffers and Files -@chapter Hidden Buffers and Files -@cindex hidden buffers and files - -Normally, Ido does not include hidden buffers (whose names start with -a space) and hidden files and directories (whose names start with -@file{.}) in the list of possible completions. However, if the -substring you enter does not match any of the visible buffers or -files, Ido will automatically look for completions among the hidden -buffers or files. - -@findex ido-toggle-ignore -You can toggle the display of hidden buffers and files with @kbd{C-a} -(@code{ido-toggle-ignore}). - -@c @deffn Command ido-toggle-ignore - -@node Customization -@chapter Customization -@cindex customization - -@noindent -You can customize the @code{ido} group to change Ido functionality: - -@example -M-x customize-group @key{RET} ido @key{RET} -@end example - -@noindent -or customize a certain variable: - -@example -M-x customize-variable @key{RET} ido-xxxxx @key{RET} -@end example - -@vindex ido-setup-hook -To modify the key bindings, use the @code{ido-setup-hook}. For example: - -@example -(add-hook 'ido-setup-hook 'ido-my-keys) - -(defun ido-my-keys () - "Add my key bindings for Ido." - (keymap-set ido-completion-map "SPC" 'ido-next-match)) -@end example - -@c @defopt ido-setup-hook -@c a new node for Ido hooks? - -@menu -* Changing List Order:: Changing the list of files. -* Find File At Point:: Make Ido guess the context. -* Ignoring:: Ignorance is bliss. -* Misc Customization:: Miscellaneous customization for Ido. -@end menu - -@node Changing List Order -@section Changing List Order -@cindex changing order of the list - -@noindent -By default, the list of current files is most recent first, -oldest last, with the exception that the files visible in the -current frame are put at the end of the list. A hook exists to -allow other functions to order the list. For example, if you add: - -@example -(add-hook 'ido-make-buffer-list-hook 'ido-summary-buffers-to-end) -@end example - -@noindent -then all files matching "Summary" are moved to the end of the list. -(I find this handy for keeping the INBOX Summary and so on out of the -way.) It also moves files matching @samp{output\*$} to the end of the -list (these are created by AUCTeX when compiling.) Other functions -could be made available which alter the list of matching files (either -deleting or rearranging elements.) - -@node Ignoring -@section Ignoring Buffers and Files -@cindex ignoring -@cindex regexp, ignore buffers and files - -@noindent -Ido is capable of ignoring buffers, directories, files and extensions -using regular expressions. - -@defopt ido-ignore-buffers -This variable takes a list of regular expressions for buffers to -ignore in @code{ido-switch-buffer}. -@end defopt - -@defopt ido-ignore-directories -This variable takes a list of regular expressions for (sub)directories -names to ignore in @code{ido-dired} and @code{ido-find-file}. -@end defopt - -@defopt ido-ignore-files -This variable takes a list of regular expressions for files to ignore -in @code{ido-find-file}. -@end defopt - -@defopt ido-ignore-unc-host-regexps -This variable takes a list of regular expressions matching UNC hosts -to ignore. The letter case will be ignored if -@code{ido-downcase-unc-hosts} is non-@code{nil}. -@end defopt - -@c FIXME: Where to add this variable? This node or ``working directory''? -@c @defopt ido-work-directory-list-ignore-regexps - -To make Ido use @code{completion-ignored-extensions} you need to -enable it: - -@example -(setq ido-ignore-extensions t) -@end example - -@vindex completion-ignored-extensions -Now you can customize @code{completion-ignored-extensions} as well. -Go ahead and add all the useless object files, backup files, shared -library files and other computing flotsam you don't want Ido to show. - -@strong{Please note:} Ido will still complete the ignored elements -if it would otherwise not show any other matches. So if you type out -the name of an ignored file, Ido will still let you open it just fine. - -@node Misc Customization -@section Miscellaneous Customization -@cindex miscellaneous customization for Ido - -@c Variables described in this sections may be moved to new nodes in -@c the future. - -@defopt ido-mode -This user option determines for which functional group (buffer and -files) Ido behavior should be enabled. -@end defopt - -@defopt ido-case-fold -If the value of this user option is non-@code{nil}, searching of -buffer and file names should ignore case. -@end defopt - -@defopt ido-show-dot-for-dired -If the value of this user option is non-@code{nil}, always put -@samp{.} as the first item in file name lists. This allows the -current directory to be opened immediately with Dired -@end defopt - -@defopt ido-enable-dot-prefix -If the value of this user option is non-@code{nil}, Ido will match -leading dot as prefix. I.e., hidden files and buffers will match only -if you type a dot as first char (even if @code{ido-enable-prefix} is -@code{nil}). -@end defopt - -@defopt ido-confirm-unique-completion -If the value of this user option is non-@code{nil}, even a unique -completion must be confirmed. This means that @code{ido-complete} -(@key{TAB}) must always be followed by @code{ido-exit-minibuffer} -(@key{RET}) even when there is only one unique completion. -@end defopt - -@defopt ido-cannot-complete-command -When @code{ido-complete} can't complete any more, it will run the -command specified by this user option. The most useful values are -@code{ido-completion-help}, which pops up a window with completion -alternatives, or @code{ido-next-match} or @code{ido-prev-match}, which -cycle the buffer list. -@end defopt - -@defopt ido-max-file-prompt-width -This user option specifies the upper limit of the prompt string. If -its value is an integer, it specifies the number of characters of the -string. If its value is a floating point number, it specifies a -fraction of the frame width. -@end defopt - -@defopt ido-max-window-height -If the value of this user option is non-@code{nil}, its value will -override the variable @code{max-mini-window-height}, which is the -maximum height for resizing mini-windows (the minibuffer and the echo -area). If it's a floating point number, it specifies a fraction of -the mini-window frame's height. If it's an integer, it specifies the -number of lines. -@end defopt - -@defopt ido-record-commands -If the value of this user option is non-@code{nil}, Ido will record -commands in the variable @code{command-history}. Note that non-Ido -equivalent is recorded. -@end defopt - -@defopt ido-all-frames -This user option will be passed to @code{walk-windows} as its -@var{all-frames} argument when Ido is finding buffers. @xref{Cyclic -Window Ordering, , Cyclic Ordering of Windows, elisp, GNU Emacs Lisp -Reference Manual}. -@end defopt - -@defopt ido-minibuffer-setup-hook -This hook variable contains Ido-specific customization of minibuffer -setup. It is run during minibuffer setup if Ido is active, and is -intended for use in customizing ido for interoperation with other -packages. -@end defopt - -@c @defopt ido-enable-tramp-completion -@c cross-reference to tramp.texi - -@c @cindex UNC host names, completion -@c @defopt ido-unc-hosts -@c @defopt ido-downcase-unc-hosts -@c @defopt ido-cache-unc-host-shares-time - -@c @defopt ido-enable-last-directory-history -@c @defopt ido-max-work-file-list -@c @defopt ido-work-directory-match-only -@c @defopt ido-auto-merge-work-directories-length -@c @defopt ido-auto-merge-delay-time -@c @defopt ido-auto-merge-inhibit-characters-regexp -@c @defopt ido-merged-indicator -@c @defopt ido-max-directory-size -@c @defopt ido-rotate-file-list-default -@c @defopt ido-enter-matching-directory -@c @defopt ido-create-new-buffer -@c @defopt ido-separator -@c @defopt ido-decorations -@c @defopt ido-use-virtual-buffers -@c @defopt ido-use-faces -@c @defopt ido-make-file-list-hook -@c @defopt ido-make-dir-list-hook -@c @defopt ido-make-buffer-list-hook -@c @defopt ido-rewrite-file-prompt-functions -@c @defopt ido-completion-buffer -@c @defopt ido-completion-buffer-all-completions -@c @defopt ido-save-directory-list-file -@c @defopt ido-read-file-name-as-directory-commands -@c @defopt ido-read-file-name-non-ido -@c @defopt ido-before-fallback-functions -@c @defopt ido-buffer-disable-smart-matches - -@node Misc -@chapter Miscellaneous -@cindex miscellaneous - -@noindent -After @kbd{C-x b} (@code{ido-switch-buffer}), the buffer at the head -of the list can be killed by pressing @kbd{C-k}. If the buffer needs -saving, you will be queried before the buffer is killed. @kbd{C-S-b} -buries the buffer at the end of the list. - -Likewise, after @kbd{C-x C-f}, you can delete (i.e., physically -remove) the file at the head of the list with @kbd{C-k}. You will -always be asked for confirmation before deleting the file. - -If you enter @kbd{C-x b} to switch to a buffer visiting a given file, -and you find that the file you are after is not in any buffer, you can -press @kbd{C-f} to immediately drop into @code{ido-find-file}. You -can switch back to buffer selection with @kbd{C-b}. - -@c @deffn Command ido-magic-forward-char -@c @deffn Command ido-magic-backward-char - -You can also use Ido in your Emacs Lisp programs: - -@example -(setq my-pkgs (list "CEDET" "Gnus" "Rcirc" "Tramp" "Org" "all-of-them")) -(ido-completing-read "What's your favorite package? " my-pkgs) -@end example - -@menu -* All Matching:: Seeing all the matching buffers or files. -* Replacement:: Replacement for @code{read-buffer} and @code{read-file-name}. -* Other Packages:: Don't want to depend on @code{ido-everywhere}? -@end menu - -@node All Matching -@section All Matching -@cindex all matching -@cindex seeing all the matching buffers or files - -@noindent -If you have many matching files, they may not all fit onto one line of -the minibuffer. Normally, the minibuffer window will grow to show you -more of the matching files (depending on the value of the variables -@code{resize-mini-windows} and @code{max-mini-window-height}). If you -want Ido to behave differently from the default minibuffer resizing -behavior, set the variable @code{ido-max-window-height}. - -Also, to improve the responsiveness of Ido, the maximum number of -matching items is limited to 12, but you can increase or remove this -limit via the @code{ido-max-prospects} user option. - -@c @defopt ido-max-prospects - -To see a full list of all matching buffers in a separate buffer, hit -@kbd{?} or press @key{TAB} when there are no further completions to -the substring. Repeated @key{TAB} presses will scroll you through -this separate buffer. - -@node Replacement -@section Replacement - -@noindent -@code{ido-read-buffer} and @code{ido-read-file-name} have been written -to be drop-in replacements for the normal buffer and file name reading -functions @code{read-buffer} and @code{read-file-name}. - -To use ido for all buffer and file selections in Emacs, customize the -variable @code{ido-everywhere}. - -@c @deffn Command ido-everywhere -@c @defopt ido-everywhere - -@node Other Packages -@section Other Packages -@cindex other packages -@cindex used by other packages - -@noindent -If you don't want to rely on the @code{ido-everywhere} functionality, -@code{ido-read-buffer}, @code{ido-read-file-name}, and -@code{ido-read-directory-name} can be used by other packages to read a -buffer name, a file name, or a directory name in the @emph{Ido} way. - -@c @node Cheatsheet - -@c * History and Acknowledgments:: How Ido came into being -@c @node History and Acknowledgments -@c @appendix History and Acknowledgments - -@node GNU Free Documentation License -@appendix GNU Free Documentation License -@include doclicense.texi - -@node Function Index -@unnumbered Function Index - -@printindex fn - -@node Variable Index -@unnumbered Variable Index - -@printindex vr - -@bye diff --git a/lisp/gnus/gnus-util.el b/lisp/gnus/gnus-util.el index 642a051e490..9f532dfeb9f 100644 --- a/lisp/gnus/gnus-util.el +++ b/lisp/gnus/gnus-util.el @@ -38,16 +38,13 @@ (require 'time-date) (require 'text-property-search) -(defcustom gnus-completing-read-function 'gnus-emacs-completing-read +(defcustom gnus-completing-read-function #'gnus-emacs-completing-read "Function use to do completing read." :version "29.1" :group 'gnus-meta :type '(radio (function-item :doc "Use Emacs standard `completing-read' function." - gnus-emacs-completing-read) - (function-item - :doc "Use `ido-completing-read' function." - gnus-ido-completing-read))) + gnus-emacs-completing-read))) (defcustom gnus-completion-styles (append (when (and (assq 'substring completion-styles-alist) @@ -1178,13 +1175,6 @@ SPEC is a predicate specifier that contains stuff like `or', `and', (completing-read prompt collection nil require-match initial-input history def))) -(autoload 'ido-completing-read "ido") -(defun gnus-ido-completing-read (prompt collection &optional require-match - initial-input history def) - "Call `ido-completing-read'." - (ido-completing-read prompt collection nil require-match - initial-input history def)) - (defmacro gnus-parse-without-error (&rest body) "Allow continuing onto the next line even if an error occurs." (declare (indent 0) (debug t)) diff --git a/lisp/icomplete.el b/lisp/icomplete.el deleted file mode 100644 index 729044f24f5..00000000000 --- a/lisp/icomplete.el +++ /dev/null @@ -1,1011 +0,0 @@ -;;; icomplete.el --- minibuffer completion incremental feedback -*- lexical-binding: t -*- - -;; Copyright (C) 1992-2025 Free Software Foundation, Inc. - -;; Author: Ken Manheimer -;; Created: Mar 1993 Ken Manheimer, klm@nist.gov - first release to usenet -;; Keywords: help, abbrev - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Enabling this package implements a more fine-grained minibuffer -;; completion feedback scheme. Prospective completions are concisely -;; indicated within the minibuffer itself, with each successive -;; keystroke. - -;; See `icomplete-completions' docstring for a description of the -;; icomplete display format. - -;; See the `icomplete-minibuffer-setup-hook' docstring for a means to -;; customize icomplete setup for interoperation with other -;; minibuffer-oriented packages. - -;; To enable/disable icomplete mode, use the `icomplete-mode' function. - -;; Thanks to everyone for their suggestions for refinements of this -;; package. I particularly have to credit Michael Cook, who -;; implemented an incremental completion style in his 'iswitch' -;; functions that served as a model for icomplete. Some other -;; contributors: Noah Friedman (restructuring as minor mode), Colin -;; Rafferty (lemacs reconciliation), Lars Lindberg, RMS, and others. - -;; klm. - -;;; Code: - -(require 'rfn-eshadow) ; rfn-eshadow-overlay -(require 'simple) ; max-mini-window-lines -(require 'cl-lib) - -(defgroup icomplete nil - "Show completions dynamically in minibuffer." - :prefix "icomplete-" - :link '(info-link "(emacs)Icomplete") - :group 'minibuffer) - -(defcustom icomplete-separator " | " - "String used by Icomplete to separate alternatives in the minibuffer." - :type 'string - :version "24.4") - -(defcustom icomplete-hide-common-prefix t - "When non-nil, hide common prefix from completion candidates. -When nil, show candidates in full." - :type 'boolean - :version "24.4") - -(defcustom icomplete-tidy-shadowed-file-names nil - "If non-nil, automatically delete superfluous parts of file names. -For example, if the user types ~/ after a long path name, -everything preceding the ~/ is discarded so the interactive -selection process starts again from the user's $HOME." - :type 'boolean) - -(defcustom icomplete-show-matches-on-no-input nil - "When non-nil, show completions when first prompting for input. -This means to show completions even when the current minibuffer contents -is the same as was the initial input after minibuffer activation. -This also means that if you traverse the list of completions with -commands like \\`C-.' and just hit \\`RET' without typing any -characters, the match under point will be chosen instead of the -default." - :type 'boolean - :version "24.4") - -(defcustom icomplete-with-completion-tables t - "Specialized completion tables with which Icomplete should operate. -If this is t, Icomplete operates on all tables. -Otherwise this should be a list of the completion tables (e.g., -`internal-complete-buffer') on which Icomplete should operate." - ;; Prior to 24.4, not a user-option, default '(internal-complete-buffer). - :version "24.4" - :type '(choice (const :tag "All" t) - (repeat function))) - -(defcustom icomplete-matches-format "%s/%s " - "Format of the current/total number of matches for the prompt prefix." - :version "28.1" - :type '(choice (const :tag "No prefix" nil) - (string :tag "Prefix format string"))) - -(defface icomplete-first-match '((t :weight bold)) - "Face used by Icomplete for highlighting first match." - :version "24.4") - -(defface icomplete-selected-match '((t :inherit highlight)) - "Face used by `icomplete-vertical-mode' for the selected candidate." - :version "28.1") - -(defface icomplete-section '((t :inherit shadow :slant italic)) - "Face used by `icomplete-vertical-mode' for the section title." - :version "28.1") - -;;;_* User Customization variables -(defcustom icomplete-prospects-height 2 - ;; We used to compute how many lines 100 characters would take in - ;; the current window width, but the return value of `window-width' - ;; is unreliable on startup (e.g., if we're in daemon mode), so now - ;; we simply base the default value on an 80 column window. - "Maximum number of lines to use in the minibuffer." - :type 'integer - :version "26.1") - -(defcustom icomplete-compute-delay .15 - "Completions-computation stall, used only with large-number completions. -See `icomplete-delay-completions-threshold'." - :type 'number) - -(defcustom icomplete-delay-completions-threshold 400 - "Pending-completions number over which to apply `icomplete-compute-delay'." - :type 'integer) - -(defcustom icomplete-max-delay-chars 2 - "Maximum number of initial chars to apply `icomplete-compute-delay'." - :type 'integer) - -(defcustom icomplete-minibuffer-setup-hook nil - "Icomplete-specific customization of minibuffer setup. - -This hook is run during minibuffer setup if Icomplete is active. -It is intended for use in customizing Icomplete for interoperation -with other features and packages. For instance: - - (add-hook \\='icomplete-minibuffer-setup-hook - (lambda () (setq-local max-mini-window-height 3))) - -will constrain Emacs to a maximum minibuffer height of 3 lines when -icompletion is occurring." - :type 'hook) - - -;;;_* Initialization - -;;;_ + Internal Variables -;;;_ = icomplete-eoinput nil -(defvar icomplete-overlay (make-overlay (point-min) (point-min) nil t t) - "Overlay used to display the list of completions.") - -(defvar icomplete--initial-input nil - "Initial input in the minibuffer when `icomplete-mode' was activated. -Used to implement the option `icomplete-show-matches-on-no-input'.") - -(defun icomplete-post-command-hook () - (setq completion-all-sorted-completions - (and (memq this-command - '(icomplete-forward-completions - icomplete-backward-completions)) - completion-all-sorted-completions)) - (let ((non-essential t)) ;E.g. don't prompt for password! - (icomplete-exhibit))) - -(defvar-keymap icomplete-minibuffer-map - :doc "Keymap used by `icomplete-mode' in the minibuffer." - "C-M-i" #'icomplete-force-complete - "C-j" #'icomplete-force-complete-and-exit - "C-." #'icomplete-forward-completions - "C-," #'icomplete-backward-completions - " " #'icomplete-ret) - -(defun icomplete-ret () - "Exit minibuffer for icomplete." - (interactive) - (if (and icomplete-show-matches-on-no-input - (car completion-all-sorted-completions) - (equal (icomplete--field-string) icomplete--initial-input)) - (icomplete-force-complete-and-exit) - (minibuffer-complete-and-exit))) - -(defun icomplete-force-complete-and-exit () - "Complete the minibuffer with the longest possible match and exit. -Use the first of the matches if there are any displayed, and use -the default otherwise." - (interactive) - ;; This function is tricky. The mandate is to "force", meaning we - ;; should take the first possible valid completion for the input. - ;; However, if there is no input and we can prove that that - ;; coincides with the default, it is much faster to just call - ;; `minibuffer-complete-and-exit'. Otherwise, we have to call - ;; `minibuffer-force-complete-and-exit', which needs the full - ;; completion set and is potentially slow and blocking. Do the - ;; latter if: - (if (or - ;; there's some input, meaning the default in off the table by - ;; definition; OR - (not (equal (icomplete--field-string) icomplete--initial-input)) - ;; there's no input, but there's also no minibuffer default - ;; (and the user really wants to see completions on no input, - ;; meaning he expects a "force" to be at least attempted); OR - (and (not minibuffer-default) - icomplete-show-matches-on-no-input) - ;; there's no input but the full completion set has been - ;; calculated, This causes the first cached completion to - ;; be taken (i.e. the one that the user sees highlighted) - completion-all-sorted-completions) - (minibuffer-force-complete-and-exit) - ;; Otherwise take the faster route... - (minibuffer-complete-and-exit))) - -(defun icomplete-force-complete () - "Complete the icomplete minibuffer." - (interactive) - ;; We're not at all interested in cycling here (bug#34077). - (if (window-minibuffer-p) - (minibuffer-force-complete) - (minibuffer-force-complete (icomplete--field-beg) (icomplete--field-end)))) - -;; Apropos `icomplete-scroll', we implement "scrolling icomplete" -;; within classic icomplete, which is "rotating", by contrast. -;; -;; The two variables supporting this are -;; `icomplete--scrolled-completions' and `icomplete--scrolled-past'. -;; They come into play when: -;; -;; - The user invokes commands `icomplete-forward-completions' and -;; `icomplete-backward-completions', thus "manually" scrolling to a -;; given position; -;; -;; - The user re-filters a selection that had already been manually -;; scrolled. The system attempts to keep the previous selection -;; stable in the face of the new filtering. This is mostly done in -;; `icomplete--render-vertical'. -;; -(defvar icomplete-scroll nil - "If non-nil, scroll candidates list instead of rotating it.") -(defvar icomplete--scrolled-completions nil - "If non-nil, tail of completions list manually scrolled to.") -(defvar icomplete--scrolled-past nil - "If non-nil, reverse tail of completions scrolled past.") - -(defun icomplete-forward-completions () - "Step forward completions by one entry. -Second entry becomes the first and can be selected with -`icomplete-force-complete-and-exit'. -Return non-nil if something was stepped." - (interactive) - (when (consp (cdr completion-all-sorted-completions)) - (cond (icomplete-scroll - (push (pop completion-all-sorted-completions) - icomplete--scrolled-past) - (setq icomplete--scrolled-completions - completion-all-sorted-completions)) - (t - (let ((last (last completion-all-sorted-completions))) - (setcdr (last completion-all-sorted-completions) - (cons (pop completion-all-sorted-completions) - (cdr last)))))))) - -(defun icomplete-backward-completions () - "Step backward completions by one entry. -Last entry becomes the first and can be selected with -`icomplete-force-complete-and-exit'. -Return non-nil if something was stepped." - (interactive) - (let* (last-but-one) - (cond ((and icomplete-scroll icomplete--scrolled-past) - (push (pop icomplete--scrolled-past) completion-all-sorted-completions) - (setq icomplete--scrolled-completions completion-all-sorted-completions)) - ((and (not icomplete-scroll) - (consp (cdr (setq last-but-one (last completion-all-sorted-completions 2))))) - ;; At least two elements in comps - (push (car (cdr last-but-one)) completion-all-sorted-completions) - (setcdr last-but-one (cdr (cdr last-but-one))))))) - -(defun icomplete-vertical-goto-first () - "Go to first completions entry when `icomplete-scroll' is non-nil." - (interactive) - (unless icomplete-scroll (error "Only works with `icomplete-scroll'")) - (while (icomplete-backward-completions))) - -(defun icomplete-vertical-goto-last () - "Go to last completions entry when `icomplete-scroll' is non-nil." - (interactive) - (unless icomplete-scroll (error "Only works with `icomplete-scroll'")) - (while (icomplete-forward-completions))) - -;;;_* Helpers for `fido-mode' (or `ido-mode' emulation) - -(defun icomplete-fido-kill () - "Kill line or current completion, like `ido-mode'. -If killing to the end of line make sense, call `kill-line', -otherwise kill the currently selected completion candidate. -Exactly what killing entails is dependent on the things being -completed. If completing files, it means delete the file. If -completing buffers it means kill the buffer. Both actions -require user confirmation." - (interactive) - (let ((end (icomplete--field-end))) - (if (< (point) end) - (call-interactively 'kill-line) - (let* ((all (completion-all-sorted-completions)) - (thing (car all)) - (cat (icomplete--category)) - (action - (cl-case cat - (buffer - (lambda () - (when (yes-or-no-p (concat "Kill buffer " thing "? ")) - (kill-buffer thing)))) - ((project-file file) - (lambda () - (let* ((dir (file-name-directory (icomplete--field-string))) - (path (expand-file-name thing dir))) - (when (yes-or-no-p (concat "Delete file " path "? ")) - (delete-file path) t)))) - (t - (error "Sorry, don't know how to kill things for `%s'" cat))))) - (let (;; Allow `yes-or-no-p' to work and don't let it - ;; `icomplete-exhibit' anything. - (icomplete-mode nil)) - (funcall action)) - (message nil))))) - -(defun icomplete-fido-delete-char () - "Delete char or maybe call `dired', like `ido-mode'." - (interactive) - (let ((end (icomplete--field-end))) - (if (or (< (point) end) (not (eq (icomplete--category) 'file))) - (call-interactively 'delete-char) - (dired (file-name-directory (icomplete--field-string))) - (exit-minibuffer)))) - -(defun icomplete-fido-ret () - "Exit minibuffer or enter directory, like `ido-mode'." - (interactive) - (let* ((dir (and (eq (icomplete--category) 'file) - (file-name-directory (icomplete--field-string)))) - (current (car completion-all-sorted-completions)) - (probe (and dir current - (expand-file-name (directory-file-name current) - (substitute-env-vars dir))))) - (cond ((and probe (file-directory-p probe) (not (string= current "./"))) - (icomplete-force-complete)) - (t - (icomplete-force-complete-and-exit))))) - -(defun icomplete-fido-exit (force) - "Attempt to exit minibuffer immediately with current input. -Unless FORCE is non-nil (interactively with a prefix argument), -honor a non-nil REQUIRE-MATCH argument to `completing-read' by -trying to complete as much as possible and disallowing the exit -if that doesn't produce a completion match." - (interactive "P") - (if (and (not force) minibuffer--require-match) - (minibuffer-complete-and-exit) - (exit-minibuffer))) - -(defun icomplete-fido-backward-updir () - "Delete char before or go up directory, like `ido-mode'." - (interactive) - (cond ((and (eq (char-before) ?/) - (eq (icomplete--category) 'file)) - (when (string-equal (icomplete--field-string) "~/") - (delete-region (icomplete--field-beg) (icomplete--field-end)) - (insert (expand-file-name "~/")) - (goto-char (line-end-position))) - (save-excursion - (goto-char (1- (point))) - (when (search-backward "/" (point-min) t) - (delete-region (1+ (point)) (point-max))))) - (t (call-interactively 'backward-delete-char)))) - -(defvar-keymap icomplete-fido-mode-map - :doc "Keymap used by `fido-mode' in the minibuffer." - "C-k" #'icomplete-fido-kill - "C-d" #'icomplete-fido-delete-char - "RET" #'icomplete-fido-ret - "C-m" #'icomplete-fido-ret - "DEL" #'icomplete-fido-backward-updir - "M-j" #'icomplete-fido-exit - "C-s" #'icomplete-forward-completions - "C-r" #'icomplete-backward-completions - "" #'icomplete-forward-completions - "" #'icomplete-backward-completions - "C-." #'icomplete-forward-completions - "C-," #'icomplete-backward-completions) - -(defun icomplete--fido-ccd () - "Make value for `completion-category-defaults' prioritizing `flex'." - (cl-loop - for (cat . alist) in completion-category-defaults collect - `(,cat . ,(cl-loop - for entry in alist for (prop . val) = entry - if (and (eq prop 'styles) - ;; Never step in front of 'external', as that - ;; might lose us completions. - (not (memq 'external val))) - collect `(,prop . (flex ,@(delq 'flex val))) - else collect entry)))) - -(defun icomplete--fido-mode-setup () - "Setup `fido-mode''s minibuffer." - (when (and icomplete-mode (icomplete-simple-completing-p)) - (use-local-map (make-composed-keymap icomplete-fido-mode-map - (current-local-map))) - (setq-local icomplete-tidy-shadowed-file-names t - icomplete-show-matches-on-no-input t - icomplete-hide-common-prefix nil - icomplete-scroll (not (null icomplete-vertical-mode)) - completion-styles '(flex) - completion-flex-nospace nil - completion-category-defaults (icomplete--fido-ccd) - completion-ignore-case t - read-buffer-completion-ignore-case t - read-file-name-completion-ignore-case t))) - -;;;###autoload -(define-minor-mode fido-mode - "An enhanced `icomplete-mode' that emulates `ido-mode'. - -This global minor mode makes minibuffer completion behave -more like `ido-mode' than regular `icomplete-mode'." - :global t - (remove-hook 'minibuffer-setup-hook #'icomplete-minibuffer-setup) - (remove-hook 'minibuffer-setup-hook #'icomplete--fido-mode-setup) - (when fido-mode - (icomplete-mode -1) - (setq icomplete-mode t) - (add-hook 'minibuffer-setup-hook #'icomplete-minibuffer-setup) - (add-hook 'minibuffer-setup-hook #'icomplete--fido-mode-setup))) - -;;;_ > icomplete-mode (&optional prefix) -;;;###autoload -(define-minor-mode icomplete-mode - "Toggle incremental minibuffer completion (Icomplete mode). - -When this global minor mode is enabled, typing in the minibuffer -continuously displays a list of possible completions that match -the string you have typed. See `icomplete-completions' for a -description of how prospective completions are displayed. - -For more information, see Info node `(emacs)Icomplete'. -For options you can set, `\\[customize-group] icomplete'. - -You can use the following key bindings to navigate and select -completions: - -\\{icomplete-minibuffer-map}" - :global t - (remove-hook 'minibuffer-setup-hook #'icomplete-minibuffer-setup) - (when icomplete-mode - (fido-mode -1) - (add-hook 'minibuffer-setup-hook #'icomplete-minibuffer-setup))) - -(defun icomplete--completion-table () minibuffer-completion-table) -(defun icomplete--completion-predicate () minibuffer-completion-predicate) -(defun icomplete--field-string () (minibuffer-contents)) -(defun icomplete--field-beg () (minibuffer-prompt-end)) -(defun icomplete--field-end () (point-max)) -(defun icomplete--category () - (let* ((beg (icomplete--field-beg)) - (md (completion--field-metadata beg))) - (alist-get 'category (cdr md)))) - -;;;_ > icomplete-simple-completing-p () -(defun icomplete-simple-completing-p () - "Non-nil if current window is a minibuffer that's doing simple completion. - -Conditions are: - the selected window is a minibuffer, - and not in the middle of macro execution, - and the completion table is not a function (which would - indicate some non-standard, non-simple completion mechanism, - like file-name and other custom-func completions), - and `icomplete-with-completion-tables' doesn't restrict completion." - - (unless executing-kbd-macro - (let ((table (icomplete--completion-table))) - (and table - (or (not (functionp table)) - (eq icomplete-with-completion-tables t) - (member table icomplete-with-completion-tables)))))) - -;;;_ > icomplete-minibuffer-setup () -(defun icomplete-minibuffer-setup () - "Run in minibuffer on activation to establish incremental completion. -Usually run by inclusion in `minibuffer-setup-hook'." - (when (and icomplete-mode (icomplete-simple-completing-p)) - (setq-local icomplete--initial-input (icomplete--field-string)) - (setq-local completion-show-inline-help nil) - (setq icomplete--scrolled-completions nil) - (use-local-map (make-composed-keymap icomplete-minibuffer-map - (current-local-map))) - (add-hook 'post-command-hook #'icomplete-post-command-hook nil t) - (run-hooks 'icomplete-minibuffer-setup-hook))) - -(defun icomplete--sorted-completions () - (or completion-all-sorted-completions - (cl-loop - initially (setq icomplete--scrolled-past nil) ; Invalidate scrolled state - with beg = (icomplete--field-beg) - with end = (icomplete--field-end) - with all = (completion-all-sorted-completions beg end) - ;; Icomplete mode re-sorts candidates, bubbling the default to - ;; top if it's found somewhere down the list. This loop's - ;; iteration variable, `fn' iterates through these "bubble up - ;; predicates" which may vary depending on specific - ;; `completing-read' invocations, described below: - for fn in (cond ((and minibuffer-default - (stringp (or (car-safe minibuffer-default) - minibuffer-default)) ; bug#38992 bug#55800 - (equal (icomplete--field-string) icomplete--initial-input)) - ;; Here, we have a non-nil string default and - ;; no input whatsoever. We want to make sure - ;; that the default is bubbled to the top so - ;; that `icomplete-force-complete-and-exit' - ;; will select it. We want to do that even if - ;; the match doesn't match the completion - ;; perfectly. - ;; - `(;; The first predicate ensures that: - ;; - ;; (completing-read "thing? " '("foo" "bar") - ;; nil nil nil nil "bar") - ;; - ;; Has "bar" at the top, so RET will select - ;; it, as desired. - ,(lambda (comp) - (equal (or (car-safe minibuffer-default) - minibuffer-default) - comp)) - ;; Why do we need this second predicate? - ;; Because that'll make things like M-x man - ;; RET RET, when invoked with point on the - ;; "bar" word, behave correctly. There, the - ;; default doesn't quite match any - ;; candidate. So: - ;; - ;; (completing-read "Man entry? " '("foo(1)" "bar(1)") - ;; nil nil nil nil "bar") - ;; - ;; Will place "bar(1)" on top, and RET will - ;; select it -- again, as desired. - ;; - ;; FIXME: it's arguable that this second - ;; behavior should be a property of the - ;; completion table and not the completion - ;; frontend such as we have done - ;; here. However, it seems generically - ;; useful for a very broad spectrum of - ;; cases. - ,(lambda (comp) - (string-prefix-p (or (car-safe minibuffer-default) - minibuffer-default) - comp)))) - ((and fido-mode - (not minibuffer-default) - (eq (icomplete--category) 'file)) - ;; When there isn't a default, `fido-mode' - ;; specifically also has some extra - ;; file-sorting semantics inherited from Ido. - ;; Those make the directory "./" bubble to the - ;; top (if it exists). This makes M-x dired - ;; RET RET go to the directory of current - ;; file, which is non-Icomplete vanilla Emacs - ;; and `ido-mode' both do. - `(,(lambda (comp) - (string= "./" comp))))) - ;; After we have setup the predicates, look for a completion - ;; matching one of them and bubble up it, destructively on - ;; `completion-all-sorted-completions' (unless that completion - ;; happens to be already on top). - thereis (or - (and (funcall fn (car all)) all) - (cl-loop - for l on all - while (consp (cdr l)) - for comp = (cadr l) - when (funcall fn comp) - do (setf (cdr l) (cddr l)))) - finally return all))) - -(defvar-keymap icomplete-vertical-mode-minibuffer-map - :doc "Keymap used by `icomplete-vertical-mode' in the minibuffer." - "C-n" #'icomplete-forward-completions - "C-p" #'icomplete-backward-completions - "" #'icomplete-forward-completions - "" #'icomplete-backward-completions - "M-<" #'icomplete-vertical-goto-first - "M->" #'icomplete-vertical-goto-last) - -(defun icomplete--vertical-minibuffer-setup () - "Setup the minibuffer for vertical display of completion candidates." - (use-local-map (make-composed-keymap icomplete-vertical-mode-minibuffer-map - (current-local-map))) - (setq-local icomplete-hide-common-prefix nil - ;; Ask `icomplete-completions' to return enough completions candidates. - icomplete-prospects-height 25 - redisplay-adhoc-scroll-in-resize-mini-windows nil)) - -;;;###autoload -(define-minor-mode icomplete-vertical-mode - "Toggle vertical candidate display in `icomplete-mode' or `fido-mode'. - -If none of these modes are on, turn on `icomplete-mode'. - -As many completion candidates as possible are displayed, depending on -the value of `max-mini-window-height', and the way the mini-window is -resized depends on `resize-mini-windows'." - :global t - (remove-hook 'icomplete-minibuffer-setup-hook - #'icomplete--vertical-minibuffer-setup) - (when icomplete-vertical-mode - (unless icomplete-mode - (icomplete-mode 1)) - (add-hook 'icomplete-minibuffer-setup-hook - #'icomplete--vertical-minibuffer-setup))) - -;;;###autoload -(define-minor-mode fido-vertical-mode - "Toggle vertical candidate display in `fido-mode'. -When turning on, if non-vertical `fido-mode' is off, turn it on. -If it's on, just add the vertical display." - :global t - (icomplete-vertical-mode -1) - (when fido-vertical-mode - (unless fido-mode (fido-mode 1)) - (icomplete-vertical-mode 1))) - - - - -;;;_* Completion - -;;;_ > icomplete-exhibit () -(defun icomplete-exhibit () - "Insert Icomplete completions display. -Should be run via minibuffer `post-command-hook'. -See `icomplete-mode' and `minibuffer-setup-hook'." - (when (and icomplete-mode - ;; Check if still in the right buffer (bug#61308) - (window-minibuffer-p) - (icomplete-simple-completing-p)) ;Shouldn't be necessary. - (let ((saved-point (point)) - (completion-lazy-hilit t)) - (save-excursion - (goto-char (icomplete--field-end)) - ;; Insert the match-status information: - (when (and (or icomplete-show-matches-on-no-input - (not (equal (icomplete--field-string) - icomplete--initial-input))) - (or - ;; Don't bother with delay after certain number of chars: - (> (- (point) (icomplete--field-beg)) - icomplete-max-delay-chars) - ;; Don't delay if the completions are known. - completion-all-sorted-completions - ;; Don't delay if alternatives number is small enough: - (and (sequencep (icomplete--completion-table)) - (< (length (icomplete--completion-table)) - icomplete-delay-completions-threshold)) - ;; Delay - give some grace time for next keystroke, before - ;; embarking on computing completions: - (sit-for icomplete-compute-delay))) - (when (and - icomplete-tidy-shadowed-file-names - (eq (icomplete--category) 'file) - rfn-eshadow-overlay (overlay-buffer rfn-eshadow-overlay) - (eq this-command 'self-insert-command) - (= saved-point (icomplete--field-end)) - (or (>= (- (point) (overlay-end rfn-eshadow-overlay)) 2) - (eq ?/ (char-before (- (point) 2))))) - (delete-region (overlay-start rfn-eshadow-overlay) - (overlay-end rfn-eshadow-overlay))) - (let* ((field-string (icomplete--field-string)) - (text (while-no-input - (icomplete-completions - field-string - (icomplete--completion-table) - (icomplete--completion-predicate) - (if (window-minibuffer-p) - (eq minibuffer--require-match t))))) - (buffer-undo-list t) - deactivate-mark) - ;; Do nothing if while-no-input was aborted. - (when (stringp text) - (move-overlay icomplete-overlay (point-min) (point) (current-buffer)) - ;; The current C cursor code doesn't know to use the overlay's - ;; marker's stickiness to figure out whether to place the cursor - ;; before or after the string, so let's spoon-feed it the pos. - (put-text-property 0 1 'cursor t text) - (overlay-put - icomplete-overlay 'before-string - (and icomplete-scroll - icomplete-matches-format - (let* ((past (length icomplete--scrolled-past)) - (current (1+ past)) - (total (+ past (safe-length - completion-all-sorted-completions)))) - (format icomplete-matches-format current total)))) - (overlay-put icomplete-overlay 'after-string text)))))))) - -(defun icomplete--augment (md prospects) - "Augment completion strings in PROSPECTS with completion metadata MD. -Return a list of strings (COMP PREFIX SUFFIX SECTION). PREFIX -and SUFFIX, if non-nil, are obtained from `affixation-function' or -`annotation-function' metadata. SECTION is obtained from -`group-function'. Consecutive `equal' sections are avoided. -COMP is the element in PROSPECTS or a transformation also given -by `group-function''s second \"transformation\" protocol." - (let* ((aff-fun (completion-metadata-get md 'affixation-function)) - (ann-fun (completion-metadata-get md 'annotation-function)) - (grp-fun (and completions-group - (completion-metadata-get md 'group-function))) - (annotated - (cond (aff-fun - (funcall aff-fun prospects)) - (ann-fun - (mapcar - (lambda (comp) - (let ((suffix (or (funcall ann-fun comp) ""))) - (list comp "" - ;; The default completion UI adds the - ;; `completions-annotations' face if no - ;; other faces are present. - (if (text-property-not-all 0 (length suffix) 'face nil suffix) - suffix - (propertize suffix 'face 'completions-annotations))))) - prospects)) - (t (mapcar #'list prospects))))) - (if grp-fun - (cl-loop with section = nil - for (c prefix suffix) in annotated - for selectedp = (get-text-property 0 'icomplete-selected c) - for tr = (propertize (or (funcall grp-fun c t) c) - 'icomplete-selected selectedp) - if (not (equal section (setq section (funcall grp-fun c nil)))) - collect (list tr prefix suffix section) - else collect (list tr prefix suffix )) - annotated))) - -(cl-defun icomplete--render-vertical - (comps md &aux scroll-above scroll-below - (total-space ; number of mini-window lines available - (1- (min - icomplete-prospects-height - (truncate (max-mini-window-lines) 1))))) - ;; Welcome to loopapalooza! - ;; - ;; First, be mindful of `icomplete-scroll' and manual scrolls. If - ;; `icomplete--scrolled-completions' and `icomplete--scrolled-past' - ;; are: - ;; - ;; - both nil, there is no manual scroll; - ;; - both non-nil, there is a healthy manual scroll that doesn't need - ;; to be readjusted (user just moved around the minibuffer, for - ;; example) - ;; - non-nil and nil, respectively, a refiltering took place and we - ;; may need to readjust them to the new filtered `comps'. - (when (and icomplete-scroll - icomplete--scrolled-completions - (null icomplete--scrolled-past)) - (cl-loop with preds - for (comp . rest) on comps - when (equal comp (car icomplete--scrolled-completions)) - do - (setq icomplete--scrolled-past preds - comps (cons comp rest)) - and return nil - do (push comp preds) - finally (setq icomplete--scrolled-completions nil))) - ;; Then, in this pretty ugly loop, collect completions to display - ;; above and below the selected one, considering scrolling - ;; positions. - (cl-loop with preds = icomplete--scrolled-past - with succs = (cdr comps) - with space-above = (- total-space - 1 - (cl-loop for (_ . r) on comps - repeat (truncate total-space 2) - while (listp r) - count 1)) - repeat total-space - for neighbor = nil - if (and preds (> space-above 0)) do - (push (setq neighbor (pop preds)) scroll-above) - (decf space-above) - else if (consp succs) collect - (setq neighbor (pop succs)) into scroll-below-aux - while neighbor - finally (setq scroll-below scroll-below-aux)) - ;; Halfway there... - (let* ((selected (propertize (car comps) 'icomplete-selected t)) - (chosen (append scroll-above (list selected) scroll-below)) - (tuples (icomplete--augment md chosen)) - max-prefix-len max-comp-len lines nsections) - (add-face-text-property 0 (length selected) - 'icomplete-selected-match 'append selected) - ;; Figure out parameters for horizontal spacing - (cl-loop - for (comp prefix) in tuples - maximizing (length prefix) into max-prefix-len-aux - maximizing (length comp) into max-comp-len-aux - finally (setq max-prefix-len max-prefix-len-aux - max-comp-len max-comp-len-aux)) - ;; Serialize completions and section titles into a list - ;; of lines to render - (cl-loop - for (comp prefix suffix section) in tuples - when section - collect (propertize section 'face 'icomplete-section) into lines-aux - and count 1 into nsections-aux - when (get-text-property 0 'icomplete-selected comp) - do (add-face-text-property 0 (length comp) - 'icomplete-selected-match 'append comp) - collect (concat prefix - (make-string (- max-prefix-len (length prefix)) ? ) - (completion-lazy-hilit comp) - (make-string (- max-comp-len (length comp)) ? ) - suffix) - into lines-aux - finally (setq lines lines-aux - nsections nsections-aux)) - ;; Kick out some lines from the beginning due to extra sections. - ;; This hopes to keep the selected entry more or less in the - ;; middle of the dropdown-like widget when `icomplete-scroll' is - ;; t. Funky, but at least I didn't use `cl-loop' - (setq lines - (nthcdr - (cond ((<= (length lines) total-space) 0) - ((> (length scroll-above) (length scroll-below)) nsections) - (t (min (ceiling nsections 2) (length scroll-above)))) - lines)) - ;; At long last, render final string return value. This may still - ;; kick out lines at the end. - (concat " \n" - (cl-loop for l in lines repeat total-space concat l concat "\n")))) - -;;;_ > icomplete-completions (name candidates predicate require-match) -(defun icomplete-completions (name candidates predicate require-match) - "Identify prospective candidates for minibuffer completion. - -The display is updated with each minibuffer keystroke during -minibuffer completion. - -Prospective completion suffixes (if any) are displayed, bracketed by -one of (), [], or {} pairs. The choice of brackets is as follows: - - (...) - a single prospect is identified and matching is enforced, - [...] - a single prospect is identified but matching is optional, or - {...} - multiple prospects, separated by commas, are indicated, and - further input is required to distinguish a single one. - -If there are multiple possibilities, `icomplete-separator' separates them. - -The displays for unambiguous matches have ` [Matched]' appended -\(whether complete or not), or ` [No matches]', if no eligible -matches exist." - (let* ((minibuffer-completion-table candidates) - (md (completion--field-metadata (icomplete--field-beg))) - (comps (icomplete--sorted-completions)) - (open-bracket (if require-match "(" "[")) - (close-bracket (if require-match ")" "]"))) - ;; `concat'/`mapconcat' is the slow part. - (if (not (consp comps)) - (progn ;;(debug (format "Candidates=%S field=%S" candidates name)) - (format " %sNo matches%s" open-bracket close-bracket)) - (if icomplete-vertical-mode - (icomplete--render-vertical comps md) - (let* ((last (if (consp comps) (last comps))) - ;; Save the "base size" encoded in `comps' then - ;; removing making `comps' a proper list. - (base-size (prog1 (cdr last) - (if last (setcdr last nil)))) - (most-try - ;; icomplete-hide-common-prefix logic is used - ;; unconditionally when there is single match. - (when (or icomplete-hide-common-prefix (not (cdr comps))) - (if (and base-size (> base-size 0)) - (completion-try-completion - name candidates predicate (length name) md) - ;; If the `comps' are 0-based, the result should be - ;; the same with `comps'. - (completion-try-completion - name comps nil (length name) md)))) - (most (if (consp most-try) (car most-try) - (if most-try (car comps) ""))) - ;; Compare name and most, so we can determine if name is - ;; a prefix of most, or something else. - (compare (compare-strings name nil nil - most nil nil completion-ignore-case)) - (ellipsis (if (char-displayable-p ?…) "…" "...")) - (determ (unless (or (eq t compare) (eq t most-try) - (= (setq compare (1- (abs compare))) - (length most))) - (concat open-bracket - (cond - ((= compare (length name)) - ;; Typical case: name is a prefix. - (substring most compare)) - ;; Don't bother truncating if it doesn't gain - ;; us at least 2 columns. - ((< compare (+ 2 (string-width ellipsis))) most) - (t (concat ellipsis (substring most compare)))) - close-bracket))) - ;;"-prospects" - more than one candidate - (prospects-len (+ (string-width - (or determ (concat open-bracket close-bracket))) - (string-width icomplete-separator) - (+ 2 (string-width ellipsis)) ;; take {…} into account - (string-width - (buffer-substring (save-excursion - (goto-char (icomplete--field-beg)) - (pos-bol)) - (icomplete--field-end))))) - (prospects-max - ;; Max total length to use, including the minibuffer content. - (* (+ icomplete-prospects-height - ;; If the minibuffer content already uses up more than - ;; one line, increase the allowable space accordingly. - (/ prospects-len (window-width))) - (window-width))) - ;; Find the common prefix among `comps'. - ;; We can't use the optimization below because its assumptions - ;; aren't always true, e.g. when completion-cycling (bug#10850): - ;; (if (eq t (compare-strings (car comps) nil (length most) - ;; most nil nil completion-ignore-case)) - ;; ;; Common case. - ;; (length most) - ;; Else, use try-completion. - (prefix (when icomplete-hide-common-prefix - (try-completion "" comps))) - (prefix-len - (and (stringp prefix) - ;; Only hide the prefix if the corresponding info - ;; is already displayed via `most'. - (string-prefix-p prefix most t) - (length prefix))) ;;) - prospects comp limit) - (prog1 - (if (or (eq most-try t) (and (not icomplete-scroll) - (not (consp (cdr comps))))) - (concat determ " [Matched]") - (when (member name comps) - ;; NAME is complete but not unique. This scenario poses - ;; following UI issues: - ;; - ;; - When `icomplete-hide-common-prefix' is non-nil, NAME - ;; is stripped empty. This would make the entry - ;; inconspicuous. - ;; - ;; - Due to sorting of completions, NAME may not be the - ;; first of the prospects and could be hidden deep in - ;; the displayed string. - ;; - ;; - Because of `icomplete-prospects-height' , NAME may - ;; not even be displayed to the user. - ;; - ;; To circumvent all the above problems, provide a visual - ;; cue to the user via an "empty string" in the try - ;; completion field. - (setq determ (concat open-bracket "" close-bracket))) - (while (and comps (not limit)) - (setq comp - (let ((cur (completion-lazy-hilit (car comps)))) - (if prefix-len (substring cur prefix-len) cur)) - comps (cdr comps)) - (setq prospects-len - (+ (string-width comp) - (string-width icomplete-separator) - prospects-len)) - (if (< prospects-len prospects-max) - (push comp prospects) - (setq limit t))) - (setq prospects (nreverse prospects)) - ;; Decorate first of the prospects. - (when prospects - (let ((first (copy-sequence (pop prospects)))) - (put-text-property 0 (length first) - 'face 'icomplete-first-match first) - (push first prospects))) - (concat determ - "{" - (mapconcat #'identity prospects icomplete-separator) - (concat (and limit (concat icomplete-separator ellipsis)) - "}"))) - ;; Restore the base-size info, since completion-all-sorted-completions - ;; is cached. - (if last (setcdr last base-size)))))))) - -(provide 'icomplete) - -;;;_* Local emacs vars. -;;Local variables: -;;allout-layout: (-2 :) -;;End: - -;;; icomplete.el ends here diff --git a/lisp/ido.el b/lisp/ido.el deleted file mode 100644 index 3f1808f88a2..00000000000 --- a/lisp/ido.el +++ /dev/null @@ -1,4933 +0,0 @@ -;;; ido.el --- interactively do things with buffers and files -*- lexical-binding: t -*- - -;; Copyright (C) 1996-2025 Free Software Foundation, Inc. - -;; Author: Kim F. Storm -;; Based on: iswitchb by Stephen Eglen -;; Keywords: extensions convenience - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - - -;;; Commentary: - -;; Ido - interactive do - switches between buffers and opens files and -;; directories with a minimum of keystrokes. It is a superset of -;; iswitchb, the interactive buffer switching package by Stephen Eglen. - -;; Interactive substring matching -;; ------------------------------ -;; -;; As you type in a substring, the list of buffers or files currently -;; matching the substring are displayed as you type. The list is -;; ordered so that the most recent buffers or files visited come at -;; the start of the list. -;; -;; The buffer or file at the start of the list will be the one visited -;; when you press RETURN. By typing more of the substring, the list is -;; narrowed down so that gradually the buffer or file you want will be -;; at the top of the list. Alternatively, you can use C-s and C-r (or -;; the right and left arrow keys) to rotate buffer or file names in the -;; list until the one you want is at the top of the list. -;; -;; Completion is also available so that you can see what is common to -;; all of the matching buffers or files as you type. -;; -;; Example: -;; -;; If I have two buffers called "123456" and "123", with "123456" the -;; most recent, when I use ido-switch-buffer, I first of all get -;; presented with the list of all the buffers -;; -;; Buffer: {123456 | 123} -;; -;; If I then press 2: -;; Buffer: 2[3]{123456 | 123} -;; -;; The list in {...} are the matching buffers, most recent first -;; (buffers visible in the current frame are put at the end of the -;; list by default). At any time I can select the item at the head of -;; the list by pressing RET. I can also put the first element at the -;; end of the list by pressing C-s or [right], or bring the last -;; element to the head of the list by pressing C-r or [left]. -;; -;; The item in [...] indicates what can be added to my input by -;; pressing TAB. In this case, I will get "3" added to my input. - -;; So, I press TAB: -;; Buffer: 23{123456 | 123} -;; -;; At this point, I still have two matching buffers. -;; If I want the first buffer in the list, I simply press RET. If I -;; wanted the second in the list, I could press C-s to move it to the -;; top of the list and then RET to select it. -;; -;; However, if I type 4, I only have one match left: -;; Buffer: 234[123456] -;; -;; Since there is only one matching buffer left, it is given in [] and -;; it is shown in the `ido-only-match' face (ForestGreen). I can now -;; press TAB or RET to go to that buffer. -;; -;; If I want to create a new buffer named "234", I press C-j instead of -;; TAB or RET. -;; -;; If instead, I type "a": -;; Buffer: 234a [No match] -;; There are no matching buffers. If I press RET or TAB, I can be -;; prompted to create a new buffer called "234a". -;; -;; Of course, where this function comes in really useful is when you -;; can specify the buffer using only a few keystrokes. In the above -;; example, the quickest way to get to the "123456" file would be -;; just to type 4 and then RET (assuming there isn't any newer buffer -;; with 4 in its name). - -;; Likewise, if you use C-x C-f (ido-find-file), the list of files and -;; directories in the current directory is provided in the same -;; fashion as the buffers above. The files and directories are -;; normally sorted in alphabetical order, but the most recently -;; visited directory is placed first to speed up navigating to -;; directories that you have visited recently. -;; -;; In addition to scrolling through the list using [right] and [left], -;; you can use [up] and [down] to quickly scroll the list to the next -;; or previous subdirectory. -;; -;; To go down into a subdirectory, and continue the file selection on -;; the files in that directory, simply move the directory to the head -;; of the list and hit RET. -;; -;; To go up to the parent directory, delete any partial file name -;; already specified (e.g. using [backspace]) and hit [backspace]. -;; -;; To go to the root directory (on the current drive), enter two -;; slashes. On MS-DOS or Windows, to select the root of another -;; drive, enter X:/ where X is the drive letter. You can also visit -;; files on other hosts using the ange-ftp notations `/host:' and -;; `/user@host:'. See the variable `ido-slow-ftp-hosts' if you want -;; to inhibit the ido substring matching for ftp access. -;; -;; If for some reason you cannot specify the proper file using -;; ido-find-file, you can press C-f to enter the normal find-file. -;; You can also press C-b to drop into ido-switch-buffer. - -;; See the doc string of ido-switch-buffer and ido-find-file for full -;; keybindings and features. -;; (describe-function 'ido-find-file) - -;; Hidden buffers and files -;; ------------------------ -;; -;; Normally, ido does not include hidden buffers (whose name starts -;; with a space) and hidden files and directories (whose name starts -;; with `.') in the list of possible completions. However, if the -;; substring you enter does not match any of the visible buffers or -;; files, ido will automatically look for completions among the hidden -;; buffers or files. -;; -;; You can toggle display of the hidden buffers and files with C-a. - -;; Additional functionality -;; ------------------------ -;; -;; After C-x b, the buffer at the head of the list can be killed by -;; pressing C-k. If the buffer needs saving, you will be queried -;; before the buffer is killed. -;; -;; Likewise, after C-x C-f, you can delete (i.e. physically remove) -;; the file at the head of the list with C-k. You will always be -;; asked for confirmation before the file is deleted. -;; -;; If you enter C-x b to switch to a buffer visiting a given file, and -;; you find that the file you are after is not in any buffer, you can -;; press C-f to immediately drop into ido-find-file. And you can -;; switch back to buffer selection with C-b. - -;; Prefix matching -;; --------------- -;; -;; The standard way of completion with Unix-shells and Emacs is to insert a -;; PREFIX and then hitting TAB (or another completion key). Cause of this -;; behavior has become second nature to a lot of Emacs users, Ido offers in -;; addition to the default substring-matching-method (look above) also the -;; prefix-matching-method. The kind of matching is the only difference to -;; the description of the substring-matching above. -;; -;; You can toggle prefix matching with C-p. -;; -;; Example: -;; -;; If you have again two Buffers "123456" and "123" then hitting "2" does -;; not match because "2" is not a PREFIX in any of the buffer-names. - -;; Flexible matching -;; ----------------- -;; -;; If you set ido-enable-flex-matching, ido will do a more flexible -;; matching (unless regexp matching is active) to find possible matches -;; among the available buffer or file names if no matches are found using -;; the normal prefix or substring matching. -;; -;; The flexible matching implies that any item which simply contains all -;; of the entered characters in the specified sequence will match. -;; -;; Example: -;; -;; If you have four files "alpha", "beta", "gamma", and "delta", -;; entering "aa" will match "alpha" and "gamma", while "ea" matches -;; "beta" and "delta". If prefix matching is also active, "aa" only -;; matches "alpha", while "ea" does not match any files. - -;; Regexp matching -;; --------------- -;; -;; There is limited provision for regexp matching within ido, -;; enabled through `ido-enable-regexp' (toggle with C-t). -;; This allows you to type `[ch]$' for example and see all file names -;; ending in `c' or `h'. -;; -;; Note: ido-style completion is inhibited when you enable regexp matching. - - -;; Customization -;; ------------- -;; -;; Customize the Ido group to change the Ido functionality. -;; -;; To modify the keybindings, use `define-key' on -;; `ido-common-completion-map' or one of the specialized keymaps: -;; `ido-file-dir-completion-map', `ido-file-completion-map' or -;; `ido-buffer-completion-map'. -;; -;; (with-eval-after-load 'ido -;; (keymap-set ido-common-completion-map "SPC" 'ido-next-match)) - -;; Seeing all the matching buffers or files -;; ---------------------------------------- -;; -;; If you have many matching files, they may not all fit onto one -;; line of the minibuffer. Normally, the minibuffer window will grow -;; to show you more of the matching files (depending on the setting -;; of the variables `resize-mini-windows' and `max-mini-window-height'). -;; If you want ido to behave differently from the default minibuffer -;; resizing behavior, set the variable `ido-max-window-height'. -;; -;; Also, to improve the responsiveness of ido, the maximum number of -;; matching items is limited to 12, but you can increase or removed -;; this limit via the `ido-max-prospects' variable. - -;; To see a full list of all matching buffers in a separate buffer, -;; hit ? or press TAB when there are no further completions to the -;; substring. Repeated TAB presses will scroll you through this -;; separate buffer. - -;; Changing the list of files -;; -------------------------- - -;; By default, the list of current files is most recent first, -;; oldest last, with the exception that the files visible in the -;; current frame are put at the end of the list. A hook exists to -;; allow other functions to order the list. For example, if you add: -;; -;; (add-hook 'ido-make-buffer-list-hook #'ido-summary-buffers-to-end) -;; -;; then all files matching "Summary" are moved to the end of the -;; list. (I find this handy for keeping the INBOX Summary and so on -;; out of the way.) It also moves files matching "output\*$" to the -;; end of the list (these are created by AUCTeX when compiling.) -;; Other functions could be made available which alter the list of -;; matching files (either deleting or rearranging elements.) - -;; Highlighting -;; ------------ - -;; The highlighting of matching items is controlled via ido-use-faces. -;; The faces used are ido-first-match, ido-only-match and -;; ido-subdir. -;; Coloring of the matching item was suggested by -;; Carsten Dominik (dominik@strw.leidenuniv.nl). - -;; Replacement for read-buffer and read-file-name -;; ---------------------------------------------- - -;; ido-read-buffer and ido-read-file-name have been written to be drop -;; in replacements for the normal buffer and file name reading -;; functions `read-buffer' and `read-file-name'. - -;; To use ido for all buffer and file selections in Emacs, customize the -;; variable `ido-everywhere'. - -;; Using ido-like behavior in other Lisp packages -;; ----------------------------------------------- - -;; If you don't want to rely on the `ido-everywhere' functionality, -;; ido-read-buffer, ido-read-file-name, and ido-read-directory-name -;; can be used by other packages to read a buffer name, a file name, -;; or a directory name in the Ido way. - -;;; Acknowledgments - -;; Infinite amounts of gratitude goes to Stephen Eglen -;; who wrote iswitch-buffer mode - from which I ripped off 99% of the code -;; for ido-switch-buffer and found the inspiration for ido-find-file. -;; The ido package would never have existed without his work. - -;; Also thanks to Klaus Berndl, Rohit Namjoshi, Robert Fenk, Alex -;; Schroeder, Bill Benedetto, Stephen Eglen, and many others for bug -;; fixes and improvements. - -;;; History - -;; Since I discovered Stephen Eglen's excellent iswitchb package, I just -;; couldn't live without it, but once being addicted to switching buffers -;; with a minimum of keystrokes, I soon found that opening files in the -;; old-fashioned way was just too slow - so I decided to write a package -;; which could open files with the same speed and ease as iswitchb could -;; switch buffers. - -;; I originally wrote a separate ifindf.el package based on a copy of -;; iswitchb.el, which did for opening files what iswitchb did for -;; switching buffers. Along the way, I corrected a few errors in -;; ifindf which could have found its way back into iswitchb, but since -;; most of the functionality of the two package was practically -;; identical, I decided that the proper thing to do was to merge my -;; ifindf package back into iswitchb. -;; -;; This is basically what ido (interactively do) is all about; but I -;; found it awkward to merge my changes into the "iswitchb-" namespace, -;; so I invented a common "ido-" namespace for the merged packages. -;; -;; This version is based on ido.el version 1.57 released on -;; gnu.emacs.sources adapted for Emacs 22.1 to use command remapping -;; and optionally hooking the read-buffer and read-file-name functions. -;; -;; Prefix matching was added by Klaus Berndl based on -;; an idea of Yuji Minejima and his mcomplete-package. - - -;;; Code: - -(defvar recentf-list) -(require 'seq) - -;;;; Options - -;; These are some things you might want to change. - -(defun ido-fractionp (n) - "Return t if N is a fraction." - (and (numberp n) (> n 0.0) (<= n 1.0))) - -(defgroup ido nil - "Switch between files using substrings." - :group 'extensions - :group 'convenience - :version "22.1" - :link '(emacs-commentary-link :tag "Commentary" "ido.el") - :link '(emacs-library-link :tag "Lisp File" "ido.el") - :link '(custom-manual "(ido) Top") - :link '(info-link "(ido) Customization")) - -;;;###autoload -(defcustom ido-mode nil - "Determines for which buffer/file Ido should be enabled. -The following values are possible: -- `buffer': Turn only on Ido buffer behavior (switching, killing, - displaying...) -- `file': Turn only on Ido file behavior (finding, writing, inserting...) -- `both': Turn on Ido buffer and file behavior. -- nil: Turn off any Ido switching. - -Setting this variable directly does not take effect; -use either \\[customize] or the function `ido-mode'." - :set (lambda (_symbol value) - (ido-mode (or value 0))) - :initialize #'custom-initialize-default - :require 'ido - :link '(emacs-commentary-link "ido.el") - :set-after '(ido-save-directory-list-file - ;; This will clear ido-unc-hosts-cache, so set it - ;; before loading history file. - ido-unc-hosts) - :type '(choice (const :tag "Turn on only buffer" buffer) - (const :tag "Turn on only file" file) - (const :tag "Turn on both buffer and file" both) - (const :tag "Switch off all" nil))) - -(defcustom ido-case-fold case-fold-search - "Non-nil if searching of buffer and file names should ignore case." - :type 'boolean) - -(defcustom ido-ignore-buffers - '("\\` ") - "List of regexps or functions matching buffer names to ignore. -For example, traditional behavior is not to list buffers whose names begin -with a space, for which the regexp is `\\\\=` '. See the source file for -example functions that filter buffer names." - :type '(repeat (choice regexp function))) - -(defcustom ido-ignore-files - '("\\`CVS/" "\\`#" "\\`.#" "\\`\\.\\./" "\\`\\./") - "List of regexps or functions matching file names to ignore. -For example, traditional behavior is not to list files whose names begin -with a #, for which the regexp is `\\\\=`#'. See the source file for -example functions that filter filenames." - :type '(repeat (choice regexp function))) - -(defcustom ido-ignore-extensions t - "Non-nil means ignore files in `completion-ignored-extensions' list." - :type 'boolean) - -(defcustom ido-show-dot-for-dired nil - "Non-nil means to always put . as the first item in file name lists. -This allows the current directory to be opened immediately with `dired'." - :type 'boolean) - -(defcustom ido-file-extensions-order nil - "List of file extensions specifying preferred order of file selections. -Each element is either a string with `.' as the first char, an empty -string matching files without extension, or t which is the default order -for files with an unlisted file extension." - :type '(repeat (choice string - (const :tag "Default order" t)))) - -(defcustom ido-ignore-directories - '("\\`CVS/" "\\`\\.\\./" "\\`\\./") - "List of regexps or functions matching sub-directory names to ignore." - :type '(repeat (choice regexp function))) - -(defcustom ido-ignore-directories-merge nil - "List of regexps or functions matching directory names to ignore during merge. -Directory names matched by one of the regexps in this list are not inserted -in merged file and directory lists." - :type '(repeat (choice regexp function))) - -;; Examples for setting the value of ido-ignore-buffers -;;(defun ido-ignore-c-mode (name) -;; "Ignore all c mode buffers -- example function for ido." -;; (with-current-buffer name -;; (derived-mode-p 'c-mode))) -;; -;;(setq ido-ignore-buffers '("\\` " ido-ignore-c-mode)) - -;; Examples for setting the value of ido-ignore-files -;;(setq ido-ignore-files '("\\` " "\\.c\\'" "\\.h\\'")) - -(defcustom ido-default-file-method 'raise-frame - "How to visit a new file when using `ido-find-file'. -Possible values: -`selected-window' Show new file in selected window -`other-window' Show new file in another window (same frame) -`display' Display file in another window without selecting to it -`other-frame' Show new file in another frame -`maybe-frame' If a file is visible in another frame, prompt to ask if - you want to see the file in the same window of the current - frame or in the other frame -`raise-frame' If a file is visible in another frame, raise that - frame; otherwise, visit the file in the same window" - :type '(choice (const :tag "Visit in selected window" selected-window) - (const :tag "Visit in other window" other-window) - (const :tag "Display (no select) in other window" display) - (const :tag "Visit in other frame" other-frame) - (const :tag "Ask to visit in other frame" maybe-frame) - (const :tag "Raise frame if already visited" raise-frame))) - -(defcustom ido-default-buffer-method 'raise-frame - "How to switch to new buffer when using `ido-switch-buffer'. -See `ido-default-file-method' for details." - :type '(choice (const :tag "Show in selected window" selected-window) - (const :tag "Show in other window" other-window) - (const :tag "Display (no select) in other window" display) - (const :tag "Show in other frame" other-frame) - (const :tag "Ask to show in other frame" maybe-frame) - (const :tag "Raise frame if already shown" raise-frame))) - -(defcustom ido-enable-flex-matching nil - "Non-nil means that Ido will do flexible string matching. -Flexible matching means that if the entered string does not -match any item, any item containing the entered characters -in the given sequence will match." - :type 'boolean) - - -(defcustom ido-enable-regexp nil - "Non-nil means that Ido will do regexp matching. -Value can be toggled within Ido using `ido-toggle-regexp'." - :type 'boolean) - -(defcustom ido-enable-prefix nil - "Non-nil means only match if the entered text is a prefix of file name. -This behavior is like the standard Emacs completion. -If nil, match if the entered text is an arbitrary substring. -Value can be toggled within Ido using `ido-toggle-prefix'." - :type 'boolean) - -(defcustom ido-enable-dot-prefix nil - "Non-nil means to match leading dot as prefix. -I.e. hidden files and buffers will match only if you type a dot -as first char even if `ido-enable-prefix' is nil." - :type 'boolean) - -;; See https://debbugs.gnu.org/2042 for more info. -(defcustom ido-buffer-disable-smart-matches t - "Non-nil means not to re-order matches for buffer switching. -By default, Ido arranges matches in the following order: - - full-matches > suffix matches > prefix matches > remaining matches - -which can get in the way for buffer switching." - :version "24.3" - :type 'boolean) - -(defcustom ido-confirm-unique-completion nil - "Non-nil means that even a unique completion must be confirmed. -This means that \\[ido-complete] must always be followed by \\[ido-exit-minibuffer] -even when there is only one unique completion." - :type 'boolean) - -(defcustom ido-cannot-complete-command #'ido-completion-auto-help - "Command run when `ido-complete' can't complete any more. -The most useful values are `ido-completion-help', which pops up a -window with completion alternatives; `ido-completion-auto-help', -which does the same but respects the value of -`completion-auto-help'; and `ido-next-match' or `ido-prev-match', -which cycle the buffer list." - :version "28.1" - :type 'function) - - -(defcustom ido-record-commands t - "Non-nil means that Ido will record commands in command history. -Note that the non-Ido equivalent command is recorded." - :type 'boolean) - -(defcustom ido-max-prospects 12 - "Upper limit of the prospect list if non-zero. -Zero means no limit for the prospect list. -For a long list of prospects, building the full list for the -minibuffer can take a non-negligible amount of time; setting this -variable reduces that time." - :type 'integer) - -(defcustom ido-max-file-prompt-width 0.35 - "Upper limit of the prompt string. -If value is an integer, it specifies the number of characters of -the string. -If value is a floating point number, it specifies a fraction of -the frame width." - :type '(choice - (integer :tag "Characters" :value 20) - (restricted-sexp :tag "Fraction of frame width" - :value 0.35 - :match-alternatives (ido-fractionp)))) - -(defcustom ido-max-window-height nil - "Non-nil specifies a value to override `max-mini-window-height'." - :type '(choice - (const :tag "Don't override" nil) - (integer :tag "Number of lines" :value 1) - (restricted-sexp - :tag "Fraction of window height" - :value 0.25 - :match-alternatives (ido-fractionp)))) - -(defcustom ido-enable-last-directory-history t - "Non-nil means that Ido will remember latest selected directory names. -See `ido-last-directory-list' and `ido-save-directory-list-file'." - :type 'boolean) - -(defcustom ido-max-work-directory-list 50 - "Maximum number of working directories to record. -This is the list of directories where files have most recently been opened. -See `ido-work-directory-list' and `ido-save-directory-list-file'." - :type 'natnum) - -(defcustom ido-work-directory-list-ignore-regexps nil - "List of regexps matching directories which should not be recorded. -Directory names matched by one of the regexps in this list are not inserted in -the `ido-work-directory-list' list." - :type '(repeat regexp)) - -(defcustom ido-enable-tramp-completion t - "Non-nil means that Ido shall perform tramp method and server name completion. -A tramp file name uses the following syntax: /method:user@host:filename." - :type 'boolean) - -(defcustom ido-record-ftp-work-directories t - "Non-nil means record FTP file names in the work directory list." - :type 'boolean) - -(defcustom ido-merge-ftp-work-directories nil - "If nil, merging ignores FTP file names in the work directory list." - :type 'boolean) - -(defcustom ido-cache-ftp-work-directory-time 1.0 - "Maximum time to cache contents of an FTP directory (in hours). -\\ -Use \\[ido-reread-directory] in prompt to refresh list. -If zero, FTP directories are not cached." - :type 'number) - -(defcustom ido-slow-ftp-hosts nil - "List of slow FTP hosts where Ido prompting should not be used. -If an FTP host is on this list, Ido automatically switches to the non-Ido -equivalent function, e.g. `find-file' rather than `ido-find-file'." - :type '(repeat string)) - -(defcustom ido-slow-ftp-host-regexps nil - "List of regexps matching slow FTP hosts (see `ido-slow-ftp-hosts')." - :type '(repeat regexp)) - -(defvar ido-unc-hosts-cache t - "Cached value from the function `ido-unc-hosts'.") - -(defcustom ido-unc-hosts nil - "List of known UNC host names to complete after initial //. -If value is a function, that function is called to search network for -hosts on first use of UNC path." - :type '(choice (repeat :tag "List of UNC host names" string) - (function-item :tag "Use `NET VIEW'" - :value ido-unc-hosts-net-view) - (function :tag "Your own function")) - :set (lambda (symbol value) - (set symbol value) - (setq ido-unc-hosts-cache t))) - -(defcustom ido-downcase-unc-hosts t - "Non-nil if UNC host names should be downcased." - :type 'boolean) - -(defcustom ido-ignore-unc-host-regexps nil - "List of regexps matching UNC hosts to ignore. -Case is ignored if `ido-downcase-unc-hosts' is set." - :type '(repeat regexp)) - -(defcustom ido-cache-unc-host-shares-time 8.0 - "Maximum time to cache shares of an UNC host (in hours). -\\ -Use \\[ido-reread-directory] in prompt to refresh list. -If zero, UNC host shares are not cached." - :type 'number) - -(defcustom ido-max-work-file-list 10 - "Maximum number of names of recently opened files to record. -This is the list of the file names (sans directory) which have most recently -been opened. See `ido-work-file-list' and `ido-save-directory-list-file'." - :type 'integer) - -(defcustom ido-work-directory-match-only t - "Non-nil means to skip non-matching directories in the directory history. -When some text is already entered at the `ido-find-file' prompt, using -\\[ido-prev-work-directory] or \\[ido-next-work-directory] will skip directories -without any matching entries." - :type 'boolean) - -(defcustom ido-auto-merge-work-directories-length 0 - "Automatically switch to merged work directories during file name input. -The value is number of characters to type before switching to merged mode. -If zero, the switch happens when no matches are found in the current directory. -Automatic merging is disabled if the value is negative." - :type 'integer) - -(defcustom ido-auto-merge-delay-time 0.70 - "Delay in seconds to wait for more input before doing auto merge." - :type 'number) - -(defcustom ido-auto-merge-inhibit-characters-regexp "[][*?~]" - "Regexp matching characters which should inhibit automatic merging. -When a (partial) file name matches this regexp, merging is inhibited." - :type 'regexp) - -(defcustom ido-merged-indicator "^" - "The string appended to first choice if it has multiple directory choices." - :type 'string) - -(defcustom ido-max-dir-file-cache 100 - "Maximum number of working directories to be cached. -\\ -This is the size of the cache of `file-name-all-completions' results. -Each cache entry is time stamped with the modification time of the -directory. Some systems, like Windows, have unreliable directory -modification times, so you may choose to disable caching on such -systems, or explicitly refresh the cache contents using the command -`ido-reread-directory' command (\\[ido-reread-directory]) in the minibuffer. -See also `ido-dir-file-cache' and `ido-save-directory-list-file'." - :type 'integer) - -(defcustom ido-max-directory-size nil - "Maximum size (in bytes) for directories to use Ido completion. -\\ -If you enter a directory with a size larger than this size, Ido will -not provide the normal completion. To show the completions, use \\[ido-toggle-ignore]." - :type '(choice (const :tag "No limit" nil) - (integer :tag "Size in bytes" 30000))) - -(defcustom ido-big-directories nil - "List of directory pattern strings that should be considered big. -Ido won't attempt to list the contents of directories matching -any of these regular expressions when completing file names." - :type '(repeat regexp) - :version "27.1") - -(defcustom ido-rotate-file-list-default nil - "Non-nil means that Ido will always rotate file list to get default in front." - :type 'boolean) - -(defcustom ido-enter-matching-directory 'only - "Additional methods to enter sub-directory of first/only matching item. -If value is `first', enter first matching sub-directory when typing a slash. -If value is `only', typing a slash only enters the sub-directory if it is -the only matching item. -If value is t, automatically enter a sub-directory when it is the only -matching item, even without typing a slash." - :type '(choice (const :tag "Never" nil) - (const :tag "Slash enters first directory" first) - (const :tag "Slash enters first and only directory" only) - (other :tag "Always enter unique directory" t))) - -(defcustom ido-create-new-buffer 'prompt - "Specify whether a new buffer is created if no buffer matches substring. -Choices are `always' to create new buffers unconditionally, `prompt' to -ask user whether to create buffer, or `never' to never create new buffer." - :type '(choice (const always) - (const prompt) - (const never))) - -(defcustom ido-setup-hook nil - "Hook run after the Ido variables and keymap have been setup. -The dynamic variable `ido-cur-item' contains the current type of item that -is read by Ido; possible values are file, dir, buffer, and list. -Additional keys can be defined in `ido-completion-map'." - :type 'hook) - -(defcustom ido-separator nil - "String used by Ido to separate the alternatives in the minibuffer." - :type '(choice string (const nil))) -(make-obsolete-variable 'ido-separator - "set 3rd element of `ido-decorations' instead." nil) - -(defcustom ido-decorations '("{" "}" " | " " | ..." "[" "]" " [No match]" - " [Matched]" " [Not readable]" " [Too big]" " [Confirm]") - "List of strings used by Ido to display the alternatives in the minibuffer. -There are between 11 and 13 elements in this list: -1st and 2nd elements are used as brackets around the prospect list, -3rd element is the separator between prospects (ignored if -`ido-separator' is set), -4th element is the string inserted at the end of a truncated list of prospects, -5th and 6th elements are used as brackets around the common match string which -can be completed using TAB, -7th element is the string displayed when there are no matches, and -8th element is displayed if there is a single match (and faces are not used), -9th element is displayed when the current directory is non-readable, -10th element is displayed when directory exceeds `ido-max-directory-size', -11th element is displayed to confirm creating new file or buffer. -12th and 13th elements (if present) are used as brackets around the sole -remaining completion. If absent, elements 5 and 6 are used instead." - :type '(repeat string)) - -(defcustom ido-use-virtual-buffers nil - "If non-nil, refer to past (\"virtual\") buffers as well as existing ones. -The options are: - nil: Do not use virtual buffers. - t: Always use virtual buffers. - auto: Use virtual buffers if the current input matches no existing buffer. - -Essentially it works as follows: Say you are visiting a file and -the buffer gets cleaned up by midnight.el. Later, you want to -switch to that buffer, but find it's no longer open. With virtual -buffers enabled, the buffer name stays in the buffer list (using -the `ido-virtual' face, and always at the end), and if you select -it, it opens the file back up again. This allows you to think -less about whether recently opened files are still open or not. -Most of the time you can quit Emacs, restart, and then switch to -a file buffer that was previously open as if it still were. - -This feature relies upon the `recentf' package, which will be -enabled if this variable is configured to a non-nil value." - :version "24.1" - :type '(choice (const :tag "Always" t) - (const :tag "Automatic" auto) - (const :tag "Never" nil))) - -(defcustom ido-use-faces t - "Non-nil means use Ido faces to highlighting first match, only match and -subdirs in the alternatives." - :type 'boolean) - -(defface ido-first-match '((t :weight bold)) - "Face used by Ido for highlighting first match.") - -(defface ido-only-match '((((class color)) - :foreground "ForestGreen") - (t :slant italic)) - "Face used by Ido for highlighting only match.") - -(defface ido-subdir '((((min-colors 88) (class color)) - :foreground "red1") - (((class color)) - :foreground "red") - (t :underline t)) - "Face used by Ido for highlighting subdirs in the alternatives.") - -(defface ido-virtual '((t :inherit font-lock-builtin-face)) - "Face used by Ido for matching virtual buffer names." - :version "24.1") - -(defface ido-indicator '((((min-colors 88) (class color)) - :foreground "yellow1" :background "red1" :width condensed) - (((class color)) - :foreground "yellow" :background "red" :width condensed) - (t :inverse-video t)) - "Face used by Ido for highlighting its indicators.") - -(defface ido-incomplete-regexp - '((t :inherit font-lock-warning-face)) - "Ido face for indicating incomplete regexps.") - -(defcustom ido-make-file-list-hook nil - "List of functions to run when the list of matching files is created. -Each function on the list may modify the dynamically bound variable -`ido-temp-list' which contains the current list of matching files." - :type 'hook) - -(defcustom ido-make-dir-list-hook nil - "List of functions to run when the list of matching directories is created. -Each function on the list may modify the dynamically bound variable -`ido-temp-list' which contains the current list of matching directories." - :type 'hook) - -(defcustom ido-make-buffer-list-hook nil - "List of functions to run when the list of matching buffers is created. -Each function on the list may modify the dynamically bound variable -`ido-temp-list' which contains the current list of matching buffer names." - :type 'hook) - -(defcustom ido-rewrite-file-prompt-functions nil - "List of functions to run when the `find-file' prompt is created. -Each function on the list may modify the following dynamically bound -variables: - dirname - the (abbreviated) directory name - to be modified by the hook functions - max-width - the max width of the resulting dirname; nil means no limit - prompt - the basic prompt (e.g. \"Find File: \") - literal - the string shown if doing \"literal\" find; set to nil to omit - vc-off - the string shown if version control is inhibited; use nil to omit - prefix - either nil or a fixed prefix for the dirname - -The following variables are available, but should not be changed: - `ido-current-directory' - the unabbreviated directory name - item - equals `file' or `dir' depending on the current mode." - :type 'hook) - -(defvar ido-rewrite-file-prompt-rules nil - "Alist of rewriting rules for directory names in Ido prompts. -A list of elements of the form (FROM . TO) or (FROM . FUNC), each -meaning to rewrite the directory name if matched by FROM by either -substituting the matched string by TO or calling the function FUNC -with the current directory name as its only argument and using the -return value as the new directory name. In addition, each FUNC may -also modify the dynamic variables described for the variable -`ido-rewrite-file-prompt-functions'.") - -(defcustom ido-completion-buffer "*Ido Completions*" - "Name of completion buffer used by Ido. -Set to nil to disable completion buffers popping up." - :type '(choice (const :tag "Disable popping up completion buffer" nil) - string)) - -(defcustom ido-completion-buffer-all-completions nil - "Non-nil means to show all completions in completion buffer. -Otherwise, only the current list of matches is shown." - :type 'boolean) - -(defcustom ido-all-frames 'visible - "Argument to pass to `walk-windows' when Ido is finding buffers. -See documentation of `walk-windows' for useful values." - :type '(choice (const :tag "Selected frame only" nil) - (const :tag "All existing frames" t) - (const :tag "All visible frames" visible) - (const :tag "All frames on this terminal" 0))) - -(defcustom ido-minibuffer-setup-hook nil - "Ido-specific customization of minibuffer setup. - -This hook is run during minibuffer setup if Ido is active. -It is intended for use in customizing Ido for interoperation -with other packages. For instance: - - (add-hook \\='ido-minibuffer-setup-hook - (lambda () (setq-local max-mini-window-height 3))) - -will constrain Emacs to a maximum minibuffer height of 3 lines when -Ido is running. Copied from `icomplete-minibuffer-setup-hook'." - :type 'hook) - -(defcustom ido-save-directory-list-file - (locate-user-emacs-file "ido.last" ".ido.last") - "File in which the Ido state is saved between invocations. -Variables stored are: `ido-last-directory-list', `ido-work-directory-list', -`ido-work-file-list', and `ido-dir-file-cache'. -Must be set before enabling Ido mode." - :version "24.4" ; added locate-user-emacs-file - :type 'string) - -(defcustom ido-read-file-name-as-directory-commands '() - "List of commands which use `read-file-name' to read a directory name. -When `ido-everywhere' is non-nil, the commands in this list will read -the directory using `ido-read-directory-name'." - :type '(repeat symbol)) - -(defcustom ido-read-file-name-non-ido '() - "List of commands which shall not read file names the Ido way. -When `ido-everywhere' is non-nil, the commands in this list will read -the file name using normal `read-file-name' style." - :type '(repeat symbol)) - -(defcustom ido-before-fallback-functions '() - "List of functions to call before calling a fallback command. -The fallback command is passed as an argument to the functions." - :type 'hook) - -;;;; Keymaps - -(defvar-keymap ido-common-completion-map - :doc "Keymap for all Ido commands." - :parent minibuffer-local-map - "C-a" #'ido-toggle-ignore - "C-c" #'ido-toggle-case - "C-e" #'ido-edit-input - "TAB" #'ido-complete - "SPC" #'ido-complete-space - "C-j" #'ido-select-text - "C-m" #'ido-exit-minibuffer - "C-p" #'ido-toggle-prefix - "C-r" #'ido-prev-match - "C-s" #'ido-next-match - "C-." #'ido-next-match - "C-," #'ido-prev-match - "C-t" #'ido-toggle-regexp - "C-z" #'ido-undo-merge-work-directory - "C-SPC" #'ido-restrict-to-matches - "M-SPC" #'ido-take-first-match - "C-@" #'ido-restrict-to-matches - "" #'ido-next-match - "" #'ido-prev-match - "?" #'ido-completion-help - "C-b" #'ido-magic-backward-char - "C-f" #'ido-magic-forward-char - "C-d" #'ido-magic-delete-char) - -(defvar-keymap ido-file-dir-completion-map - :doc "Keymap for Ido file and directory commands." - :parent ido-common-completion-map - "C-x C-b" #'ido-enter-switch-buffer - "C-x C-f" #'ido-fallback-command - "C-x C-d" #'ido-enter-dired - "" #'ido-next-match-dir - "" #'ido-prev-match-dir - "M-" #'ido-prev-work-directory - "M-" #'ido-next-work-directory - "" #'ido-delete-backward-updir - "DEL" #'ido-delete-backward-updir - " " #'ido-delete-backward-updir - " " #'ido-delete-backward-word-updir - "C-" #'ido-up-directory - "C-l" #'ido-reread-directory - "M-d" #'ido-wide-find-dir-or-delete-dir - "M-b" #'ido-push-dir - "M-v" #'ido-push-dir-first - "M-f" #'ido-wide-find-file-or-pop-dir - "M-k" #'ido-forget-work-directory - "M-m" #'ido-make-directory - "M-n" #'ido-next-work-directory - "M-o" #'ido-prev-work-file - "C-M-o" #'ido-next-work-file - "M-p" #'ido-prev-work-directory - "M-s" #'ido-merge-work-directories) - -(defvar-keymap ido-file-completion-map - :doc "Keymap for Ido file commands." - :parent ido-file-dir-completion-map - "C-o" #'ido-copy-current-word - "C-w" #'ido-copy-current-file-name - "M-l" #'ido-toggle-literal) - -(defvar-keymap ido-buffer-completion-map - :doc "Keymap for Ido buffer commands." - :parent ido-common-completion-map - "C-x C-f" #'ido-enter-find-file - "C-x C-b" #'ido-fallback-command - "C-k" #'ido-kill-buffer-at-head - "C-S-b" #'ido-bury-buffer-at-head - "C-o" #'ido-toggle-virtual-buffers) - -;;;; Persistent variables - -(defvar ido-file-history nil - "History of files selected using `ido-find-file'.") - -(defvar ido-buffer-history nil - "History of buffers selected using `ido-switch-buffer'.") - -(defvar ido-last-directory-list nil - "List of last selected directory names. -See `ido-enable-last-directory-history' for details.") - -(defvar ido-work-directory-list nil - "List of actual working directory names. -The current directory is inserted at the front of this list whenever a -file is opened with `ido-find-file' and family.") - -(defvar ido-work-file-list nil - "List of actual work file names. -Opening a file with `ido-find-file' and similar functions -inserts the current file name (relative to its containing directory) -at the front of this list.") - -(defvar ido-dir-file-cache nil - "List of `file-name-all-completions' results. -Each element in the list is of the form (DIR (MTIME) FILE...).") - -(defvar ido-ignore-item-temp-list nil - "List of items to ignore in current Ido invocation. -Intended to be let-bound by functions which call Ido repeatedly. -Should never be set permanently.") - -;;;; Temporary storage - -(defvar ido-completion-map nil - "Currently active keymap for Ido commands.") - -(defvar-local ido-eoinput 1 - "Point where minibuffer input ends and completion info begins. -Copied from `icomplete-eoinput'.") - -(defvar ido-common-match-string nil - "Stores the string that is common to all matching files.") - -(defvar ido-rescan nil - "Non-nil means we need to regenerate the list of matching items.") - -(defvar ido-rotate nil - "Non-nil means we are rotating list of matches.") - -(defvar ido-text nil - "Stores the user's string as it is typed in.") - -(defvar ido-text-init nil - "The initial string for the user's string it is typed in.") - -(defvar ido-input-stack nil - "Stores the user's strings when user hits M-b/M-f.") - -(defvar ido-matches nil - "List of files currently matching `ido-text'.") - -(defvar ido-report-no-match t - "Report \"[No Match]\" when no completions matches `ido-text'.") - -(defvar ido-exit nil - "Flag to monitor how `ido-find-file' exits. -If equal to `takeprompt', we use the prompt as the file name to be -selected.") - -(defvar ido-current-directory nil - "Current directory for `ido-find-file'.") - -(defvar ido-predicate nil - "Current completion predicate.") - -(defvar ido-auto-merge-timer nil - "Delay timer for auto merge.") - -(defvar ido-use-mycompletion-depth 0 - "Non-nil means use Ido completion feedback. -Is set by Ido functions to the current `minibuffer-depth', -so that it doesn't interfere with other minibuffer usage.") - -(defvar ido-incomplete-regexp nil - "Non-nil if an incomplete regexp is entered.") - -(defvar ido-initial-position nil - "Non-nil means to explicitly cursor on entry to minibuffer. -Value is an integer which is number of chars to right of prompt.") - -(defvar ido-virtual-buffers nil - "List of virtual buffers, that is, past visited files. -This is a copy of `recentf-list', pared down and with faces applied. -Only used if `ido-use-virtual-buffers' is non-nil.") - -;;;; Variables with dynamic bindings. - -;; These are declared here to keep the byte compiler quiet. - -;; Stores the current ido item type ('file, 'dir, 'buffer, or 'list). -(defvar ido-cur-item) - -;; Stores the current default item. -(defvar ido-default-item) - -;; Stores the current list of items that will be searched through. -;; The list is ordered, so that the most interesting item comes first, -;; although by default, the files visible in the current frame are put -;; at the end of the list. Created by `ido-make-item-list'. -(defvar ido-cur-list) - -;; Stores the choice list for ido-completing-read -(defvar ido-choice-list) - -;; Stores the list of items which are ignored when building -;; `ido-cur-list'. It is in no specific order. -(defvar ido-ignored-list) - -;; Remember if current directory is non-readable (so we cannot do completion). -(defvar ido-directory-nonreadable) - -;; Remember if current directory is 'huge' (so we don't want to do completion). -(defvar ido-directory-too-big) - -;; Keep current item list if non-nil. -(defvar ido-keep-item-list) - -;; Process ido-ignore-* lists. -(defvar ido-process-ignore-lists) - -;; Don't process ido-ignore- lists once. -(defvar ido-process-ignore-lists-inhibit) - -;; Is ido using virtual buffers? -(defvar ido-enable-virtual-buffers) - -;; Buffer from which ido was entered. -(defvar ido-entry-buffer) - -;; Non-nil if matching file must be selected. -(defvar ido-require-match) - -;; Non-nil if we should add [confirm] to prompt -(defvar ido-show-confirm-message) - -;; Stores a temporary version of the file list being created. -(defvar ido-temp-list) - -;; Non-nil if default list element should be rotated into place. -(defvar ido-rotate-temp) - -;; Stores current index in ido-work-directory-list. -(defvar ido-work-directory-index) - -;; Stores current index in ido-work-file-list. -(defvar ido-work-file-index) - -;; Set when merged work directory list is in use. -(defvar ido-use-merged-list) - -;; Set when merged work directory list not yet built. -(defvar ido-try-merged-list) - -;; Saved state prior to last work directory merge. -;; Value is a list (ido-text dir cur-list ignored-list matches). -(defvar ido-pre-merge-state) - -;; Original value of vc-handled-backends for use in ido-toggle-vc. -(defvar ido-saved-vc-hb) - -;; Stores temporary state of literal find file. -(defvar ido-find-literal) - -;; Set to 'ignore to inhibit switching between find-file/switch-buffer. -(defvar ido-context-switch-command) - -;; Dynamically bound in ido-read-internal. -(defvar ido-completing-read) - -;; If dynamically set when ido-exit is 'fallback, overrides fallback command. -(defvar ido-fallback nil) - -;;; FUNCTIONS - -(defun ido-active (&optional merge) - (if merge - ido-use-merged-list - (and (boundp 'ido-completing-read) - (= ido-use-mycompletion-depth (minibuffer-depth))))) - -(defvar ido-trace-enable nil) - -(defun ido-trace (p &optional s retval) - (if ido-trace-enable - (let ((b (get-buffer-create " *IDO Trace*")) - (deactivate-mark deactivate-mark)) - (save-excursion - (save-restriction - (set-buffer b) - (insert p ": " (if (stringp s) s (format "%S" s)) "\n"))))) - retval) - -(defun ido-toggle-trace (arg) - (interactive "P") - (setq ido-trace-enable (or arg (not ido-trace-enable))) - (if ido-trace-enable - (message "IDO trace on")) - (let ((b (get-buffer " *IDO Trace*"))) - (if b - (if ido-trace-enable - (kill-buffer b) - (pop-to-buffer b t t) - (setq truncate-lines t))))) - -(defun ido-local-file-exists-p (file) - "Tell if FILE exists locally." - (let (file-name-handler-alist) - (file-exists-p file))) - -(defun ido-unc-hosts (&optional query) - "Return list of UNC host names." - (let ((hosts - (cond - ((listp ido-unc-hosts) - ido-unc-hosts) ;; static list or nil - ((listp ido-unc-hosts-cache) - ido-unc-hosts-cache) ;; result of net search - ((and query (fboundp ido-unc-hosts)) - (message (propertize "Searching for UNC hosts..." 'face 'highlight)) - (setq ido-unc-hosts-cache (funcall ido-unc-hosts)) - (message nil) - ido-unc-hosts-cache) - (query - (setq ido-unc-hosts-cache nil)) - (t (fboundp ido-unc-hosts))))) - (when query - (let ((case-fold-search ido-downcase-unc-hosts) - res host re-list re) - (while hosts - (setq host (car hosts) - hosts (cdr hosts) - re-list (and ido-process-ignore-lists - ido-ignore-unc-host-regexps)) - (while re-list - (setq re (car re-list) - re-list (cdr re-list)) - (if (string-match re host) - (setq re-list nil - host nil))) - (when host - (when ido-downcase-unc-hosts - (setq host (downcase host))) - (setq res (cons host res)))) - (setq hosts (sort res #'string<)))) - hosts)) - -(defun ido-unc-hosts-net-view () - "Query network for list of UNC host names using `NET VIEW'." - (let (hosts) - (with-temp-buffer - (shell-command "net view" t) - (goto-char (point-min)) - (while (re-search-forward "^\\\\\\\\\\([[:graph:]]+\\)" nil t) - (setq hosts (cons (match-string 1) hosts)))) - hosts)) - -(defun ido-is-tramp-root (&optional dir) - (and ido-enable-tramp-completion - (string-match "\\`/[^/]+[@:]\\'" - (or dir ido-current-directory)))) - -(defun ido-is-unc-root (&optional dir) - (and (ido-unc-hosts) - (string-equal "//" - (or dir ido-current-directory)))) - -(defun ido-is-unc-host (&optional dir) - (and (ido-unc-hosts) - (string-match "\\`//[^/]+/\\'" - (or dir ido-current-directory)))) - -(defun ido-is-root-directory (&optional dir) - (setq dir (or dir ido-current-directory)) - (or - (string-equal "/" dir) - (and (memq system-type '(windows-nt ms-dos)) - (string-match "\\`[a-zA-Z]:[/\\]\\'" dir)) - (if ido-enable-tramp-completion - (ido-is-tramp-root dir) - (string-match "\\`/[^:/][^:/]+:\\'" dir)))) - -(defun ido-is-ftp-directory (&optional dir) - (string-match - (if ido-enable-tramp-completion - ;; like tramp-file-name-regexp-unified, but doesn't match single drive letters - "\\`/[^/:][^/:]+:" - "\\`/[^/:][^/:]+:/") - (or dir ido-current-directory))) - -(defun ido-is-slow-ftp-host (&optional dir) - (and (or ido-slow-ftp-hosts ido-slow-ftp-host-regexps) - (setq dir (or dir ido-current-directory)) - ;; (featurep 'ange-ftp) - ;; (ange-ftp-ftp-name dir) - (string-match - (if ido-enable-tramp-completion - "\\`/\\([^/]+[@:]\\)*\\([^@/:][^@/:]+\\):" - "\\`/\\([^/:]*@\\)?\\([^@/:][^@/:]+\\):/") - dir) - (let ((host (substring dir (match-beginning 2) (match-end 2)))) - (or (member host ido-slow-ftp-hosts) - (let ((re ido-slow-ftp-host-regexps)) - (while (and re (not (string-match (car re) host))) - (setq re (cdr re))) - re))))) - -(defun ido-time-stamp (&optional time) - ;; Time is a floating point number (fractions of 1 hour) - (/ (float-time time) 3600)) - -(defun ido-cache-ftp-valid (&optional time) - (and (numberp ido-cache-ftp-work-directory-time) - (> ido-cache-ftp-work-directory-time 0) - (or (not time) - (< (- (ido-time-stamp) time) ido-cache-ftp-work-directory-time)))) - -(defun ido-cache-unc-valid (&optional time) - (and (numberp ido-cache-unc-host-shares-time) - (> ido-cache-unc-host-shares-time 0) - (or (not time) - (< (- (ido-time-stamp) time) ido-cache-unc-host-shares-time)))) - -(defun ido-may-cache-directory (&optional dir) - (setq dir (or dir ido-current-directory)) - (cond - ((and (ido-is-root-directory dir) - (or ido-enable-tramp-completion - (memq system-type '(windows-nt ms-dos)))) - nil) - ((ido-is-unc-host dir) - (ido-cache-unc-valid)) - ((ido-is-ftp-directory dir) - (ido-cache-ftp-valid)) - ((ido-directory-too-big-p dir) - nil) - (t t))) - -(defun ido-pp (list &optional sep) - (let ((print-level nil) (eval-expression-print-level nil) - (print-length nil) (eval-expression-print-length nil)) - (insert "\n;; ----- " (symbol-name list) " -----\n(\n ") - (setq list (symbol-value list)) - (while list - (let* ((elt (car list)) - (s (if (consp elt) (car elt) elt))) - (if (and (stringp s) (= (length s) 0)) - (setq s nil)) - (if s - (prin1 elt (current-buffer))) - (if (and (setq list (cdr list)) s) - (insert (or sep "\n "))))) - (insert "\n)\n"))) - -(defun ido-save-history () - "Save Ido history and cache information between sessions." - (interactive) - (when (and ido-last-directory-list ido-save-directory-list-file) - (let ((buf (get-buffer-create " *ido session*")) - (version-control 'never)) - (unwind-protect - (with-current-buffer buf - (erase-buffer) - (insert ";;; -*- coding: utf-8 -*-\n") - (setq buffer-file-coding-system 'utf-8) - (ido-pp 'ido-last-directory-list) - (ido-pp 'ido-work-directory-list) - (ido-pp 'ido-work-file-list) - (ido-pp 'ido-dir-file-cache "\n\n ") - (if (listp ido-unc-hosts-cache) - (ido-pp 'ido-unc-hosts-cache) - (insert "\n;; ----- ido-unc-hosts-cache -----\nt\n")) - (write-file ido-save-directory-list-file nil)) - (kill-buffer buf))))) - -(defun ido-load-history (&optional arg) - "Load Ido history and cache information from previous session. -With prefix argument, reload history unconditionally." - (interactive "P") - (if (or arg (and ido-save-directory-list-file (not ido-last-directory-list))) - (let ((file (expand-file-name ido-save-directory-list-file)) - buf) - (when (file-readable-p file) - (setq buf (get-buffer-create " *ido session*")) - (unwind-protect - (with-current-buffer buf - (erase-buffer) - (insert-file-contents file) - (condition-case nil - (setq ido-last-directory-list (read (current-buffer)) - ido-work-directory-list (read (current-buffer)) - ido-work-file-list (read (current-buffer)) - ido-dir-file-cache (read (current-buffer)) - ido-unc-hosts-cache (read (current-buffer))) - (error nil))) - (kill-buffer buf))))) - (ido-wash-history)) - -(defun ido-wash-history () - "Clean-up Ido history and cache information. -Removes badly formatted data and ignored directories." - (interactive) - ;; Check format of each of our lists, discard bogus elements - (setq ido-last-directory-list - (and (listp ido-last-directory-list) - (let ((l ido-last-directory-list) r) - (while l - (if (and (consp (car l)) - (stringp (car (car l))) - (stringp (cdr (car l)))) - (setq r (cons (car l) r))) - (setq l (cdr l))) - (nreverse r)))) - (setq ido-work-directory-list - (and (listp ido-work-directory-list) - (let ((l ido-work-directory-list) r) - (while l - (if (and (stringp (car l)) - (or ido-record-ftp-work-directories - (not (ido-is-ftp-directory (car l))))) - (setq r (cons (car l) r))) - (setq l (cdr l))) - (nreverse r)))) - (setq ido-work-file-list - (and (listp ido-work-file-list) - (let ((l ido-work-file-list) r) - (while l - (if (stringp (car l)) - (setq r (cons (car l) r))) - (setq l (cdr l))) - (nreverse r)))) - (setq ido-dir-file-cache - (and (listp ido-dir-file-cache) - (let ((l ido-dir-file-cache) r) - (while l - (if (and (listp (car l)) - (> (length (car l)) 2) - (let ((dir (car (car l))) - (time (car (cdr (car l)))) - (files (cdr (cdr (car l))))) - (and - (stringp dir) - (if (condition-case nil - (not (time-equal-p time 0)) - (error)) - (ido-may-cache-directory dir) - (and - (consp time) - (numberp (cdr time)) - (cond - ((eq (car time) 'ftp) - (and (ido-is-ftp-directory dir) - (ido-cache-ftp-valid (cdr time)))) - ((eq (car time) 'unc) - (and (ido-is-unc-host dir) - (ido-cache-unc-valid (cdr time))))))) - (let ((s files) (ok t)) - (while s - (if (stringp (car s)) - (setq s (cdr s)) - (setq s nil ok nil))) - ok)))) - (setq r (cons (car l) r))) - (setq l (cdr l))) - (nreverse r)))) - - ;; Remove ignored directories from work directory list - ;; according to ido-work-directory-list-ignore-regexps - (if ido-work-directory-list - (let ((dirs (reverse ido-work-directory-list))) - (setq ido-work-directory-list nil) - (while dirs - (ido-record-work-directory (car dirs)) - (setq dirs (cdr dirs))))) - ;; Get rid of text properties - (let ((l ido-last-directory-list) e) - (while l - (setq e (car l) l (cdr l)) - (set-text-properties 0 (length (car e)) nil (car e)) - (set-text-properties 0 (length (cdr e)) nil (cdr e)))) - (let ((l ido-work-directory-list) e) - (while l - (setq e (car l) l (cdr l)) - (set-text-properties 0 (length e) nil e))) - (let ((l ido-work-file-list) e) - (while l - (setq e (car l) l (cdr l)) - (set-text-properties 0 (length e) nil e))) - (let ((l ido-dir-file-cache) e d) - (while l - (setq e (car l) l (cdr l)) - (if (listp e) - (while e - (setq d (car e) e (cdr e)) - (if (not (consp d)) - (set-text-properties 0 (length d) nil d))))))) - - -(defun ido-kill-emacs-hook () - ;; ido kill emacs hook - (ido-save-history)) - -(defun ido-common-initialization () - (add-hook 'minibuffer-setup-hook #'ido-minibuffer-setup) - (add-hook 'choose-completion-string-functions #'ido-choose-completion-string)) - -(define-minor-mode ido-everywhere - "Toggle use of Ido for all buffer/file reading." - :global t - (remove-function read-file-name-function #'ido-read-file-name) - (remove-function read-buffer-function #'ido-read-buffer) - (when ido-everywhere - (if (not ido-mode) - (ido-mode 'both) - (add-function :override read-file-name-function #'ido-read-file-name) - (add-function :override read-buffer-function #'ido-read-buffer)))) - -(defvar ido-minor-mode-map-entry nil) - -;;;###autoload -(defun ido-mode (&optional arg) - "Toggle Ido mode on or off. -With ARG, turn Ido mode on if arg is positive, off otherwise. -Turning on Ido mode will remap (via a minor-mode keymap) the default -keybindings for the `find-file' and `switch-to-buffer' families of -commands to the Ido versions of these functions. -However, if ARG arg equals `files', remap only commands for files, or -if it equals `buffers', remap only commands for buffer switching. -This function also adds a hook to the minibuffer." - (interactive "P") - (setq ido-mode - (cond - ((null arg) (if ido-mode nil 'both)) - ((eq arg t) 'both) - ((eq arg 'files) 'file) - ((eq arg 'buffers) 'buffer) - ((memq arg '(file buffer both)) arg) - ((> (prefix-numeric-value arg) 0) 'both) - (t nil))) - - (ido-everywhere (if (and ido-mode ido-everywhere) 1 -1)) - - (when ido-mode - (ido-common-initialization) - (ido-load-history) - - (add-hook 'kill-emacs-hook #'ido-kill-emacs-hook) - - (let ((map (make-sparse-keymap))) - (when (memq ido-mode '(file both)) - (define-key map [remap find-file] 'ido-find-file) - (define-key map [remap find-file-read-only] 'ido-find-file-read-only) - (define-key map [remap find-alternate-file] 'ido-find-alternate-file) - (define-key map [remap write-file] 'ido-write-file) - (define-key map [remap insert-file] 'ido-insert-file) - (define-key map [remap list-directory] 'ido-list-directory) - (define-key map [remap dired] 'ido-dired) - (define-key map [remap find-file-other-window] - 'ido-find-file-other-window) - (define-key map [remap find-file-read-only-other-window] - 'ido-find-file-read-only-other-window) - (define-key map [remap find-alternate-file-other-window] - #'ido-find-alternate-file-other-window) - (define-key map [remap dired-other-window] #'ido-dired-other-window) - (define-key map [remap find-file-other-frame] - 'ido-find-file-other-frame) - (define-key map [remap find-file-read-only-other-frame] - 'ido-find-file-read-only-other-frame) - (define-key map [remap dired-other-frame] #'ido-dired-other-frame)) - - (when (memq ido-mode '(buffer both)) - (define-key map [remap switch-to-buffer] 'ido-switch-buffer) - (define-key map [remap switch-to-buffer-other-window] - 'ido-switch-buffer-other-window) - (define-key map [remap switch-to-buffer-other-frame] - 'ido-switch-buffer-other-frame) - (define-key map [remap insert-buffer] 'ido-insert-buffer) - (define-key map [remap kill-buffer] 'ido-kill-buffer) - (define-key map [remap display-buffer] 'ido-display-buffer) - (define-key map [remap display-buffer-other-frame] - #'ido-display-buffer-other-frame)) - - (if ido-minor-mode-map-entry - (setcdr ido-minor-mode-map-entry map) - (setq ido-minor-mode-map-entry (cons 'ido-mode map)) - (add-to-list 'minor-mode-map-alist ido-minor-mode-map-entry)))) - - (when (called-interactively-p 'any) - (message "Ido mode %s" (if ido-mode "enabled" "disabled")))) - - -;;; IDO KEYMAP - -(defalias 'ido-init-completion-maps 'ignore "") -(make-obsolete 'ido-init-completion-maps "it does nothing." "25.1") - -(defun ido-setup-completion-map () - "Set up the completion keymap used by Ido. - -Create a keymap, bind `ido-completion-map' to it, and depending -on what is being completed (`ido-cur-item') set its parent keymap -to one of: - - `ido-common-completion-map' - `ido-file-dir-completion-map' - `ido-file-completion-map' - `ido-buffer-completion-map' - -If option `ido-context-switch-command' is non-nil or `viper-mode' -is enabled then some keybindings are changed in the keymap." - ;; generated every time so that it can inherit new functions. - (let ((map (make-sparse-keymap)) - (viper-p (if (boundp 'viper-mode) viper-mode))) - (when viper-p - (define-key map [remap viper-intercept-ESC-key] 'ignore)) - (pcase ido-cur-item - ((or 'file 'dir) - (when ido-context-switch-command - (define-key map "\C-x\C-b" ido-context-switch-command) - (define-key map "\C-x\C-d" 'ignore)) - (when viper-p - (define-key map [remap viper-backward-char] - 'ido-delete-backward-updir) - (define-key map [remap viper-del-backward-char-in-insert] - 'ido-delete-backward-updir) - (define-key map [remap viper-delete-backward-word] - 'ido-delete-backward-word-updir)) - (set-keymap-parent map - (if (eq ido-cur-item 'file) - ido-file-completion-map - ido-file-dir-completion-map))) - ('buffer - (when ido-context-switch-command - (define-key map "\C-x\C-f" ido-context-switch-command)) - (set-keymap-parent map ido-buffer-completion-map)) - (_ - (set-keymap-parent map ido-common-completion-map))) - (setq ido-completion-map map))) - -(defun ido-final-slash (dir &optional fix-it) - ;; return DIR if DIR has final slash. - ;; else if FIX-IT is non-nil, return DIR/ - ;; else return nil. - (setq dir (ido-name dir)) - (cond - ((string-match "/\\'" dir) dir) - ((ido-is-tramp-root dir) dir) - (fix-it (concat dir "/")) - (t nil))) - -(defun ido-no-final-slash (s) - ;; Remove optional final slash from string S - (let ((l (1- (length s)))) - (if (and (> l 0) (eq (aref s l) ?/)) - (substring s 0 l) - s))) - -(defun ido-nonreadable-directory-p (dir) - ;; Return t if dir is a directory, but not readable - ;; Do not check for non-readable directories via tramp, as this causes a premature - ;; connect on incomplete tramp paths (after entering just method:). - (let ((ido-enable-tramp-completion nil)) - (and (ido-final-slash dir) - (not (ido-is-unc-host dir)) - (file-directory-p dir) - (not (file-readable-p dir))))) - -(defun ido-directory-too-big-p (dir) - ;; Return t if dir is a directory, but too big to show - ;; Do not check for non-readable directories via tramp, as this causes a premature - ;; connect on incomplete tramp paths (after entering just method:). - (let ((ido-enable-tramp-completion nil) - (case-fold-search nil)) - (or (seq-some (lambda (regexp) (string-match-p regexp dir)) - ido-big-directories) - (and (numberp ido-max-directory-size) - (ido-final-slash dir) - (not (ido-is-unc-host dir)) - (file-directory-p dir) - (> (file-attribute-size (file-attributes (file-truename dir))) - ido-max-directory-size))))) - -(defun ido-set-current-directory (dir &optional subdir no-merge) - ;; Set ido's current directory to DIR or DIR/SUBDIR - (unless (and ido-enable-tramp-completion - (string-match "\\`/[^/]*@\\'" dir)) - (setq dir (ido-final-slash dir t))) - (setq ido-use-merged-list nil - ido-try-merged-list (not no-merge)) - (when subdir - (setq dir (concat dir subdir)) - (unless (and ido-enable-tramp-completion - (string-match "\\`/[^/]*@\\'" dir)) - (setq dir (ido-final-slash dir t)))) - (and ido-completion-buffer - (get-buffer ido-completion-buffer) - (kill-buffer ido-completion-buffer)) - (cond - ((equal dir ido-current-directory) - nil) - ((ido-is-unc-root dir) - (ido-trace "unc" dir) - (setq ido-current-directory dir) - (setq ido-directory-nonreadable nil) - (setq ido-directory-too-big nil) - t) - (t - (ido-trace "cd" dir) - (setq ido-current-directory dir) - (and ido-completion-buffer - (get-buffer ido-completion-buffer) - (kill-buffer ido-completion-buffer)) - (setq ido-directory-nonreadable (ido-nonreadable-directory-p dir)) - (setq ido-directory-too-big (and (not ido-directory-nonreadable) - (ido-directory-too-big-p dir))) - t))) - -(defun ido-set-current-home (&optional dir) - ;; Set ido's current directory to user's home directory - (ido-set-current-directory (expand-file-name (or dir "~/")))) - -(defun ido-record-command (command arg) - "Add (COMMAND ARG) to `command-history' if `ido-record-commands' is non-nil." - (when ido-record-commands - (add-to-history 'command-history (list command arg)))) - -(defun ido-make-prompt (item prompt) - ;; Make the prompt for ido-read-internal - (cond - ((and (memq item '(file dir)) ido-current-directory) - (let ((dirname (abbreviate-file-name ido-current-directory)) - (max-width (if (and ido-max-file-prompt-width (floatp ido-max-file-prompt-width)) - (floor (* (frame-width) ido-max-file-prompt-width)) - ido-max-file-prompt-width)) - (literal (and (boundp 'ido-find-literal) ido-find-literal "(literal) ")) - (vc-off (and ido-saved-vc-hb (not vc-handled-backends) "[-VC] ")) - ;; (prefix nil) - (rule ido-rewrite-file-prompt-rules)) - (let ((case-fold-search nil)) - (while rule - (if (and (consp (car rule)) - (string-match (car (car rule)) dirname)) - (setq dirname - (if (stringp (cdr (car rule))) - (replace-match (cdr (car rule)) t nil dirname) - (funcall (cdr (car rule)) dirname)))) - (setq rule (cdr rule)))) - (run-hooks 'ido-rewrite-file-prompt-functions) - (concat prompt - ; (if ido-process-ignore-lists "" "&") - (or literal "") - (or vc-off "") - ;; (or prefix "") - (let ((l (length dirname))) - (if (and max-width (> max-width 0) (> l max-width)) - (let* ((s (substring dirname (- max-width))) - (i (string-search "/" s))) - (concat "..." (if i (substring s i) s))) - dirname))))) - (t prompt))) - -;; Here is very briefly how ido-find-file works: -;; -;; (ido-find-file) -;; (ido-file-internal method) -;; set ido-current-directory -;; (ido-read-internal 'file ...) -;; (while ... -;; (ido-make-item-list ...) -;; (ido-set-matches) -;; (completing-read ... ido-text-init ...) -;; -;; ... here user is allowed to type characters and commands -;; a command may set ido-exit and call (exit-minibuffer) -;; to make ido-read-internal do advanced tasks (or return) -;; -;; ... ido-tidy and ido-exhibit are pre- and post-hooks -;; which are run before and after each user command. -;; -;; return value from completing-read is stored in ido-final-text -;; - ido-exit may cause further actions to be taken: -;; 'refresh - repeat loop (make-item-list, set-matches) -;; 'edit - edit the prompt string, then repeat loop -;; 'keep - repeat loop but don't (re)make-item-list -;; 'updir - go up one directory, repeat loop -;; else set ido-selected based on ido-final-text, -;; optionally update ido-current-directory and repeat loop, or -;; exit with the return value of ido-selected (file name) -;; selected file name is returned from ido-read-internal, -;; ido-exit and method determines what action is taken -;; e.g. the file name may be ignored or joined with ido-current-directory, and -;; the relevant function is called (find-file, write-file, etc). - -(defun ido-read-internal (item prompt hist &optional default require-match initial) - "Perform the `ido-read-buffer' and `ido-read-file-name' functions. -Return the name of a buffer or file selected. -PROMPT is the prompt to give to the user. -DEFAULT if given is the default item to start with. -If REQUIRE-MATCH is non-nil, an existing file must be selected. -If INITIAL is non-nil, it specifies the initial input string." - (let - ((ido-cur-item item) - (ido-entry-buffer (current-buffer)) - (ido-process-ignore-lists t) - (ido-process-ignore-lists-inhibit nil) - (ido-set-default-item t) - ido-default-item - ido-selected - ido-final-text - (done nil) - (icomplete-mode nil) ;; prevent icomplete starting up - ;; Exported dynamic variables: - ido-cur-list - ido-ignored-list - (ido-rotate-temp nil) - (ido-keep-item-list nil) - (ido-use-merged-list nil) - (ido-try-merged-list t) - (ido-pre-merge-state nil) - (ido-case-fold ido-case-fold) - (ido-enable-prefix ido-enable-prefix) - (ido-enable-regexp ido-enable-regexp) - (ido-show-confirm-message nil) - ) - - (ido-setup-completion-map) - - (setq ido-text-init - (if (consp initial) - (cons (car initial) - ;; `completing-read' uses 0-based index while - ;; `read-from-minibuffer' uses 1-based index. - (1+ (cdr initial))) - initial)) - (setq ido-input-stack nil) - - (run-hooks 'ido-setup-hook) - - (while (not done) - (ido-trace "\n_LOOP_" ido-text-init) - (setq ido-exit nil) - (setq ido-rescan t) - (setq ido-rotate nil) - (setq ido-text "") - (when ido-set-default-item - (setq ido-default-item - (cond - ((eq item 'buffer) - (if (bufferp default) (buffer-name default) default)) - ((stringp default) - (if (memq item '(file dir)) - (file-name-nondirectory default) - default)) - ((eq item 'file) - (and ido-enable-last-directory-history - (let ((d (assoc ido-current-directory ido-last-directory-list))) - (and d (cdr d))))))) - (if (member ido-default-item ido-ignore-item-temp-list) - (setq ido-default-item nil)) - (ido-trace "new default" ido-default-item) - (if ido-default-item - (setq ido-initial-position 0)) - (setq ido-set-default-item nil)) - - (if ido-process-ignore-lists-inhibit - (setq ido-process-ignore-lists nil)) - - (if (and ido-use-merged-list (memq ido-try-merged-list '(t wide)) (not ido-keep-item-list)) - (let ((olist ido-cur-list) - (oign ido-ignored-list) - (omat ido-matches) - (l (ido-make-merged-file-list ido-text-init - (eq ido-use-merged-list 'auto) - (eq ido-try-merged-list 'wide)))) - (ido-trace "merged" l) - (cond - ((not l) - (if (eq ido-try-merged-list 'wide) - (setq ido-pre-merge-state - (list "" ido-current-directory olist oign omat) - ido-cur-list nil - ido-ignored-list nil - ido-matches nil - ido-keep-item-list t - ido-try-merged-list (if (eq ido-use-merged-list 'auto) 'auto nil) - ido-use-merged-list nil) - (setq ido-cur-list olist - ido-ignored-list oign - ido-matches omat - ido-keep-item-list t - ido-try-merged-list (if (eq ido-use-merged-list 'auto) 'auto nil) - ido-use-merged-list nil))) - ((eq l t) - (setq ido-use-merged-list nil)) - ((eq l 'input-pending-p) - (setq ido-try-merged-list t - ido-use-merged-list nil)) - (t - (setq ido-pre-merge-state - (list ido-text-init ido-current-directory olist oign omat)) - (ido-set-current-directory (car (cdr (car l)))) - (if (ido-final-slash ido-text-init) - (setq ido-text-init "")) - (setq ido-cur-list l - ido-ignored-list nil - ido-matches l - ido-rescan nil - ido-keep-item-list t - ido-use-merged-list t) - (ido-trace "Merged" t) - )))) - - (cond - (ido-keep-item-list - (setq ido-keep-item-list nil - ido-rescan nil)) - ((eq ido-cur-item 'file) - (setq ido-ignored-list nil - ido-cur-list (and (not ido-directory-nonreadable) - (not ido-directory-too-big) - (ido-make-file-list ido-default-item)))) - ((eq ido-cur-item 'dir) - (setq ido-ignored-list nil - ido-cur-list (and (not ido-directory-nonreadable) - (not ido-directory-too-big) - (ido-make-dir-list ido-default-item)))) - ((eq ido-cur-item 'buffer) - (setq ido-ignored-list nil - ido-cur-list (ido-make-buffer-list ido-default-item))) - ((eq ido-cur-item 'list) - (setq ido-ignored-list nil - ido-cur-list (ido-make-choice-list ido-default-item))) - (t nil)) - (setq ido-rotate-temp nil) - - (if ido-process-ignore-lists-inhibit - (setq ido-process-ignore-lists t - ido-process-ignore-lists-inhibit nil)) - - (ido-set-matches) - (if (and ido-matches (eq ido-try-merged-list 'auto)) - (setq ido-try-merged-list t)) - (let ((max-mini-window-height (or ido-max-window-height - (and (boundp 'max-mini-window-height) - max-mini-window-height))) - (ido-completing-read t) - (ido-require-match require-match) - (ido-use-mycompletion-depth (1+ (minibuffer-depth))) - (show-paren-mode nil) - ;; Postpone history adding till later - (history-add-new-input nil)) - ;; prompt the user for the file name - (setq ido-exit nil) - (setq ido-final-text - (catch 'ido - (read-from-minibuffer (ido-make-prompt item prompt) - (prog1 ido-text-init - (setq ido-text-init nil)) - ido-completion-map nil hist)))) - (ido-trace "read-from-minibuffer" ido-final-text) - (and ido-completion-buffer - (get-buffer ido-completion-buffer) - (kill-buffer ido-completion-buffer)) - - (ido-trace "\n_EXIT_" ido-exit) - - (cond - ((eq ido-exit 'refresh) - (if (and (eq ido-use-merged-list 'auto) - (or (input-pending-p))) - (setq ido-use-merged-list nil - ido-keep-item-list t)) - nil) - - ((eq ido-exit 'done) - (setq done t - ido-selected ido-text - ido-exit nil)) - - ((memq ido-exit '(edit chdir)) - (cond - ((memq ido-cur-item '(file dir)) - (let* ((read-file-name-function nil) - (edit (eq ido-exit 'edit)) - (d ido-current-directory) - (f ido-text-init) - (new t)) - (setq ido-text-init "") - (while new - (setq new (if edit - (condition-case nil - (read-file-name (concat prompt "[EDIT] ") - (expand-file-name d) - (concat d f) nil f) - (quit (concat d f))) - f) - d (or (file-name-directory new) "/") - f (file-name-nondirectory new) - edit t) - (if (or - (file-directory-p d) - (and (yes-or-no-p (format "Create directory %s? " d)) - (condition-case nil - (progn (make-directory d t) t) - (error - (message "Could not create directory") - (sit-for 1) - nil)))) - (progn - (ido-set-current-directory d nil (eq ido-exit 'chdir)) - (setq ido-text-init f - new nil)))))) - (t - (setq ido-text-init - (condition-case nil - (read-string (concat prompt "[EDIT] ") ido-final-text) - (quit ido-final-text))))) - - nil) - - ((eq ido-exit 'keep) - (setq ido-keep-item-list t)) - - ((memq ido-exit '(dired fallback find-file switch-to-buffer insert-buffer insert-file)) - (setq done t)) - - ((memq ido-exit '(updir push)) - ;; cannot go up if already at the root-dir (Unix) or at the - ;; root-dir of a certain drive (Windows or MS-DOS). - (if (ido-is-tramp-root) - (when (string-match "\\`\\(/\\([^/]+[:@]\\)*\\)\\([^/]+\\)[:@]\\'" ido-current-directory) - (setq ido-text-init (match-string 3 ido-current-directory)) - (ido-set-current-directory (match-string 1 ido-current-directory)) - (setq ido-set-default-item t)) - (unless (ido-is-root-directory) - (when (eq ido-exit 'push) - (setq ido-input-stack (cons (cons ido-cur-item ido-text) ido-input-stack)) - (setq ido-cur-item 'dir) - (setq ido-text-init (file-name-nondirectory (substring ido-current-directory 0 -1))) - (ido-trace "push" ido-input-stack)) - (ido-set-current-directory (file-name-directory (substring ido-current-directory 0 -1))) - (setq ido-set-default-item t)))) - - ((eq ido-exit 'pop) - (ido-trace "pop" ido-input-stack) - (let ((elt (car ido-input-stack))) - (setq ido-input-stack (cdr ido-input-stack)) - (ido-set-current-directory (concat ido-current-directory ido-text)) - (setq ido-cur-item (car elt)) - (setq ido-text-init (cdr elt)))) - - ((eq ido-exit 'pop-all) - (ido-trace "pop-all" ido-input-stack) - (while ido-input-stack - (let ((elt (car ido-input-stack))) - (setq ido-input-stack (cdr ido-input-stack)) - (ido-set-current-directory (concat ido-current-directory ido-text)) - (setq ido-cur-item (car elt)) - (setq ido-text-init (cdr elt))))) - - ;; Handling the require-match must be done in a better way. - ((and require-match - (not (memq require-match '(confirm confirm-after-completion))) - (not (if ido-directory-too-big - (file-exists-p (concat ido-current-directory ido-final-text)) - (ido-existing-item-p)))) - (error "Must specify valid item")) - - (t - (setq ido-selected - (if (or (eq ido-exit 'takeprompt) - (null ido-matches)) - ido-final-text - ;; else take head of list - (ido-name (car ido-matches)))) - - (cond - ((memq item '(buffer list)) - (setq done t)) - - ((string-equal "./" ido-selected) - nil) - - ((string-equal "../" ido-selected) - ;; cannot go up if already at the root-dir (Unix) or at the - ;; root-dir of a certain drive (Windows or MS-DOS). - (or (ido-is-root-directory) - (ido-set-current-directory (file-name-directory (substring ido-current-directory 0 -1)))) - (setq ido-set-default-item t)) - - ((and (string-match (if ido-enable-tramp-completion ".[:@]\\'" ".:\\'") ido-selected) - (ido-is-root-directory) ;; Ange-ftp or Tramp - (not (ido-local-file-exists-p ido-selected))) - (ido-set-current-directory ido-current-directory ido-selected) - (ido-trace "tramp prefix" ido-selected) - (if (ido-is-slow-ftp-host) - (setq ido-exit 'fallback - done t) - (setq ido-set-default-item t))) - - ((string-match (if (memq system-type '(windows-nt ms-dos)) - "\\`[a-zA-Z]:\\|[/\\][^/\\]" - "/[^/]") - ido-selected) - (ido-set-current-directory (file-name-directory ido-selected)) - (setq ido-set-default-item t)) - - ((string-match "\\`~" ido-selected) - (ido-set-current-home ido-selected)) - - ((ido-final-slash ido-selected) - (if ido-enable-last-directory-history - (let ((x (assoc ido-current-directory ido-last-directory-list))) - (if x - (setcdr x ido-selected) - (setq ido-last-directory-list - (cons (cons ido-current-directory ido-selected) ido-last-directory-list))))) - (ido-set-current-directory ido-current-directory ido-selected) - (if ido-input-stack - ; automatically pop stack elements which match existing files or directories - (let (elt) - (while (and (setq elt (car ido-input-stack)) - (file-exists-p (concat ido-current-directory (cdr elt)))) - (if (setq ido-input-stack (cdr ido-input-stack)) - (ido-set-current-directory ido-current-directory (cdr elt)) - (setq ido-text-init (cdr elt))) - (setq ido-cur-item (car elt)))) - (setq ido-set-default-item t))) - - (t - (setq done t)))))) - (add-to-history (cond - ((consp hist) - (or (car hist) 'minibuffer-history)) - (hist hist) - (t 'minibuffer-history)) - ido-selected) - ido-selected)) - -(defun ido-edit-input () - "Edit absolute file name entered so far with Ido; terminate by RET. -If cursor is not at the end of the user input, move to end of input." - (interactive) - (if (not (eobp)) - (end-of-line) - (setq ido-text-init (if ido-matches (ido-name (car ido-matches)) ido-text)) - (setq ido-exit 'edit) - (exit-minibuffer))) - -;;; MAIN FUNCTIONS -(defun ido-buffer-internal (method &optional fallback prompt default initial switch-cmd) - ;; Internal function for ido-switch-buffer and friends - (if (not ido-mode) - (progn - (run-hook-with-args 'ido-before-fallback-functions - (or fallback 'switch-to-buffer)) - (call-interactively (or fallback 'switch-to-buffer))) - (setq ido-fallback nil) - (let* ((ido-context-switch-command switch-cmd) - (ido-current-directory nil) - (ido-directory-nonreadable nil) - (ido-directory-too-big nil) - (ido-enable-virtual-buffers (and ido-use-virtual-buffers - (not (eq ido-use-virtual-buffers 'auto)))) - (require-match (confirm-nonexistent-file-or-buffer)) - (buf (ido-read-internal 'buffer (or prompt "Buffer: ") 'ido-buffer-history default - require-match initial)) - filename) - - ;; Choose the buffer name: either the text typed in, or the head - ;; of the list of matches - - (cond - ((eq ido-exit 'find-file) - (ido-file-internal - (if (memq method '(other-window other-frame)) method ido-default-file-method) - nil nil nil nil ido-text)) - - ((eq ido-exit 'insert-file) - (ido-file-internal 'insert 'insert-file nil "Insert file: " nil ido-text 'ido-enter-insert-buffer)) - - ((eq ido-exit 'fallback) - (let ((read-buffer-function nil)) - (setq this-command (or ido-fallback fallback 'switch-to-buffer)) - (run-hook-with-args 'ido-before-fallback-functions this-command) - (call-interactively this-command))) - - ;; Check buf is non-nil. - ((not buf) nil) - ((= (length buf) 0) nil) - - ;; View buffer if it exists - ((get-buffer buf) - (add-to-history 'buffer-name-history buf) - (if (eq method 'insert) - (progn - (ido-record-command 'insert-buffer buf) - (push-mark - (save-excursion - (insert-buffer-substring (get-buffer buf)) - (point)))) - (ido-visit-buffer buf method t))) - - ;; check for a virtual buffer reference - ((and ido-enable-virtual-buffers - ido-virtual-buffers - (setq filename (assoc buf ido-virtual-buffers))) - (if (eq method 'kill) - (setq recentf-list - (delete (cdr filename) recentf-list)) - (ido-visit-buffer (find-file-noselect (cdr filename)) method t))) - - ((and (eq ido-create-new-buffer 'prompt) - (null require-match) - (not (y-or-n-p (format-message - "No buffer matching `%s', create one? " buf)))) - nil) - - ;; buffer doesn't exist - ((and (eq ido-create-new-buffer 'never) - (null require-match)) - (message "No buffer matching `%s'" buf)) - - ((and (eq ido-create-new-buffer 'prompt) - (null require-match) - (not (y-or-n-p (format-message - "No buffer matching `%s', create one? " buf)))) - nil) - - ;; create a new buffer - (t - (add-to-history 'buffer-name-history buf) - (setq buf (get-buffer-create buf)) - (set-buffer-major-mode buf) - (ido-visit-buffer buf method t)))))) - -(defun ido-record-work-directory (&optional dir) - (when (and (numberp ido-max-work-directory-list) (> ido-max-work-directory-list 0)) - (if (and (setq dir (or dir ido-current-directory)) (> (length dir) 0)) - (let ((items ido-work-directory-list-ignore-regexps) - (case-fold-search nil)) - (while (and items dir) - (if (string-match (car items) dir) - (setq dir nil)) - (setq items (cdr items))) - (if dir - (setq ido-work-directory-list (cons dir (delete dir ido-work-directory-list)))))) - (if (> (length ido-work-directory-list) ido-max-work-directory-list) - (setcdr (nthcdr (1- ido-max-work-directory-list) ido-work-directory-list) nil)))) - -(defun ido-forget-work-directory () - (interactive) - (when (and ido-current-directory ido-work-directory-list) - (setq ido-work-directory-list (delete ido-current-directory ido-work-directory-list)) - (when ido-use-merged-list - (ido-undo-merge-work-directory) - (setq ido-exit 'refresh - ido-try-merged-list t - ido-use-merged-list t - ido-text-init ido-text - ido-rotate-temp t) - (exit-minibuffer)))) - -(defun ido-record-work-file (name) - ;; Save NAME in ido-work-file-list - (when (and (numberp ido-max-work-file-list) (> ido-max-work-file-list 0)) - (or - (and ido-work-file-list (equal (car ido-work-file-list) name)) - (setq ido-work-file-list (cons name (delete name ido-work-file-list)))) - (if (> (length ido-work-file-list) ido-max-work-file-list) - (setcdr (nthcdr (1- ido-max-work-file-list) ido-work-file-list) nil)))) - -(defun ido-expand-directory (dir) - ;; Expand DIR or use DEFAULT-DIRECTORY if nil. - ;; Add final slash to result in case it was missing from DEFAULT-DIRECTORY. - (ido-final-slash (expand-file-name (or dir default-directory)) t)) - -(defun ido-file-internal (method &optional fallback default prompt item initial switch-cmd) - ;; Internal function for ido-find-file and friends - (unless item - (setq item 'file)) - (setq ido-fallback nil) - (let ((ido-current-directory (ido-expand-directory default)) - (ido-context-switch-command switch-cmd) - ido-directory-nonreadable ido-directory-too-big - filename) - - (if (or (not ido-mode) (ido-is-slow-ftp-host)) - (setq filename t - ido-exit 'fallback) - (setq ido-directory-nonreadable - (ido-nonreadable-directory-p ido-current-directory) - ido-directory-too-big - (and (not ido-directory-nonreadable) - (ido-directory-too-big-p ido-current-directory)))) - - (let (ido-saved-vc-hb - (vc-handled-backends (and (boundp 'vc-handled-backends) - vc-handled-backends)) - (ido-work-directory-index -1) - (ido-work-file-index -1) - (ido-find-literal nil)) - - (unless filename - (setq ido-saved-vc-hb vc-handled-backends - filename - (ido-read-internal item - (or prompt "Find file: ") - 'ido-file-history - (and (eq method 'alt-file) buffer-file-name) - (confirm-nonexistent-file-or-buffer) - initial))) - - ;; Choose the file name: either the text typed in, or the head - ;; of the list of matches - - (cond - ((eq ido-exit 'fallback) - ;; Need to guard setting of default-directory here, since - ;; we don't want to change directory of current buffer. - (let ((default-directory ido-current-directory) - (read-file-name-function nil)) - (setq this-command (or ido-fallback fallback 'find-file)) - (run-hook-with-args 'ido-before-fallback-functions this-command) - (if (eq this-command 'write-file) - (write-file (read-file-name - "Write file: " - default-directory - (and buffer-file-name - (expand-file-name - (file-name-nondirectory buffer-file-name) - default-directory))) - t) - (call-interactively this-command)))) - - ((eq ido-exit 'switch-to-buffer) - (ido-buffer-internal - (if (memq method '(other-window other-frame)) - method ido-default-buffer-method) - nil nil nil ido-text)) - - ((eq ido-exit 'insert-buffer) - (ido-buffer-internal 'insert 'insert-buffer "Insert buffer: " - nil ido-text 'ido-enter-insert-file)) - - ((eq ido-exit 'dired) - (funcall (cond ((eq method 'other-window) #'dired-other-window) - ((eq method 'other-frame) #'dired-other-frame) - (t #'dired)) - (concat ido-current-directory (or ido-text "")))) - - ((eq method 'alt-file) - (ido-record-work-file filename) - (setq default-directory ido-current-directory) - (ido-record-work-directory) - (find-alternate-file filename)) - - ((eq method 'alt-file-other-window) - (ido-record-work-file filename) - (setq default-directory ido-current-directory) - (ido-record-work-directory) - (find-alternate-file-other-window filename)) - - ((memq method '(dired dired-other-window dired-other-frame - list-directory)) - (if (equal filename ".") - (setq filename "")) - (let* ((dirname (ido-final-slash - (concat ido-current-directory filename) t)) - (file (substring dirname 0 -1))) - (cond - ((file-directory-p dirname) - (ido-record-command method dirname) - (ido-record-work-directory dirname) - (funcall method dirname)) - ((file-directory-p ido-current-directory) - (cond - ((file-exists-p file) - (ido-record-command method ido-current-directory) - (ido-record-work-directory) - (funcall method ido-current-directory) - (if (eq method 'dired) - (with-no-warnings - (dired-goto-file (expand-file-name file))))) - ((string-match "[[*?]" filename) - (setq dirname (concat ido-current-directory filename)) - (ido-record-command method dirname) - (ido-record-work-directory) - (funcall method dirname)) - ((y-or-n-p (format "Directory %s does not exist. Create it? " - filename)) - (ido-record-command method dirname) - (ido-record-work-directory dirname) - (make-directory dirname) - (funcall method dirname)) - (t - ;; put make-directory command on history - (ido-record-command 'make-directory dirname)))) - (t (error "No such directory"))))) - - ((eq method 'write) - (ido-record-work-file filename) - (setq default-directory ido-current-directory) - (setq filename (concat ido-current-directory filename)) - (ido-record-command 'write-file filename) - (add-to-history 'file-name-history filename) - (ido-record-work-directory) - (write-file filename t)) - - ((eq method 'read-only) - (ido-record-work-file filename) - (setq filename (concat ido-current-directory filename)) - (ido-record-command fallback filename) - (ido-record-work-directory) - (run-hook-with-args 'ido-before-fallback-functions fallback) - (funcall fallback filename)) - - ((eq method 'insert) - (ido-record-work-file filename) - (setq filename (concat ido-current-directory filename)) - (ido-record-command - (if ido-find-literal 'insert-file-literally 'insert-file) - filename) - (add-to-history 'file-name-history filename) - (ido-record-work-directory) - (insert-file-1 filename - (if ido-find-literal - #'insert-file-contents-literally - #'insert-file-contents))) - - (filename - (ido-record-work-file filename) - (setq filename (concat ido-current-directory filename)) - (ido-record-command 'find-file filename) - (add-to-history 'file-name-history filename) - (ido-record-work-directory) - (ido-visit-buffer (find-file-noselect filename nil ido-find-literal) - method)))))) - -(defun ido-existing-item-p () - ;; Return non-nil if there is a matching item - (not (null ido-matches))) - -;;; COMPLETION CODE - -(defun ido-set-common-completion () - ;; Find common completion of `ido-text' in `ido-matches' - ;; The result is stored in `ido-common-match-string' - (let (val) - (setq ido-common-match-string nil) - (if (and ido-matches - (not ido-enable-regexp) ;; testing - (stringp ido-text) - (> (length ido-text) 0)) - (if (setq val (ido-find-common-substring ido-matches ido-text)) - (setq ido-common-match-string val))) - val)) - -(defun ido-complete () - "Try and complete the current pattern amongst the file names." - (interactive) - (let (res) - (cond - (ido-incomplete-regexp - ;; Do nothing - ) - ((and (memq ido-cur-item '(file dir)) - (string-search "$" ido-text)) - (let ((evar (substitute-in-file-name (concat ido-current-directory ido-text)))) - (if (not (file-exists-p (file-name-directory evar))) - (message "Expansion generates non-existing directory name") - (if (file-directory-p evar) - (ido-set-current-directory evar) - (let ((d (or (file-name-directory evar) "/")) - (f (file-name-nondirectory evar))) - (when (file-directory-p d) - (ido-set-current-directory d) - (setq ido-text-init f)))) - (setq ido-exit 'refresh) - (exit-minibuffer)))) - - (ido-directory-too-big - (setq ido-directory-too-big nil) - (setq ido-text-init ido-text) - (setq ido-exit 'refresh) - (exit-minibuffer)) - - ((not ido-matches) - (when ido-completion-buffer - (call-interactively (setq this-command ido-cannot-complete-command)))) - - ((and (= 1 (length ido-matches)) - (not (and ido-enable-tramp-completion - (string-equal ido-current-directory "/") - (string-match ".[@:]\\'" (ido-name (car ido-matches))))) - (not (ido-local-file-exists-p (ido-name (car ido-matches))))) - ;; only one choice, so select it. - (if (not ido-confirm-unique-completion) - (exit-minibuffer) - (setq ido-rescan (not ido-enable-prefix)) - (delete-region (minibuffer-prompt-end) (point)) - (insert (ido-name (car ido-matches))))) - - (t ;; else there could be some completions - (setq res ido-common-match-string) - (if (and (not (memq res '(t nil))) - (not (equal res ido-text))) - ;; found something to complete, so put it in the minibuffer. - (progn - ;; move exact match to front if not in prefix mode - (setq ido-rescan (not ido-enable-prefix)) - (delete-region (minibuffer-prompt-end) (point)) - (insert res)) - ;; else nothing to complete - (call-interactively (setq this-command ido-cannot-complete-command)) - ))))) - -(defun ido-complete-space () - "Try completion unless inserting the space makes sense." - (interactive) - (if (and (stringp ido-common-match-string) - (stringp ido-text) - (cond - ((> (length ido-common-match-string) (length ido-text)) - (= (aref ido-common-match-string (length ido-text)) ? )) - (ido-matches - (let (insert-space - (re (concat (regexp-quote ido-text) " ")) - (comp ido-matches)) - (while comp - (if (string-match re (ido-name (car comp))) - (setq comp nil insert-space t) - (setq comp (cdr comp)))) - insert-space)) - (t nil))) - (insert " ") - (ido-complete))) - -(defun ido-undo-merge-work-directory (&optional text try refresh) - "Undo or redo last Ido directory merge operation. -If no merge has yet taken place, toggle automatic merging option." - (interactive) - (cond - (ido-pre-merge-state - (ido-set-current-directory (nth 1 ido-pre-merge-state)) - (setq ido-text-init (or text (car ido-pre-merge-state)) - ido-cur-list (nth 2 ido-pre-merge-state) - ido-ignored-list (nth 3 ido-pre-merge-state) - ido-matches (nth 4 ido-pre-merge-state) - ido-use-merged-list nil - ido-try-merged-list try - ido-keep-item-list (not refresh) - ido-rescan nil - ido-exit 'refresh - ido-pre-merge-state nil) - (exit-minibuffer)) - (text - nil) - (ido-try-merged-list - (setq ido-try-merged-list nil)) - (ido-matches - (setq ido-try-merged-list t)) - ((not ido-use-merged-list) - (ido-merge-work-directories)))) - -;;; Magic C-f - -(defun ido-magic-forward-char (arg) - "Move forward in user input or perform magic action. -If no user input is present, or at end of input, perform magic actions: -C-x C-b ... C-f switch to `ido-find-file'. -C-x C-f ... C-f fallback to non-Ido `find-file'. -C-x C-d ... C-f fallback to non-Ido brief `dired'. -C-x d ... C-f fallback to non-Ido `dired'." - (interactive "P") - (cond - ((or arg (not (eobp))) - (forward-char (min (prefix-numeric-value arg) - (- (point-max) (point))))) - ((memq ido-cur-item '(file dir)) - (ido-fallback-command)) - (ido-context-switch-command - (call-interactively ido-context-switch-command)) - ((eq ido-cur-item 'buffer) - (ido-enter-find-file)))) - -;;; Magic C-b - -(defun ido-magic-backward-char (arg) - "Move backward in user input or perform magic action. -If no user input is present, or at start of input, perform magic actions: -C-x C-f C-b switch to `ido-switch-buffer'. -C-x C-d C-b switch to `ido-switch-buffer'. -C-x d C-b switch to `ido-switch-buffer'. -C-x C-b C-b fallback to non-Ido `switch-to-buffer'." - (interactive "P") - (cond - ((or arg (> (point) (minibuffer-prompt-end))) - (forward-char - (- (min (prefix-numeric-value arg) - (- (point) (minibuffer-prompt-end)))))) - ((eq last-command this-command) - (when (and (memq ido-cur-item '(file dir)) - (not (bobp))) - (ido-push-dir))) ; else do nothing - ((eq ido-cur-item 'buffer) - (ido-fallback-command)) - (ido-context-switch-command - (call-interactively ido-context-switch-command)) - (t - (ido-enter-switch-buffer)))) - -;;; Magic C-d - -(defun ido-magic-delete-char (arg) - "Delete following char in user input or perform magic action. -If at end of user input, perform magic actions: -C-x C-f ... C-d enter `dired' on current directory." - (interactive "P") - (cond - ((or arg (not (eobp))) - (delete-char (min (prefix-numeric-value arg) - (- (point-max) (point))))) - (ido-context-switch-command - nil) - ((memq ido-cur-item '(file dir)) - (ido-enter-dired)))) - - -;;; TOGGLE FUNCTIONS - -(defun ido-toggle-case () - "Toggle the value of `ido-case-fold'." - (interactive) - (setq ido-case-fold (not ido-case-fold)) - ;; ask for list to be regenerated. - (setq ido-rescan t)) - -(defun ido-toggle-regexp () - "Toggle the value of `ido-enable-regexp'." - (interactive) - (setq ido-enable-regexp (not ido-enable-regexp)) - ;; ask for list to be regenerated. - (setq ido-rescan t)) - -(defun ido-toggle-prefix () - "Toggle the value of `ido-enable-prefix'." - (interactive) - (setq ido-enable-prefix (not ido-enable-prefix)) - ;; ask for list to be regenerated. - (setq ido-rescan t)) - -(defun ido-toggle-ignore () - "Toggle ignoring files specified with `ido-ignore-files'." - (interactive) - (if (and (not (eobp)) (> (point) (minibuffer-prompt-end))) - (goto-char (minibuffer-prompt-end)) - (if ido-directory-too-big - (progn - (message "Reading directory...") - (setq ido-directory-too-big nil)) - (setq ido-process-ignore-lists (not ido-process-ignore-lists))) - (setq ido-text-init ido-text) - (setq ido-exit 'refresh) - (exit-minibuffer))) - -(defun ido-toggle-vc () - "Toggle version control for this file." - (interactive) - (if (and ido-mode (eq ido-cur-item 'file)) - (progn - (setq vc-handled-backends - (if vc-handled-backends nil ido-saved-vc-hb)) - (setq ido-text-init ido-text) - (setq ido-exit 'keep) - (exit-minibuffer)))) - -(defun ido-toggle-literal () - "Toggle literal reading of this file." - (interactive) - (if (and ido-mode (eq ido-cur-item 'file)) - (progn - (setq ido-find-literal (not ido-find-literal)) - (setq ido-text-init ido-text) - (setq ido-exit 'keep) - (exit-minibuffer)))) - -(defun ido-toggle-virtual-buffers () - "Toggle the use of virtual buffers. -See `ido-use-virtual-buffers' for explanation of virtual buffer." - (interactive) - (when (and ido-mode (eq ido-cur-item 'buffer)) - (setq ido-enable-virtual-buffers - (if ido-enable-virtual-buffers - nil - ;; Use `always' instead of t for `ido-exhibit'. - 'always)) - (setq ido-text-init ido-text) - (setq ido-exit 'refresh) - (exit-minibuffer))) - -(defun ido-reread-directory () - "Read current directory again. -May be useful if cached version is no longer valid, but directory -timestamp has not changed (e.g. with FTP or on Windows)." - (interactive) - (if (and ido-mode (memq ido-cur-item '(file dir))) - (progn - (if (ido-is-unc-root) - (setq ido-unc-hosts-cache t) - (ido-remove-cached-dir ido-current-directory)) - (setq ido-text-init ido-text) - (setq ido-rotate-temp t) - (setq ido-exit 'refresh) - (exit-minibuffer)))) - -(defun ido-exit-minibuffer () - "Exit minibuffer, but make sure we have a match if one is needed." - (interactive) - (if (and (or (not ido-require-match) - (if (memq ido-require-match '(confirm confirm-after-completion)) - (if (or (eq ido-cur-item 'dir) - (eq last-command this-command)) - t - (setq ido-show-confirm-message t) - nil)) - (ido-existing-item-p)) - (not ido-incomplete-regexp)) - (exit-minibuffer))) - -(defun ido-select-text () - "Select the buffer or file named by the prompt. -If no buffer or file exactly matching the prompt exists, maybe create a new one." - (interactive) - (setq ido-exit 'takeprompt) - (exit-minibuffer)) - -(defun ido-fallback-command (&optional fallback-command) - "Fallback to non-Ido version of current command. -The optional FALLBACK-COMMAND argument indicates which command to run." - (interactive) - (let ((i (length ido-text))) - (while (> i 0) - (push (aref ido-text (setq i (1- i))) unread-command-events))) - (setq ido-exit 'fallback) - (setq ido-fallback fallback-command) - (exit-minibuffer)) - -(defun ido-enter-find-file () - "Drop into `find-file' from buffer switching." - (interactive) - (setq ido-exit 'find-file) - (exit-minibuffer)) - -(defun ido-enter-switch-buffer () - "Drop into `ido-switch-buffer' from file switching." - (interactive) - (setq ido-exit 'switch-to-buffer) - (exit-minibuffer)) - -(defun ido-enter-dired () - "Drop into `dired' from file switching." - (interactive) - (setq ido-exit 'dired) - (exit-minibuffer)) - -(defun ido-enter-insert-buffer () - "Drop into `insert-buffer' from insert file." - (interactive) - (setq ido-exit 'insert-buffer) - (exit-minibuffer)) - -(defun ido-enter-insert-file () - "Drop into `insert-file' from insert buffer." - (interactive) - (setq ido-exit 'insert-file) - (exit-minibuffer)) - - -(defun ido-up-directory (&optional clear) - "Go up one directory level." - (interactive "P") - (setq ido-text-init (if clear nil ido-text)) - (setq ido-exit 'updir) - (setq ido-rotate-temp t) - (exit-minibuffer)) - -(defun ido-delete-backward-updir (count) - "Delete char backwards, or at beginning of buffer, go up one level." - (interactive "P") - (cond - ((= (minibuffer-prompt-end) (point)) - (if (not count) - (ido-up-directory t))) - ((and ido-pre-merge-state (string-equal (car ido-pre-merge-state) ido-text)) - (ido-undo-merge-work-directory (substring ido-text 0 -1) t t)) - ((eq this-original-command 'viper-backward-char) - (funcall this-original-command (prefix-numeric-value count))) - ((eq this-original-command 'viper-del-backward-char-in-insert) - (funcall this-original-command)) - (t - (delete-char (- (prefix-numeric-value count)))))) - -(defun ido-delete-backward-word-updir (count) - "Delete all chars backwards, or at beginning of buffer, go up one level." - (interactive "P") - (if (= (minibuffer-prompt-end) (point)) - (if (not count) - (ido-up-directory t)) - (if (eq this-original-command 'viper-delete-backward-word) - (funcall this-original-command (prefix-numeric-value count)) - (backward-kill-word (prefix-numeric-value count))))) - -(defun ido-get-work-directory (&optional incr must-match) - (let ((n (length ido-work-directory-list)) - (i ido-work-directory-index) - (j 0) - dir) - (if (or (not ido-text) (= (length ido-text) 0)) - (setq must-match nil)) - (while (< j n) - (setq i (+ i incr) - j (1+ j)) - (if (> incr 0) - (if (>= i n) (setq i 0)) - (if (< i 0) (setq i (1- n)))) - (setq dir (nth i ido-work-directory-list)) - (if (and dir - (not (equal dir ido-current-directory)) - (file-directory-p dir) - (or (not must-match) - ;; TODO. check for nonreadable and too-big. - (ido-set-matches-1 - (if (eq ido-cur-item 'file) - (ido-make-file-list-1 dir) - (ido-make-dir-list-1 dir))))) - (setq j n) - (setq dir nil))) - (if dir - (setq ido-work-directory-index i)) - dir)) - -(defun ido-prev-work-directory () - "Change to next working directory in list." - (interactive) - (let ((dir (ido-get-work-directory 1 ido-work-directory-match-only))) - (when dir - (ido-set-current-directory dir) - (setq ido-exit 'refresh) - (setq ido-text-init ido-text) - (setq ido-rotate-temp t) - (exit-minibuffer)))) - -(defun ido-next-work-directory () - "Change to previous working directory in list." - (interactive) - (let ((dir (ido-get-work-directory -1 ido-work-directory-match-only))) - (when dir - (ido-set-current-directory dir) - (setq ido-exit 'refresh) - (setq ido-text-init ido-text) - (setq ido-rotate-temp t) - (exit-minibuffer)))) - -(defun ido-merge-work-directories () - "Search (and merge) work directories for files matching the current input string." - (interactive) - (setq ido-use-merged-list t ido-try-merged-list t) - (setq ido-exit 'refresh) - (setq ido-text-init ido-text) - (setq ido-rotate-temp t) - (exit-minibuffer)) - -(defun ido-wide-find-file (&optional file) - "Prompt for FILE to search for using `find', starting from current directory." - (interactive) - (unless file - (setq file - (condition-case nil - (read-string (concat "Wide find file: " ido-current-directory) ido-text) - (quit "")))) - (when (> (length file) 0) - (setq ido-use-merged-list t ido-try-merged-list 'wide) - (setq ido-exit 'refresh) - (setq ido-text-init file) - (setq ido-rotate-temp t) - (exit-minibuffer))) - -(defun ido-wide-find-dir (&optional dir) - "Prompt for DIR to search for using `find', starting from current directory." - (interactive) - (unless dir - (setq dir - (condition-case nil - (read-string (concat "Wide find directory: " ido-current-directory) ido-text) - (quit "")))) - (when (> (length dir) 0) - (setq ido-use-merged-list t ido-try-merged-list 'wide) - (setq ido-exit 'refresh) - (setq ido-text-init (ido-final-slash dir t)) - (setq ido-rotate-temp t) - (exit-minibuffer))) - -(defun ido-wide-find-dir-or-delete-dir (&optional _dir) - "Prompt for DIR to search for using `find', starting from current directory. -If input stack is non-empty, delete current directory component." - (interactive) - (if ido-input-stack - (ido-delete-backward-word-updir 1) - (ido-wide-find-dir))) - -(defun ido-take-first-match () - "Use first matching item as input text." - (interactive) - (when ido-matches - (setq ido-text-init (ido-name (car ido-matches))) - (setq ido-exit 'refresh) - (exit-minibuffer))) - -(defun ido-push-dir () - "Move to previous directory in file name, push current input on stack." - (interactive) - (setq ido-exit 'push) - (exit-minibuffer)) - -(defun ido-push-dir-first () - "Move to previous directory in file name, push first match on stack." - (interactive) - (if ido-matches - (setq ido-text (ido-name (car ido-matches)))) - (setq ido-exit 'push) - (exit-minibuffer)) - -(defun ido-pop-dir (arg) - "Pop directory from input stack back to input. -With \\[universal-argument], pop all elements." - (interactive "P") - (when ido-input-stack - (setq ido-exit (if arg 'pop-all 'pop)) - (exit-minibuffer))) - -(defun ido-wide-find-file-or-pop-dir (arg) - (interactive "P") - (if ido-input-stack - (ido-pop-dir arg) - (ido-wide-find-file))) - -(defun ido-make-directory (&optional dir) - "Prompt for DIR to create in current directory." - (interactive) - (unless dir - (setq dir - (read-string (concat "Make directory: " ido-current-directory) ido-text))) - (when (> (length dir) 0) - (setq dir (concat ido-current-directory dir)) - (unless (file-exists-p dir) - (make-directory dir t) - (ido-set-current-directory dir) - (setq ido-exit 'refresh) - (setq ido-text-init nil) - (setq ido-rotate-temp t) - (exit-minibuffer)))) - -(defun ido-get-work-file (incr) - (let ((n (length ido-work-file-list)) - (i (+ ido-work-file-index incr)) - name) - (if (> incr 0) - (if (>= i n) (setq i 0)) - (if (< i 0) (setq i (1- n)))) - (setq name (nth i ido-work-file-list)) - (setq ido-work-file-index i) - name)) - -(defun ido-prev-work-file () - "Change to next working file name in list." - (interactive) - (let ((name (ido-get-work-file 1))) - (when name - (setq ido-text-init name) - (setq ido-exit 'refresh) - (exit-minibuffer)))) - -(defun ido-next-work-file () - "Change to previous working file name in list." - (interactive) - (let ((name (ido-get-work-file -1))) - (when name - (setq ido-text-init name) - (setq ido-exit 'refresh) - (exit-minibuffer)))) - -(defun ido-copy-current-file-name (all) - "Insert file name of current buffer. -If repeated, insert text from buffer instead." - (interactive "P") - (let* ((bfname (or (buffer-file-name ido-entry-buffer) - (buffer-name ido-entry-buffer))) - (name (and bfname (file-name-nondirectory bfname)))) - (when name - (setq ido-text-init - (if (or all - (eq last-command this-command) - (not (equal (file-name-directory bfname) ido-current-directory)) - (not (string-match "\\.[^.]*\\'" name))) - name - (substring name 0 (1+ (match-beginning 0))))) - (setq ido-exit 'refresh - ido-try-merged-list nil) - (exit-minibuffer)))) - -(defun ido-copy-current-word (_all) - "Insert current word (file or directory name) from current buffer." - (interactive "P") - (let ((word (with-current-buffer ido-entry-buffer - (let ((p (point)) start-line end-line start-name) - (if (and mark-active (/= p (mark))) - (setq start-name (mark)) - (beginning-of-line) - (setq start-line (point)) - (end-of-line) - (setq end-line (point)) - (goto-char p) - (if (re-search-backward "[^-_a-zA-Z0-9:./\\~@]" start-line 1) - (forward-char 1)) - (setq start-name (point)) - (re-search-forward "[-_a-zA-Z0-9:./\\~@]*" end-line 1) - (if (= start-name (point)) - (setq start-name nil))) - (and start-name - (buffer-substring-no-properties start-name (point))))))) - (if (cond - ((not word) nil) - ((string-match "\\`[~/]" word) - (setq ido-text-init word - ido-try-merged-list nil - ido-exit 'chdir)) - ((string-search "/" word) - (setq ido-text-init (concat ido-current-directory word) - ido-try-merged-list nil - ido-exit 'chdir)) - (t - (setq ido-text-init word - ido-try-merged-list nil - ido-exit 'refresh))) - (exit-minibuffer)))) - -(defun ido-next-match () - "Put first element of `ido-matches' at the end of the list." - (interactive) - (if ido-matches - (let ((next (cadr ido-matches))) - (setq ido-cur-list (ido-chop ido-cur-list next)) - (setq ido-matches (ido-chop ido-matches next)) - (setq ido-rescan nil)))) - -(defun ido-prev-match () - "Put last element of `ido-matches' at the front of the list." - (interactive) - (if ido-matches - (let ((prev (car (last ido-matches)))) - (setq ido-cur-list (ido-chop ido-cur-list prev)) - (setq ido-matches (ido-chop ido-matches prev)) - (setq ido-rescan nil)))) - -(defun ido-next-match-dir () - "Find next directory in match list. -If work directories have been merged, cycle through directories for -first matching file." - (interactive) - (if ido-use-merged-list - (if ido-matches - (let* ((elt (car ido-matches)) - (dirs (cdr elt))) - (when (> (length dirs) 1) - (setcdr elt (ido-chop dirs (cadr dirs)))) - (setq ido-rescan nil))) - (let ((cnt (length ido-matches)) - (i 1)) - (while (and (< i cnt) (not (ido-final-slash (nth i ido-matches)))) - (setq i (1+ i))) - (if (< i cnt) - (setq ido-cur-list (ido-chop ido-cur-list (nth i ido-matches))))))) - -(defun ido-prev-match-dir () - "Find previous directory in match list. -If work directories have been merged, cycle through directories -for first matching file." - (interactive) - (if ido-use-merged-list - (if ido-matches - (let* ((elt (car ido-matches)) - (dirs (cdr elt))) - (when (> (length dirs) 1) - (setcdr elt (ido-chop dirs (car (last dirs))))) - (setq ido-rescan nil))) - (let* ((cnt (length ido-matches)) - (i (1- cnt))) - (while (and (> i 0) (not (ido-final-slash (nth i ido-matches)))) - (setq i (1- i))) - (if (> i 0) - (setq ido-cur-list (ido-chop ido-cur-list (nth i ido-matches))))))) - -(defun ido-restrict-to-matches (&optional removep) - "Set current item list to the currently matched items. - -When argument REMOVEP is non-nil, the currently matched items are -instead removed from the current item list." - (interactive "P") - (when ido-matches - (setq ido-cur-list (if removep - ;; An important feature is to preserve the - ;; order of the elements. - (seq-difference ido-cur-list ido-matches) - ido-matches) - ido-matches ido-cur-list - ido-text-init "" - ido-rescan nil - ido-exit 'keep) - (exit-minibuffer))) - -(defun ido-chop (items elem) - "Remove all elements before ELEM and put them at the end of ITEMS." - (let ((ret nil) - (next nil) - (sofar nil)) - (while (not ret) - (setq next (car items)) - (if (equal next elem) - (setq ret (append items (nreverse sofar))) - ;; else - (progn - (setq items (cdr items)) - (setq sofar (cons next sofar))))) - ret)) - -(defun ido-name (item) - ;; Return file name for current item, whether in a normal list - ;; or a merged work directory list. - (if (consp item) (car item) item)) - - -;;; CREATE LIST OF ALL CURRENT FILES - -(defun ido-all-completions () - ;; Return unsorted list of all completions. - (let ((ido-process-ignore-lists nil) - (ido-directory-too-big nil)) - (cond - ((eq ido-cur-item 'file) - (ido-make-file-list-1 ido-current-directory)) - ((eq ido-cur-item 'dir) - (ido-make-dir-list-1 ido-current-directory)) - ((eq ido-cur-item 'buffer) - (ido-make-buffer-list-1)) - ((eq ido-cur-item 'list) - ido-choice-list) - (t nil)))) - - -;; File list sorting - -(defun ido-file-lessp (a b) - "Simple compare two file names." - (when ido-case-fold - (setq a (downcase a) - b (downcase b))) - (string-lessp (ido-no-final-slash a) (ido-no-final-slash b))) - - -(defun ido-file-extension-lessp (a b) - "Compare file names according to ido-file-extensions-order list." - (when ido-case-fold - (setq a (downcase a) - b (downcase b))) - (let ((n (compare-strings a 0 nil b 0 nil nil)) - lessp p) - (if (eq n t) - nil - (if (< n 0) - (setq n (1- (- n)) - p a a b b p - lessp t) - (setq n (1- n))) - (cond - ((= n 0) - lessp) - ((= (aref a n) ?.) - (ido-file-extension-aux a b n lessp)) - (t - (while (and (> n 2) (/= (aref a n) ?.)) - (setq n (1- n))) - (if (> n 1) - (ido-file-extension-aux a b n lessp) - lessp)))))) - -(defun ido-file-extension-aux (a b n lessp) - (let ((oa (ido-file-extension-order a n)) - (ob (ido-file-extension-order b n))) - (cond - ((and oa ob) - (cond - ((= oa ob) - lessp) - (lessp - (> oa ob)) - (t - (< oa ob)))) - (oa - (not lessp)) - (ob - lessp) - (t - lessp)))) - -(defun ido-file-extension-order (s n) - (let ((l ido-file-extensions-order) - (i 0) o do) - (while l - (cond - ((eq (car l) t) - (setq do i - l (cdr l))) - ((eq (compare-strings s n nil (car l) 0 nil nil) t) - (setq o i - l nil)) - (t - (setq l (cdr l)))) - (setq i (1+ i))) - (or o do))) - - -(defun ido-sort-merged-list (items promote) - ;; Input is list of ("file" . "dir") cons cells. - ;; Output is sorted list of ("file "dir" ...) lists - (let ((l (sort items (lambda (a b) (string-lessp (car b) (car a))))) - res a cur) - (while l - (setq a (car l) - l (cdr l)) - (if (and res (string-equal (car (car res)) (car a))) - (progn - (setcdr (car (if cur (cdr res) res)) (cons (cdr a) (cdr (car res)))) - (if (and promote (string-equal ido-current-directory (cdr a))) - (setq cur t))) - (setq res (cons (list (car a) (cdr a)) res) - cur nil))) - res)) - -(defun ido-wide-find-dirs-or-files (dir file &optional prefix finddir) - ;; As ido-run-find-command, but returns a list of cons pairs ("file" . "dir") - (let ((filenames - (delq nil - (mapcar (lambda (name) - (unless (ido-ignore-item-p name ido-ignore-files t) - name)) - (split-string - (shell-command-to-string - (concat "find " - (shell-quote-argument dir) - (if ido-case-fold " -iname " " -name ") - (shell-quote-argument - (concat (if prefix "" "*") file "*")) - " -type " (if finddir "d" "f") " -print")))))) - filename d f - res) - (while filenames - (setq filename (car filenames) - filenames (cdr filenames)) - (if (and (file-name-absolute-p filename) - (file-exists-p filename)) - (setq d (file-name-directory filename) - f (file-name-nondirectory filename) - res (cons (cons (if finddir (ido-final-slash f t) f) d) res)))) - res)) - -(defun ido-flatten-merged-list (items) - "Create a list of directory names based on a merged directory list." - (let (res) - (while items - (let* ((item (car items)) - (file (car item)) - (dirs (cdr item))) - (while dirs - (setq res (cons (concat (car dirs) file) res) - dirs (cdr dirs)))) - (setq items (cdr items))) - res)) - - -(defun ido-make-merged-file-list-1 (text auto wide) - (let (res) - (if (and (ido-final-slash text) ido-dir-file-cache) - (if wide - (setq res (ido-wide-find-dirs-or-files - ido-current-directory (substring text 0 -1) ido-enable-prefix t)) - ;; Use list of cached directories - (let ((re (concat (regexp-quote (substring text 0 -1)) "[^/:]*/\\'")) - (dirs ido-dir-file-cache) - dir d f) - (while dirs - (setq dir (car dirs) - d (car dir) - dirs (cdr dirs)) - (when (not (ido-ignore-item-p d ido-ignore-directories-merge)) - (setq dir (cdr (cdr dir))) - (while dir - (setq f (car dir) - dir (cdr dir)) - (if (and (string-match re f) - (not (ido-ignore-item-p f ido-ignore-directories))) - (setq res (cons (cons f d) res))))) - (if (and auto (input-pending-p)) - (setq dirs nil - res t))))) - (if wide - (setq res (ido-wide-find-dirs-or-files - ido-current-directory text ido-enable-prefix nil)) - (let ((ido-text text) - (dirs ido-work-directory-list) - (must-match (and text (> (length text) 0))) - dir fl) - (if (and auto (not (member ido-current-directory dirs))) - (setq dirs (cons ido-current-directory dirs))) - (while dirs - (setq dir (car dirs) - dirs (cdr dirs)) - (when (and dir (stringp dir) - (or ido-merge-ftp-work-directories - (not (ido-is-ftp-directory dir))) - (file-directory-p dir) - ;; TODO. check for nonreadable and too-big. - (setq fl (if (eq ido-cur-item 'file) - (ido-make-file-list-1 dir t) - (ido-make-dir-list-1 dir t)))) - (if must-match - (setq fl (ido-set-matches-1 fl))) - (if fl - (setq res (nconc fl res)))) - (if (and auto (input-pending-p)) - (setq dirs nil - res t)))))) - res)) - -(defun ido-make-merged-file-list (text auto wide) - (let (res) - (message "Searching for `%s'...." text) - (condition-case nil - (if (eq t (setq res - (while-no-input - (ido-make-merged-file-list-1 text auto wide)))) - (setq res 'input-pending-p)) - (quit - (setq res t - ido-try-merged-list nil - ido-use-merged-list nil))) - (when (and res (listp res)) - (setq res (ido-sort-merged-list res auto))) - (when (and (or ido-rotate-temp ido-rotate-file-list-default) - (listp res) - (> (length text) 0)) - (let ((elt (assoc text res))) - (when (and elt (not (eq elt (car res)))) - (setq res (delq elt res)) - (setq res (cons elt res))))) - (message nil) - res)) - -(defun ido-make-buffer-list-1 (&optional frame visible) - "Return list of non-ignored buffer names." - (with-temp-buffer - ;; Each call to ido-ignore-item-p LET-binds case-fold-search. - ;; That is slow if there's no buffer-local binding available, - ;; roughly O(number of buffers). This hack avoids it. - (setq-local case-fold-search nil) - (delq nil - (mapcar - (lambda (x) - (let ((name (buffer-name x))) - (if (not (or (ido-ignore-item-p name ido-ignore-buffers) (member name visible))) - name))) - (buffer-list frame))))) - -(defun ido-make-buffer-list (default) - "Return the current list of buffers. -Currently visible buffers are put at the end of the list. -The hook `ido-make-buffer-list-hook' is run after the list has been -created to allow the user to further modify the order of the buffer names -in this list. If DEFAULT is non-nil, and corresponds to an existing buffer, -it is put to the start of the list." - (let* ((ido-current-buffers (ido-get-buffers-in-frames 'current)) - (ido-temp-list (ido-make-buffer-list-1 (selected-frame) ido-current-buffers))) - (if ido-temp-list - (nconc ido-temp-list ido-current-buffers) - (setq ido-temp-list ido-current-buffers)) - (if ido-predicate - (setq ido-temp-list (seq-filter - (lambda (name) - (funcall ido-predicate (cons name (get-buffer name)))) - ido-temp-list))) - (if default - (setq ido-temp-list - (cons default (delete default ido-temp-list)))) - (if (bound-and-true-p ido-enable-virtual-buffers) - (ido-add-virtual-buffers-to-list)) - (run-hooks 'ido-make-buffer-list-hook) - ido-temp-list)) - -(defun ido-add-virtual-buffers-to-list () - "Add recently visited files, and bookmark files, to the buffer list. -This is to make them appear as if they were \"virtual buffers\"." - ;; If no buffers matched, and virtual buffers are being used, then - ;; consult the list of past visited files, to see if we can find - ;; the file which the user might thought was still open. - (unless recentf-mode (recentf-mode 1)) - (setq ido-virtual-buffers nil) - (let (name) - (dolist (head (append - recentf-list - (and (fboundp 'bookmark-get-filename) - (delq nil (mapcar #'bookmark-get-filename - (bound-and-true-p bookmark-alist)))))) - (setq name (file-name-nondirectory head)) - ;; In case HEAD is a directory with trailing /. See bug#14552. - (when (equal name "") - (setq name (file-name-nondirectory (directory-file-name head)))) - (when (equal name "") - (setq name head)) - (and (not (equal name "")) - (null (let (file-name-handler-alist) (get-file-buffer head))) - (not (assoc name ido-virtual-buffers)) - (not (member name ido-temp-list)) - (not (ido-ignore-item-p name ido-ignore-buffers)) - ;;(file-exists-p head) - (push (cons name head) ido-virtual-buffers)))) - (when ido-virtual-buffers - (if ido-use-faces - (dolist (comp ido-virtual-buffers) - (put-text-property 0 (length (car comp)) - 'face 'ido-virtual - (car comp)))) - (setq ido-temp-list - (nconc ido-temp-list - (nreverse (mapcar #'car ido-virtual-buffers)))))) - -(defun ido-make-choice-list (default) - "Return the current list of choices. -If DEFAULT is non-nil, and corresponds to an element of choices, -it is put to the start of the list." - (let ((ido-temp-list ido-choice-list)) - (if default - (progn - (setq ido-temp-list - (delete default ido-temp-list)) - (setq ido-temp-list - (cons default ido-temp-list)))) - ; (run-hooks 'ido-make-choice-list-hook) - ido-temp-list)) - -(defun ido-to-end (items) - "Move the elements from ITEMS to the end of `ido-temp-list'." - (mapc - (lambda (elem) - (setq ido-temp-list (delq elem ido-temp-list))) - items) - (if ido-temp-list - (nconc ido-temp-list items) - (setq ido-temp-list items))) - -(defun ido-file-name-all-completions-1 (dir) - (cond - ((ido-nonreadable-directory-p dir) '()) - ;; do not check (ido-directory-too-big-p dir) here. - ;; Caller must have done that if necessary. - - ((and ido-enable-tramp-completion - (string-match "\\`/[^/]+[:@]\\'" dir)) - ;; Strip method:user@host: part of tramp completions. - ;; Tramp completions do not include leading slash. - (let* ((len (1- (length dir))) - (compl - (or ;; We do not want to be disturbed by "File does not - ;; exist" errors. - (ignore-errors (file-name-all-completions "" dir)) - ;; work around bug in ange-ftp. - ;; /ftp:user@host: => nil - ;; /ftp:user@host:./ => ok - (and - (not (string= "/ftp:" dir)) - (file-remote-p dir) - ;; tramp-ftp-file-name-p is available only when tramp - ;; has been loaded. - (fboundp 'tramp-ftp-file-name-p) - (tramp-ftp-file-name-p dir) - (string-match ":\\'" dir) - (file-name-all-completions "" (concat dir "./")))))) - (if (and compl - (> (length (car compl)) len) - (string= (substring (car compl) 0 len) (substring dir 1))) - (mapcar (lambda (c) (substring c len)) compl) - compl))) - (t - (file-name-all-completions "" dir)))) - -(defun ido-file-name-all-completions (dir) - "Return name of all files in DIR. -Uses and updates `ido-dir-file-cache'." - (cond - ((ido-is-unc-root dir) - (mapcar - (lambda (host) - (if (string-match "/\\'" host) host (concat host "/"))) - (ido-unc-hosts t))) - ((and (numberp ido-max-dir-file-cache) (> ido-max-dir-file-cache 0) - (stringp dir) (> (length dir) 0) - (ido-may-cache-directory dir)) - (let* ((cached (assoc dir ido-dir-file-cache)) - (ctime (nth 1 cached)) - (ftp (ido-is-ftp-directory dir)) - (unc (ido-is-unc-host dir)) - (attr (if (or ftp unc) nil (file-attributes dir))) - (mtime (file-attribute-modification-time attr)) - valid) - (when cached ; should we use the cached entry ? - (cond - (ftp - (setq valid (and (eq (car ctime) 'ftp) - (ido-cache-ftp-valid (cdr ctime))))) - (unc - (setq valid (and (eq (car ctime) 'unc) - (ido-cache-unc-valid (cdr ctime))))) - (t - (if attr - (setq valid (time-equal-p ctime mtime))))) - (unless valid - (setq ido-dir-file-cache (delq cached ido-dir-file-cache) - cached nil))) - (unless cached - (cond - (unc - (setq mtime (cons 'unc (ido-time-stamp)))) - ((and ftp (file-readable-p dir)) - (setq mtime (cons 'ftp (ido-time-stamp))))) - (if mtime - (setq cached (cons dir (cons mtime (ido-file-name-all-completions-1 dir))) - ido-dir-file-cache (cons cached ido-dir-file-cache))) - (if (> (length ido-dir-file-cache) ido-max-dir-file-cache) - (setcdr (nthcdr (1- ido-max-dir-file-cache) ido-dir-file-cache) nil))) - (and cached - (cdr (cdr cached))))) - (t - (ido-file-name-all-completions-1 dir)))) - -(defun ido-remove-cached-dir (dir) - "Remove DIR from `ido-dir-file-cache'." - (if (and ido-dir-file-cache - (stringp dir) (> (length dir) 0)) - (let ((cached (assoc dir ido-dir-file-cache))) - (if cached - (setq ido-dir-file-cache (delq cached ido-dir-file-cache)))))) - - -(defun ido-make-file-list-1 (dir &optional merged) - "Return list of non-ignored files in DIR. -If MERGED is non-nil, each file is cons'ed with DIR." - (and (or (ido-is-tramp-root dir) (ido-is-unc-root dir) - (file-directory-p dir)) - (delq nil - (mapcar - (lambda (name) - (if (not (ido-ignore-item-p name ido-ignore-files t)) - (if merged (cons name dir) name))) - (ido-file-name-all-completions dir))))) - -(defun ido-make-file-list (default) - "Return the current list of files. -Currently visible files are put at the end of the list. -The hook `ido-make-file-list-hook' is run after the list has been -created to allow the user to further modify the order of the file names -in this list." - (let ((ido-temp-list (ido-make-file-list-1 ido-current-directory))) - (setq ido-temp-list (sort ido-temp-list - (if ido-file-extensions-order - #'ido-file-extension-lessp - #'ido-file-lessp))) - (unless (ido-is-tramp-root ido-current-directory) - (let ((default-directory ido-current-directory)) - (ido-to-end ;; move ftp hosts and visited files to end - (delq nil (mapcar - (lambda (x) (if (or (and (string-match ".:\\'" x) - (not (ido-local-file-exists-p x))) - (and (not (ido-final-slash x)) - (let (file-name-handler-alist) - (get-file-buffer x)))) - x)) - ido-temp-list))))) - (ido-to-end ;; move . files to end - (delq nil (mapcar - (lambda (x) (if (string-match "\\`\\." x) x)) - ido-temp-list))) - (if (and default (member default ido-temp-list)) - (if (or ido-rotate-temp ido-rotate-file-list-default) - (unless (equal default (car ido-temp-list)) - (let ((l ido-temp-list) k) - (while (and l (cdr l) (not (equal default (car (cdr l))))) - (setq l (cdr l))) - (setq k (cdr l)) - (setcdr l nil) - (nconc k ido-temp-list) - (setq ido-temp-list k))) - (setq ido-temp-list - (delete default ido-temp-list)) - (setq ido-temp-list - (cons default ido-temp-list)))) - (when ido-show-dot-for-dired - (setq ido-temp-list (delete "." ido-temp-list)) - (setq ido-temp-list (cons "." ido-temp-list))) - (run-hooks 'ido-make-file-list-hook) - ido-temp-list)) - -(defun ido-make-dir-list-1 (dir &optional merged) - "Return list of non-ignored subdirs in DIR. -If MERGED is non-nil, each subdir is cons'ed with DIR." - (and (or (ido-is-tramp-root dir) (file-directory-p dir)) - (delq nil - (mapcar - (lambda (name) - (and (ido-final-slash name) - (not (ido-ignore-item-p name ido-ignore-directories)) - (if merged (cons name dir) name))) - (ido-file-name-all-completions dir))))) - -(defun ido-make-dir-list (default) - "Return the current list of directories. -The hook `ido-make-dir-list-hook' is run after the list has been -created to allow the user to further modify the order of the -directory names in this list." - (let ((ido-temp-list (ido-make-dir-list-1 ido-current-directory))) - (setq ido-temp-list (sort ido-temp-list #'ido-file-lessp)) - (ido-to-end ;; move . files to end - (delq nil (mapcar - (lambda (x) (if (string-equal (substring x 0 1) ".") x)) - ido-temp-list))) - (if (and default (member default ido-temp-list)) - (if (or ido-rotate-temp ido-rotate-file-list-default) - (unless (equal default (car ido-temp-list)) - (let ((l ido-temp-list) k) - (while (and l (cdr l) (not (equal default (car (cdr l))))) - (setq l (cdr l))) - (setq k (cdr l)) - (setcdr l nil) - (nconc k ido-temp-list) - (setq ido-temp-list k))) - (setq ido-temp-list - (delete default ido-temp-list)) - (setq ido-temp-list - (cons default ido-temp-list)))) - (setq ido-temp-list (delete "." ido-temp-list)) - (unless ido-input-stack - (setq ido-temp-list (cons "." ido-temp-list))) - (run-hooks 'ido-make-dir-list-hook) - ido-temp-list)) - -;; List of the files visible in the current frame. -(defvar ido-bufs-in-frame) - -(defun ido-get-buffers-in-frames (&optional current) - "Return the list of buffers that are visible in the current frame. -If optional argument CURRENT is given, restrict searching to the current -frame, rather than all frames, regardless of value of `ido-all-frames'." - (let ((ido-bufs-in-frame nil)) - (walk-windows 'ido-get-bufname nil - (if current - nil - ido-all-frames)) - ido-bufs-in-frame)) - -(defun ido-get-bufname (win) - "Used by `ido-get-buffers-in-frames' to walk through all windows." - (let ((buf (buffer-name (window-buffer win)))) - (unless (or (member buf ido-bufs-in-frame) - (member buf ido-ignore-item-temp-list)) - ;; Only add buf if it is not already in list. - ;; This prevents same buf in two different windows being - ;; put into the list twice. - (setq ido-bufs-in-frame - (cons buf ido-bufs-in-frame))))) - -;;; FIND MATCHING ITEMS - -(defun ido-set-matches-1 (items &optional do-full) - "Return list of matches in ITEMS." - (let* ((case-fold-search ido-case-fold) - (slash (and (not ido-enable-prefix) (ido-final-slash ido-text))) - (text (if slash (substring ido-text 0 -1) ido-text)) - (rex0 (if ido-enable-regexp text (regexp-quote text))) - (rexq (concat rex0 (if slash ".*/" ""))) - (re (if ido-enable-prefix (concat "\\`" rexq) rexq)) - (full-re (and do-full - (not (and (eq ido-cur-item 'buffer) - ido-buffer-disable-smart-matches)) - (not ido-enable-regexp) - (not (string-match "\\$\\'" rex0)) - (concat "\\`" rex0 (if slash "/" "") "\\'"))) - (suffix-re (and do-full slash - (not (and (eq ido-cur-item 'buffer) - ido-buffer-disable-smart-matches)) - (not ido-enable-regexp) - (not (string-match "\\$\\'" rex0)) - (concat rex0 "/\\'"))) - (prefix-re (and full-re (not ido-enable-prefix) - (concat "\\`" rexq))) - (non-prefix-dot (or (not ido-enable-dot-prefix) - (not ido-process-ignore-lists) - ido-enable-prefix - (= (length ido-text) 0))) - full-matches suffix-matches prefix-matches matches) - (setq ido-incomplete-regexp nil) - (condition-case error - (mapc - (lambda (item) - (let ((name (ido-name item))) - (if (and (or non-prefix-dot - (and (> (length name) 0) - (if (= (aref ido-text 0) ?.) - (= (aref name 0) ?.) - (/= (aref name 0) ?.)))) - (string-match re name)) - (cond - ((and (eq ido-cur-item 'buffer) - (or (not (stringp ido-default-item)) - (not (string= name ido-default-item))) - (string= name (buffer-name ido-entry-buffer))) - (setq matches (cons item matches))) - ((and full-re (string-match full-re name)) - (setq full-matches (cons item full-matches))) - ((and suffix-re (string-match suffix-re name)) - (setq suffix-matches (cons item suffix-matches))) - ((and prefix-re (string-match prefix-re name)) - (setq prefix-matches (cons item prefix-matches))) - (t (setq matches (cons item matches)))))) - t) - items) - (invalid-regexp - (setq ido-incomplete-regexp t - ;; Consider the invalid regexp message internally as a - ;; special-case single match, and handle appropriately - ;; elsewhere. - matches (cdr error)))) - (when prefix-matches - (ido-trace "prefix match" prefix-matches) - ;; Bug#2042. - (setq matches (nconc prefix-matches matches))) - (when suffix-matches - (ido-trace "suffix match" (list text suffix-re suffix-matches)) - (setq matches (nconc suffix-matches matches))) - (when full-matches - (ido-trace "full match" (list text full-re full-matches)) - (setq matches (nconc full-matches matches))) - (when (and (null matches) - ido-enable-flex-matching - (> (length ido-text) 1) - (not ido-enable-regexp)) - (setq re (concat (regexp-quote (string (aref ido-text 0))) - (mapconcat (lambda (c) - (concat "[^" (string c) "]*" - (regexp-quote (string c)))) - (substring ido-text 1) ""))) - (if ido-enable-prefix - (setq re (concat "\\`" re))) - (mapc - (lambda (item) - (let ((name (ido-name item))) - (if (string-match re name) - (setq matches (cons item matches))))) - items)) - (delete-consecutive-dups matches t))) - - -(defun ido-set-matches () - "Set `ido-matches' to the list of items matching prompt." - (when ido-rescan - (setq ido-matches (ido-set-matches-1 (reverse ido-cur-list) (not ido-rotate)) - ido-rotate nil))) - -(defun ido-ignore-item-p (name re-list &optional ignore-ext) - "Return t if the buffer or file NAME should be ignored." - (or (and (member name ido-ignore-item-temp-list) t) - (and - ido-process-ignore-lists re-list - (save-match-data - (let ((ext-list (and ignore-ext ido-ignore-extensions - completion-ignored-extensions)) - (case-fold-search ido-case-fold) - ignorep nextstr - (flen (length name)) slen) - (while ext-list - (setq nextstr (car ext-list)) - (if (cond - ((stringp nextstr) - (and (>= flen (setq slen (length nextstr))) - (string-equal (substring name (- flen slen)) nextstr))) - ((functionp nextstr) (funcall nextstr name)) - (t nil)) - (setq ignorep t - ext-list nil - re-list nil) - (setq ext-list (cdr ext-list)))) - (while re-list - (setq nextstr (car re-list)) - (if (cond - ((stringp nextstr) (string-match nextstr name)) - ((functionp nextstr) (funcall nextstr name)) - (t nil)) - (setq ignorep t - re-list nil) - (setq re-list (cdr re-list)))) - ;; return the result - (if ignorep - (setq ido-ignored-list (cons name ido-ignored-list))) - ignorep))))) - -;; Private variable used by `ido-word-matching-substring'. -(defvar ido-change-word-sub) - -(defun ido-find-common-substring (items subs) - "Return common string following SUBS in each element of ITEMS." - (let (res - alist - ido-change-word-sub) - (setq ido-change-word-sub - (if ido-enable-regexp - subs - (regexp-quote subs))) - (setq res (mapcar #'ido-word-matching-substring items)) - (setq res (delq nil res)) ;; remove any nil elements (shouldn't happen) - (setq alist (mapcar #'ido-makealist res)) ;; could use an OBARRAY - - ;; try-completion returns t if there is an exact match. - (let* ((completion-ignore-case ido-case-fold) - (comp (try-completion subs alist))) - (if (eq comp t) - subs - comp)))) - -(defun ido-word-matching-substring (word) - "Return part of WORD before first match to `ido-change-word-sub'. -If `ido-change-word-sub' cannot be found in WORD, return nil." - (let ((case-fold-search ido-case-fold)) - (let ((m (string-match ido-change-word-sub (ido-name word)))) - (if m - (substring (ido-name word) m) - ;; else no match - nil)))) - -(defun ido-makealist (res) - "Return dotted pair (RES . 1)." - (cons res 1)) - -(defun ido-choose-completion-string (choice &rest _ignored) - (when (ido-active) - ;; Insert the completion into the buffer where completion was requested. - (and ido-completion-buffer - (get-buffer ido-completion-buffer) - (kill-buffer ido-completion-buffer)) - (cond - ((ido-active t) ;; ido-use-merged-list - (setq ido-current-directory "" - ido-text choice - ido-exit 'done)) - ((not (ido-final-slash choice)) - (setq ido-text choice - ido-exit 'done)) - (t - (ido-set-current-directory ido-current-directory choice) - (setq ido-exit 'refresh))) - (exit-minibuffer) - t)) - -;; This is a shameless copy of `switch-to-completions'. -(defun ido-switch-to-completions () - "Select the window showing `ido-completion-buffer'." - (interactive) - (let ((window (or (get-buffer-window ido-completion-buffer 0) - ;; Make sure we have a completions window. - (progn (ido-completion-help) - (get-buffer-window ido-completion-buffer 0))))) - (when window - (select-window window) - ;; In the new buffer, go to the first completion. - ;; FIXME: Perhaps this should be done in `ido-completion-help'. - (when (bobp) - (first-completion))))) - -(defun ido-completion-auto-help () - "Call `ido-completion-help' if `completion-auto-help' is non-nil." - (interactive) - ;; Note: `completion-auto-help' could also be `lazy', but this value - ;; is irrelevant to ido, which is fundamentally eager, so it is - ;; treated the same as t. - (when completion-auto-help - (ido-completion-help))) - -(defun ido-completion-help () - "Show possible completions in the `ido-completion-buffer'." - (interactive) - (setq ido-rescan nil) - (let ((temp-buf (and ido-completion-buffer - (get-buffer ido-completion-buffer))) - display-it full-list) - (if (and (eq last-command this-command) temp-buf) - ;; scroll buffer - (let (win (buf (current-buffer))) - (display-buffer temp-buf) - (set-buffer temp-buf) - (setq win (get-buffer-window temp-buf)) - (if (pos-visible-in-window-p (point-max) win) - (if (or ido-completion-buffer-all-completions - (boundp 'ido-completion-buffer-full)) - (set-window-start win (point-min)) - (with-no-warnings - (setq-local ido-completion-buffer-full t)) - (setq full-list t - display-it t)) - (scroll-other-window)) - (set-buffer buf)) - (setq display-it t)) - (if (and ido-completion-buffer display-it) - (with-temp-buffer-window ido-completion-buffer - '((display-buffer-reuse-window display-buffer-at-bottom) - (window-height . fit-window-to-buffer)) - nil - (let* ((comps - (cond - (ido-directory-too-big - (message "Reading directory...") - (setq ido-directory-too-big nil - ido-ignored-list nil - ido-cur-list (ido-all-completions) - ido-rescan t) - (ido-set-matches) - (or ido-matches ido-cur-list)) - (ido-use-merged-list - (ido-flatten-merged-list (or ido-matches ido-cur-list))) - ((or full-list ido-completion-buffer-all-completions) - (ido-all-completions)) - (t - (copy-sequence (or ido-matches ido-cur-list))))) - (completion-list - ;; If we have an alist COMPLETIONS, transform to a - ;; simple list first. - (sort (if (and (consp comps) - (consp (car comps))) - (mapcar #'car comps) - comps) - #'ido-file-lessp))) - ;;(add-hook 'completion-setup-hook #'completion-setup-function) - (display-completion-list completion-list)))))) - -;;; KILL CURRENT BUFFER -(defun ido-kill-buffer-at-head () - "Kill the buffer at the head of `ido-matches'. -If cursor is not at the end of the user input, delete to end of input." - (interactive) - (if (not (eobp)) - (delete-region (point) (line-end-position)) - (let ((buf (ido-name (car ido-matches))) - (nextbuf (cadr ido-matches))) - (cond - ((get-buffer buf) - ;; If next match names a buffer use the buffer object; buffer - ;; name may be changed by packages such as uniquify. - (when (and nextbuf (get-buffer nextbuf)) - (setq nextbuf (get-buffer nextbuf))) - (if (null (kill-buffer buf)) - ;; Buffer couldn't be killed. - (setq ido-rescan t) - ;; Else `kill-buffer' succeeds so re-make the buffer list - ;; taking into account packages like uniquify may rename - ;; buffers. - (if (bufferp nextbuf) - (setq nextbuf (buffer-name nextbuf))) - (setq ido-default-item nextbuf - ido-text-init ido-text - ido-exit 'refresh) - (exit-minibuffer))) - ;; Handle virtual buffers - ((assoc buf ido-virtual-buffers) - (setq recentf-list - (delete (cdr (assoc buf ido-virtual-buffers)) recentf-list)) - (setq ido-cur-list (delete buf ido-cur-list)) - (setq ido-rescan t)))))) - -;;; BURY CURRENT BUFFER -(defun ido-bury-buffer-at-head () - "Bury the buffer at the head of `ido-matches'." - (interactive) - (let ((buf (ido-name (car ido-matches))) - (nextbuf (cadr ido-matches))) - (when (get-buffer buf) - (bury-buffer buf) - (setq ido-default-item nextbuf - ido-text-init ido-text - ido-exit 'refresh) - (exit-minibuffer)))) - -;;; DELETE CURRENT FILE -(defun ido-delete-file-at-head () - "Delete the file at the head of `ido-matches'. -Trash the file if `delete-by-moving-to-trash' is non-nil. -If cursor is not at the end of the user input, delete to end of input." - (interactive) - (if (not (eobp)) - (delete-region (point) (line-end-position)) - (let ((file (ido-name (car ido-matches)))) - (if file - (setq file (concat ido-current-directory file))) - (when (and file - (file-exists-p file) - (not (file-directory-p file)) - (file-writable-p ido-current-directory) - (or delete-by-moving-to-trash - (yes-or-no-p (concat "Delete " file "? ")))) - (delete-file file 'trash) - ;; Check if file still exists. - (if (file-exists-p file) - ;; file could not be deleted - (setq ido-rescan t) - ;; else file was killed so remove name from list. - (setq ido-cur-list (delq (car ido-matches) ido-cur-list))))))) - - -;;; VISIT CHOSEN BUFFER -(defun ido-visit-buffer (buffer method &optional record) - "Switch to BUFFER according to METHOD. -Record command in `command-history' if optional RECORD is non-nil." - (if (bufferp buffer) - (setq buffer (buffer-name buffer))) - (let (win newframe) - (cond - ;; "Killing" of virtual buffers is handled in `ido-buffer-internal'. - ((eq method 'kill) - (if record - (ido-record-command 'kill-buffer buffer)) - (kill-buffer buffer)) - - ((eq method 'other-window) - (if record - (ido-record-command 'switch-to-buffer buffer)) - (switch-to-buffer-other-window buffer)) - - ((eq method 'display) - (display-buffer buffer)) - - ((eq method 'display-even-when-displayed) - (display-buffer buffer t)) - - ((eq method 'other-frame) - (switch-to-buffer-other-frame buffer) - (select-frame-set-input-focus (selected-frame))) - - ((eq method 'display-other-frame) - (display-buffer-other-frame buffer)) - - ((and (memq method '(raise-frame maybe-frame)) - window-system - (setq win (ido-buffer-window-other-frame buffer)) - (or (eq method 'raise-frame) - (y-or-n-p "Jump to frame? "))) - (setq newframe (window-frame win)) - (select-frame-set-input-focus newframe) - (select-window win)) - - ;; (eq method 'selected-window) - (t - ;; No buffer in other frames... - (if record - (ido-record-command 'switch-to-buffer buffer)) - (switch-to-buffer buffer) - )))) - - -(defun ido-buffer-window-other-frame (buffer) - "Return window pointer if BUFFER is visible in another frame. -If BUFFER is visible in the current frame, return nil." - (let ((blist (ido-get-buffers-in-frames 'current))) - ;;If the buffer is visible in current frame, return nil - (if (member buffer blist) - nil - ;; maybe in other frame or icon - (get-buffer-window buffer 0) ; better than 'visible - ))) - - -;;; ----------- IDONIZED FUNCTIONS ------------ - -;;;###autoload -(defun ido-switch-buffer () - "Switch to another buffer. -The buffer is displayed according to `ido-default-buffer-method' -- the -default is to show it in the same window, unless it is already visible -in another frame. - -As you type in a string, all of the buffers matching the string are -displayed if substring-matching is used (default). Look at -`ido-enable-prefix' and `ido-toggle-prefix'. When you have found the -buffer you want, it can then be selected. As you type, most keys have -their normal keybindings, except for the following: \\ - -RET\tSelect the buffer at the front of the list of matches. -\tIf the list is empty, possibly prompt to create new buffer. - -\\[ido-select-text]\tUse the current input string verbatim. - -\\[ido-next-match]\tPut the first element at the end of the list. -\\[ido-prev-match]\tPut the last element at the start of the list. -\\[ido-complete]\tComplete a common suffix to the current string that matches -\tall buffers. If there is only one match, select that buffer. -\tIf there is no common suffix, show a list of all matching buffers -\tin a separate window. -\\[ido-edit-input]\tEdit input string. -\\[ido-fallback-command]\tFallback to non-ido version of current command. -\\[ido-toggle-regexp]\tToggle regexp searching. -\\[ido-toggle-prefix]\tToggle between substring and prefix matching. -\\[ido-toggle-case]\tToggle case-sensitive searching of buffer names. -\\[ido-completion-help]\tShow list of matching buffers in separate window. -\\[ido-enter-find-file]\tDrop into `ido-find-file'. -\\[ido-kill-buffer-at-head]\tKill buffer at head of buffer list. -\\[ido-toggle-ignore]\tToggle ignoring buffers listed in `ido-ignore-buffers'." - (interactive) - (ido-buffer-internal ido-default-buffer-method)) - -;;;###autoload -(defun ido-switch-buffer-other-window () - "Switch to another buffer and show it in another window. -The buffer name is selected interactively by typing a substring. -For details of keybindings, see `ido-switch-buffer'." - (interactive) - (ido-buffer-internal 'other-window 'switch-to-buffer-other-window)) - -;;;###autoload -(defun ido-display-buffer (&optional action) - "Display a buffer in another window but don't select it. - -If ACTION (the prefix argument interactively), display the buffer -in another windown even if it's already displayed in the current -window. - -The buffer name is selected interactively by typing a substring. -For details of keybindings, see `ido-switch-buffer'." - (interactive "P") - (ido-buffer-internal (if action - 'display-even-when-displayed - 'display) - 'display-buffer nil nil nil 'ignore)) - -;;;###autoload -(defun ido-display-buffer-other-frame () - "Display a buffer preferably in another frame. -The buffer name is selected interactively by typing a substring. -For details of keybindings, see `ido-switch-buffer'." - (interactive) - (ido-buffer-internal 'display-other-frame #'display-buffer-other-frame - nil nil nil #'ignore)) - -;;;###autoload -(defun ido-kill-buffer () - "Kill a buffer. -The buffer name is selected interactively by typing a substring. -For details of keybindings, see `ido-switch-buffer'." - (interactive) - (ido-buffer-internal 'kill 'kill-buffer "Kill buffer: " - (buffer-name (current-buffer)) nil 'ignore)) - -;;;###autoload -(defun ido-insert-buffer () - "Insert contents of a buffer in current buffer after point. -The buffer name is selected interactively by typing a substring. -For details of keybindings, see `ido-switch-buffer'." - (interactive) - (ido-buffer-internal 'insert 'insert-buffer "Insert buffer: " - nil nil 'ido-enter-insert-file)) - -;;;###autoload -(defun ido-switch-buffer-other-frame () - "Switch to another buffer and show it in another frame. -The buffer name is selected interactively by typing a substring. -For details of keybindings, see `ido-switch-buffer'." - (interactive) - (if ido-mode - (ido-buffer-internal 'other-frame) - (call-interactively 'switch-to-buffer-other-frame))) - -;;;###autoload -(defun ido-find-file-in-dir (dir) - "Switch to another file starting from DIR." - (interactive "DDir: ") - (setq dir (file-name-as-directory dir)) - (ido-file-internal ido-default-file-method nil dir nil nil nil 'ignore)) - -;;;###autoload -(defun ido-find-file () - "Edit file with name obtained via minibuffer. -The file is displayed according to `ido-default-file-method' -- the -default is to show it in the same window, unless it is already visible -in another frame. - -The file name is selected interactively by typing a substring. As you -type in a string, all of the filenames matching the string are displayed -if substring-matching is used (default). Look at `ido-enable-prefix' and -`ido-toggle-prefix'. When you have found the filename you want, it can -then be selected. As you type, most keys have their normal keybindings, -except for the following: \\ - -RET\tSelect the file at the front of the list of matches. -\tIf the list is empty, possibly prompt to create new file. - -\\[ido-select-text]\tUse the current input string verbatim. - -\\[ido-next-match]\tPut the first element at the end of the list. -\\[ido-prev-match]\tPut the last element at the start of the list. -\\[ido-complete]\tComplete a common suffix to the current string that matches -\tall files. If there is only one match, select that file. -\tIf there is no common suffix, show a list of all matching files -\tin a separate window. -\\[ido-magic-delete-char]\tOpen the specified directory in Dired mode. -\\[ido-edit-input]\tEdit input string (including directory). -\\[ido-prev-work-directory]\tGo to previous directory in work directory history. -\\[ido-next-work-directory]\tGo to next directory in work directory history. -\\[ido-merge-work-directories]\tSearch for file in the work directory history. -\\[ido-forget-work-directory]\tRemove current directory from the work directory history. -\\[ido-prev-work-file]\tCycle to previous file in work file history. -\\[ido-next-work-file]\tCycle to next file in work file history. -\\[ido-wide-find-file-or-pop-dir]\tPrompt for a file and use find to locate it. -\\[ido-wide-find-dir-or-delete-dir]\tPrompt for a directory and use find to locate it. -\\[ido-make-directory]\tPrompt for a directory to create in current directory. -\\[ido-fallback-command]\tFallback to non-Ido version of current command. -\\[ido-toggle-regexp]\tToggle regexp searching. -\\[ido-toggle-prefix]\tToggle between substring and prefix matching. -\\[ido-toggle-case]\tToggle case-sensitive searching of file names. -\\[ido-toggle-literal]\tToggle literal reading of this file. -\\[ido-completion-help]\tShow list of matching files in separate window. -\\[ido-toggle-ignore]\tToggle ignoring files listed in `ido-ignore-files'. -\\[ido-reread-directory]\tReread the current directory." - (interactive) - (ido-file-internal ido-default-file-method)) - -;;;###autoload -(defun ido-find-file-other-window () - "Switch to another file and show it in another window. -The file name is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (ido-file-internal 'other-window 'find-file-other-window)) - -;;;###autoload -(defun ido-find-alternate-file () - "Find another file, select its buffer, kill previous buffer. -The file name is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (ido-file-internal 'alt-file 'find-alternate-file nil "Find alternate file: ")) - -;;;###autoload -(defun ido-find-alternate-file-other-window () - "Find file as a replacement for the file in the next window. -The file name is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (ido-file-internal 'alt-file-other-window #'find-alternate-file-other-window)) - -;;;###autoload -(defun ido-find-file-read-only () - "Edit file read-only with name obtained via minibuffer. -The file name is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (ido-file-internal 'read-only 'find-file-read-only nil "Find file read-only: ")) - -;;;###autoload -(defun ido-find-file-read-only-other-window () - "Edit file read-only in other window with name obtained via minibuffer. -The file name is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (ido-file-internal 'read-only 'find-file-read-only-other-window nil - "Find file read-only other window: ")) - -;;;###autoload -(defun ido-find-file-read-only-other-frame () - "Edit file read-only in other frame with name obtained via minibuffer. -The file name is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (ido-file-internal 'read-only 'find-file-read-only-other-frame nil - "Find file read-only other frame: ")) - -;;;###autoload -(defun ido-display-file () - "Display a file in another window but don't select it. -The file name is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (ido-file-internal 'display nil nil nil nil nil 'ignore)) - -;;;###autoload -(defun ido-find-file-other-frame () - "Switch to another file and show it in another frame. -The file name is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (ido-file-internal 'other-frame 'find-file-other-frame)) - -;;;###autoload -(defun ido-write-file () - "Write current buffer to a file. -The file name is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (let ((ido-process-ignore-lists t) - (ido-work-directory-match-only nil) - (ido-ignore-files (cons "[^/]\\'" ido-ignore-files)) - (ido-report-no-match nil) - (ido-confirm-unique-completion t) - (ido-auto-merge-work-directories-length -1)) - (ido-file-internal 'write 'write-file nil "Write file: " nil nil 'ignore))) - -;;;###autoload -(defun ido-insert-file () - "Insert contents of file in current buffer. -The file name is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (ido-file-internal 'insert 'insert-file nil "Insert file: " nil nil 'ido-enter-insert-buffer)) - -;;;###autoload -(defun ido-dired () - "Call `dired' the Ido way. -The directory is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (let ((ido-report-no-match nil) - (ido-auto-merge-work-directories-length -1)) - (ido-file-internal 'dired 'dired nil "Dired: " 'dir))) - -;;;###autoload -(defun ido-dired-other-window () - "\"Edit\" a directory. Like `ido-dired' but select in another window. -The directory is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (let ((ido-report-no-match nil) - (ido-auto-merge-work-directories-length -1)) - (ido-file-internal 'dired-other-window #'dired-other-window nil - "Dired: " 'dir))) - -;;;###autoload -(defun ido-dired-other-frame () - "\"Edit\" a directory. Like `ido-dired' but make a new frame. -The directory is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (let ((ido-report-no-match nil) - (ido-auto-merge-work-directories-length -1)) - (ido-file-internal 'dired-other-frame #'dired-other-frame nil - "Dired: " 'dir))) - -(defun ido-list-directory () - "Call `list-directory' the Ido way. -The directory is selected interactively by typing a substring. -For details of keybindings, see `ido-find-file'." - (interactive) - (let ((ido-report-no-match nil) - (ido-auto-merge-work-directories-length -1)) - (ido-file-internal 'list-directory 'list-directory nil "List directory: " 'dir))) - -;;; XEmacs hack for showing default buffer - -;; The first time we enter the minibuffer, Emacs puts up the default -;; buffer to switch to, but XEmacs doesn't -- presumably there is a -;; subtle difference in the two versions of post-command-hook. The -;; default is shown for both whenever we delete all of our text -;; though, indicating its just a problem the first time we enter the -;; function. To solve this, we use another entry hook for emacs to -;; show the default the first time we enter the minibuffer. - - -;;; ICOMPLETE TYPE CODE - -(defun ido-initiate-auto-merge (buffer) - (ido-trace "\n*merge timeout*" buffer) - (setq ido-auto-merge-timer nil) - (when (and (buffer-live-p buffer) - (ido-active) - (boundp 'ido-eoinput) ido-eoinput) - (let ((contents (buffer-substring-no-properties (minibuffer-prompt-end) ido-eoinput))) - (ido-trace "request merge") - (setq ido-use-merged-list 'auto - ido-text-init contents - ido-rotate-temp t - ido-exit 'refresh) - (with-current-buffer buffer - (ido-tidy)) - (throw 'ido contents)))) - -(defun ido-exhibit () - "Post command hook for Ido." - ;; Find matching files and display a list in the minibuffer. - ;; Copied from `icomplete-exhibit' with two changes: - ;; 1. It prints a default file name when there is no text yet entered. - ;; 2. It calls my completion routine rather than the standard completion. - - (when (ido-active) - (let ((contents (buffer-substring-no-properties (minibuffer-prompt-end) (point-max))) - (buffer-undo-list t) - try-single-dir-match - refresh) - - (when ido-trace-enable - (ido-trace "\nexhibit" this-command) - (ido-trace "dir" ido-current-directory) - (ido-trace "contents" contents) - (ido-trace "list" ido-cur-list) - (ido-trace "matches" ido-matches) - (ido-trace "rescan" ido-rescan)) - - (save-excursion - (goto-char (point-max)) - ;; Register the end of input, so we know where the extra stuff (match-status info) begins: - (unless (boundp 'ido-eoinput) - ;; In case it got wiped out by major mode business: - (make-local-variable 'ido-eoinput)) - (setq ido-eoinput (point)) - - ;; Handle explicit directory changes - (cond - ((memq ido-cur-item '(buffer list)) - ) - - ((= (length contents) 0) - ) - - ((= (length contents) 1) - (cond - ((and (ido-is-tramp-root) (string-equal contents "/")) - (ido-set-current-directory ido-current-directory contents) - (setq refresh t)) - ((and (ido-unc-hosts) (string-equal contents "/") - (let ((ido-enable-tramp-completion nil)) - (ido-is-root-directory))) - (ido-set-current-directory "//") - (setq refresh t)) - )) - - ((and (string-match (if ido-enable-tramp-completion ".[:@]\\'" ".:\\'") contents) - (ido-is-root-directory) ;; Ange-ftp or tramp - (not (ido-local-file-exists-p contents))) - (ido-set-current-directory ido-current-directory contents) - (when (ido-is-slow-ftp-host) - (setq ido-exit 'fallback) - (exit-minibuffer)) - (setq refresh t)) - - ((ido-final-slash contents) ;; xxx/ - (ido-trace "final slash" contents) - (cond - ((string-equal contents "~/") - (ido-set-current-home) - (setq refresh t)) - ((string-equal contents "../") - (ido-up-directory t) - (setq refresh t)) - ((string-equal contents "./") - (setq refresh t)) - ((string-match "\\`~[-_a-zA-Z0-9]+[$]?/\\'" contents) - (ido-trace "new home" contents) - (ido-set-current-home contents) - (setq refresh t)) - ((string-match "[$][A-Za-z0-9_]+/\\'" contents) - (let ((exp (condition-case () - (expand-file-name - (substitute-in-file-name (substring contents 0 -1)) - ido-current-directory) - (error nil)))) - (ido-trace contents exp) - (when (and exp (file-directory-p exp)) - (ido-set-current-directory (file-name-directory exp)) - (setq ido-text-init (file-name-nondirectory exp)) - (setq refresh t)))) - ((and (memq system-type '(windows-nt ms-dos)) - (string-equal (substring contents 1) ":/")) - (ido-set-current-directory (file-name-directory contents)) - (setq refresh t)) - ((string-equal (substring contents -2 -1) "/") - (ido-set-current-directory - (if (memq system-type '(windows-nt ms-dos)) - (expand-file-name "/" ido-current-directory) - "/")) - (setq refresh t)) - ((and (or ido-directory-nonreadable ido-directory-too-big) - (file-directory-p (concat ido-current-directory (file-name-directory contents)))) - (ido-set-current-directory - (concat ido-current-directory (file-name-directory contents))) - (setq refresh t)) - (t - (ido-trace "try single dir") - (setq try-single-dir-match t)))) - - ((and (string-equal (substring contents -2 -1) "/") - (not (string-search "$" contents))) - (ido-set-current-directory - (cond - ((= (length contents) 2) - "/") - (ido-matches - (concat ido-current-directory (ido-name (car ido-matches)))) - (t - (concat ido-current-directory (substring contents 0 -1))))) - (setq ido-text-init (substring contents -1)) - (setq refresh t)) - - ((and (not ido-use-merged-list) - (not (ido-final-slash contents)) - (eq ido-try-merged-list t) - (numberp ido-auto-merge-work-directories-length) - (> ido-auto-merge-work-directories-length 0) - (= (length contents) ido-auto-merge-work-directories-length) - (not (and ido-auto-merge-inhibit-characters-regexp - (string-match ido-auto-merge-inhibit-characters-regexp contents))) - (not (input-pending-p))) - (setq ido-use-merged-list 'auto - ido-text-init contents - ido-rotate-temp t) - (setq refresh t)) - - (t nil)) - - (when refresh - (ido-trace "refresh on /" ido-text-init) - (setq ido-exit 'refresh) - (exit-minibuffer)) - - (when (and ido-enter-matching-directory - ido-matches - (or (eq ido-enter-matching-directory 'first) - (null (cdr ido-matches))) - (ido-final-slash (ido-name (car ido-matches))) - (or try-single-dir-match - (eq ido-enter-matching-directory t))) - (ido-trace "single match" (car ido-matches)) - (ido-set-current-directory - (concat ido-current-directory (ido-name (car ido-matches)))) - (setq ido-exit 'refresh) - (exit-minibuffer)) - - ;; Update the list of matches - (setq ido-text contents) - (ido-set-matches) - (ido-trace "new " ido-matches) - - (when (and (boundp 'ido-enable-virtual-buffers) - (not (eq ido-enable-virtual-buffers 'always)) - (eq ido-cur-item 'buffer) - (eq ido-use-virtual-buffers 'auto)) - - (when (and (not ido-enable-virtual-buffers) - (not ido-matches)) - (setq ido-text-init ido-text) - (setq ido-enable-virtual-buffers t) - (setq ido-exit 'refresh) - (exit-minibuffer)) - - ;; If input matches real buffers turn off virtual buffers. - (when (and ido-enable-virtual-buffers - ido-matches - (ido-set-matches-1 (ido-make-buffer-list-1))) - (setq ido-enable-virtual-buffers nil) - (setq ido-text-init ido-text) - (setq ido-exit 'refresh) - (exit-minibuffer))) - - (when (and (not ido-matches) - (not ido-directory-nonreadable) - (not ido-directory-too-big) - ;; ido-rescan ? - ido-process-ignore-lists - ido-ignored-list) - (let ((ido-process-ignore-lists nil) - (ido-rotate ido-rotate) - (ido-cur-list ido-ignored-list)) - (ido-trace "try all" ido-ignored-list) - (ido-set-matches)) - (when ido-matches - (ido-trace "found " ido-matches) - (setq ido-rescan t) - (setq ido-process-ignore-lists-inhibit t) - (setq ido-text-init ido-text) - (setq ido-exit 'refresh) - (exit-minibuffer))) - - (when (and - ido-rescan - (not ido-matches) - (memq ido-cur-item '(file dir)) - (not (ido-is-root-directory)) - (> (length contents) 1) - (not (string-search "$" contents)) - (not ido-directory-nonreadable) - (not ido-directory-too-big)) - (ido-trace "merge?") - (if ido-use-merged-list - (ido-undo-merge-work-directory contents nil) - (when (and (eq ido-try-merged-list t) - (numberp ido-auto-merge-work-directories-length) - (= ido-auto-merge-work-directories-length 0) - (not (and ido-auto-merge-inhibit-characters-regexp - (string-match ido-auto-merge-inhibit-characters-regexp contents))) - (not (input-pending-p))) - (ido-trace "\n*start timer*") - (setq ido-auto-merge-timer - (run-with-timer ido-auto-merge-delay-time nil - #'ido-initiate-auto-merge - (current-buffer)))))) - - (setq ido-rescan t) - - (if (and ido-use-merged-list - ido-matches - (not (string-equal (car (cdr (car ido-matches))) ido-current-directory))) - (progn - (ido-set-current-directory (car (cdr (car ido-matches)))) - (setq ido-use-merged-list t - ido-exit 'keep - ido-text-init ido-text) - (exit-minibuffer))) - - ;; Insert the match-status information: - (ido-set-common-completion) - (let ((inf (ido-completions contents))) - (setq ido-show-confirm-message nil) - (ido-trace "inf" inf) - (let ((pos (point))) - (insert inf) - (if (< pos (point-max)) - ;; Tell set-minibuffer-message where to display the - ;; overlay with temporary messages. - (put-text-property pos (1+ pos) 'minibuffer-message t))) - ) - )))) - -(defun ido-completions (name) - "Return the string that is displayed after the user's text. -Modified from `icomplete-completions'." - (let* ((comps ido-matches) - (ind (and (consp (car comps)) (> (length (cdr (car comps))) 1) - ido-merged-indicator)) - first) - - (if (and ind ido-use-faces) - (put-text-property 0 1 'face 'ido-indicator ind)) - - (if (and ido-use-faces comps) - (let* ((fn (ido-name (car comps))) - (ln (length fn))) - (setq first (copy-sequence fn)) - (put-text-property 0 ln 'face - (if (= (length comps) 1) - (if ido-incomplete-regexp - 'ido-incomplete-regexp - 'ido-only-match) - 'ido-first-match) - first) - (if ind (setq first (concat first ind))) - (setq comps (cons first (cdr comps))))) - - (cond ((null comps) - (cond - (ido-show-confirm-message - (or (nth 10 ido-decorations) " [Confirm]")) - (ido-directory-nonreadable - (or (nth 8 ido-decorations) " [Not readable]")) - (ido-directory-too-big - (or (nth 9 ido-decorations) " [Too big]")) - (ido-report-no-match - (nth 6 ido-decorations)) ;; [No match] - (t ""))) - (ido-incomplete-regexp - (concat " " (car comps))) - ((null (cdr comps)) ;one match - (concat (if (if (not ido-enable-regexp) - (= (length (ido-name (car comps))) (length name)) - ;; We can't rely on the length of the input - ;; for regexps, so explicitly check for a - ;; complete match - (string-match name (ido-name (car comps))) - (string-equal (match-string 0 (ido-name (car comps))) - (ido-name (car comps)))) - "" - ;; When there is only one match, show the matching file - ;; name in full, wrapped in [ ... ]. - (concat - (or (nth 11 ido-decorations) (nth 4 ido-decorations)) - (ido-name (car comps)) - (or (nth 12 ido-decorations) (nth 5 ido-decorations)))) - (if (not ido-use-faces) (nth 7 ido-decorations)))) ;; [Matched] - (t ;multiple matches - (let* ((items (if (> ido-max-prospects 0) (1+ ido-max-prospects) 999)) - (alternatives - (apply - #'concat - (cdr (apply - #'nconc - (mapcar - (lambda (com) - (setq com (ido-name com)) - (setq items (1- items)) - (cond - ((< items 0) ()) - ((= items 0) (list (nth 3 ido-decorations))) ; " | ..." - (t - (list (or ido-separator (nth 2 ido-decorations)) ; " | " - (let ((str (substring com 0))) - (if (and ido-use-faces - (not (string= str first)) - (ido-final-slash str)) - (put-text-property 0 (length str) 'face 'ido-subdir str)) - str))))) - comps)))))) - - (concat - ;; put in common completion item -- what you get by pressing tab - (if (and (stringp ido-common-match-string) - (> (length ido-common-match-string) (length name))) - (concat (nth 4 ido-decorations) ;; [ ... ] - (substring ido-common-match-string (length name)) - (nth 5 ido-decorations))) - ;; list all alternatives - (nth 0 ido-decorations) ;; { ... } - alternatives - (nth 1 ido-decorations))))))) - -(defun ido-minibuffer-setup () - "Minibuffer setup hook for Ido." - ;; Copied from `icomplete-minibuffer-setup-hook'. - (when (ido-active) - (add-hook 'pre-command-hook #'ido-tidy nil t) - (add-hook 'post-command-hook #'ido-exhibit nil t) - (run-hooks 'ido-minibuffer-setup-hook) - (when ido-initial-position - (goto-char (+ (minibuffer-prompt-end) ido-initial-position)) - (setq ido-initial-position nil)))) - -(defun ido-tidy () - "Pre command hook for Ido." - ;; Remove completions display, if any, prior to new user input. - ;; Copied from `icomplete-tidy'." - - (when ido-auto-merge-timer - (ido-trace "\n*cancel timer*" this-command) - (cancel-timer ido-auto-merge-timer) - (setq ido-auto-merge-timer nil)) - - (when (ido-active) - (if (bound-and-true-p ido-eoinput) - (if (> ido-eoinput (point-max)) - ;; Oops, got rug pulled out from under us - reinit: - (setq ido-eoinput (point-max)) - (let ((inhibit-read-only t) - (buffer-undo-list t)) - (delete-region ido-eoinput (point-max)))) - - ;; Reestablish the local variable 'cause minibuffer-setup is weird: - (setq-local ido-eoinput 1)))) - -(defun ido-summary-buffers-to-end () - ;; Move the summaries to the end of the buffer list. - ;; This is an example function which can be hooked on to - ;; `ido-make-buffer-list-hook'. Any buffer matching the regexps - ;; `Summary' or `output\*$'are put to the end of the list. - (let ((summaries (delq nil (mapcar - (lambda (x) - (if (or - (string-match "Summary" x) - (string-match "output\\*\\'" x)) - x)) - ido-temp-list)))) - (ido-to-end summaries))) - -;;; Helper functions for other programs - -(put 'ibuffer-find-file 'ido 'find-file) -(put 'dired 'ido 'dir) -(put 'dired-other-window 'ido 'dir) -(put 'dired-other-frame 'ido 'dir) -;; See https://debbugs.gnu.org/11954 for reasons. -(put 'dired-do-copy 'ido 'ignore) -(put 'dired-do-rename 'ido 'ignore) - -;;;###autoload -(defun ido-read-buffer (prompt &optional default require-match predicate) - "Ido replacement for the built-in `read-buffer'. -Return the name of a buffer selected. -PROMPT is the prompt to give to the user. DEFAULT if given is the default -buffer to be selected, which will go to the front of the list. -If REQUIRE-MATCH is non-nil, an existing buffer must be selected. -Optional arg PREDICATE if non-nil is a function limiting the -buffers that can be considered." - (let* ((ido-current-directory nil) - (ido-directory-nonreadable nil) - (ido-directory-too-big nil) - (ido-predicate predicate) - (ido-context-switch-command 'ignore) - (buf (ido-read-internal 'buffer prompt 'ido-buffer-history default require-match))) - (if (eq ido-exit 'fallback) - (let ((read-buffer-function nil)) - (run-hook-with-args 'ido-before-fallback-functions 'read-buffer) - (read-buffer prompt default require-match predicate)) - buf))) - -;;;###autoload -(defun ido-read-file-name (prompt &optional dir default-filename mustmatch initial predicate) - "Ido replacement for the built-in `read-file-name'. -Read file name, prompting with PROMPT and completing in directory DIR. -See `read-file-name' for additional parameters." - (let (filename) - (cond - ((and (not (memq this-command ido-read-file-name-non-ido)) - (or (eq predicate 'file-directory-p) - (eq (and (symbolp this-command) - (get this-command 'ido)) - 'dir) - (memq this-command ido-read-file-name-as-directory-commands))) - (setq filename - (ido-read-directory-name prompt dir default-filename mustmatch initial))) - ((and (not (eq (and (symbolp this-command) - (get this-command 'ido)) 'ignore)) - (not (memq this-command ido-read-file-name-non-ido)) - (or (null predicate) (eq predicate 'file-exists-p))) - (let* (ido-saved-vc-hb - (ido-context-switch-command - (if (eq (and (symbolp this-command) - (get this-command 'ido)) 'find-file) - nil 'ignore)) - (vc-handled-backends (and (boundp 'vc-handled-backends) vc-handled-backends)) - (ido-current-directory (ido-expand-directory dir)) - (ido-directory-nonreadable (not (file-readable-p ido-current-directory))) - (ido-directory-too-big (and (not ido-directory-nonreadable) - (ido-directory-too-big-p ido-current-directory))) - (ido-work-directory-index -1) - (ido-show-dot-for-dired (and ido-show-dot-for-dired - (not default-filename))) - (ido-work-file-index -1) - (ido-find-literal nil)) - (setq ido-exit nil) - (setq filename - (ido-read-internal 'file prompt 'ido-file-history - (cond ; Bug#11861. - ((stringp default-filename) default-filename) - ((consp default-filename) (car default-filename)) - ((and (not default-filename) initial) - (expand-file-name initial dir)) - (buffer-file-name buffer-file-name)) - mustmatch initial)) - (setq dir ido-current-directory) ; See bug#1516. - (cond - ((eq ido-exit 'fallback) - (setq filename 'fallback)) - ((eq ido-exit 'dired) - (setq filename ido-current-directory)) - (filename - (setq filename - (concat ido-current-directory filename)))))) - (t - (setq filename 'fallback))) - (if (eq filename 'fallback) - (let ((read-file-name-function nil)) - (run-hook-with-args 'ido-before-fallback-functions 'read-file-name) - (read-file-name prompt dir default-filename mustmatch initial predicate)) - filename))) - -;;;###autoload -(defun ido-read-directory-name (prompt &optional dir default-dirname mustmatch initial) - "Ido replacement for the built-in `read-directory-name'. -Read directory name, prompting with PROMPT and completing in directory DIR. -See `read-directory-name' for additional parameters." - (let* (filename - (ido-context-switch-command 'ignore) - ido-saved-vc-hb - (ido-current-directory (ido-expand-directory dir)) - (ido-directory-nonreadable (not (file-readable-p ido-current-directory))) - (ido-directory-too-big (and (not ido-directory-nonreadable) - (ido-directory-too-big-p ido-current-directory))) - (ido-work-directory-index -1) - (ido-work-file-index -1)) - (setq filename (ido-read-internal - 'dir prompt 'ido-file-history - (or default-dirname ; Bug#11861. - (if initial - (expand-file-name initial ido-current-directory) - ido-current-directory)) - mustmatch initial)) - (cond - ((eq ido-exit 'fallback) - (let ((read-file-name-function nil)) - (run-hook-with-args 'ido-before-fallback-functions 'read-directory-name) - (read-directory-name prompt ido-current-directory - default-dirname mustmatch initial))) - ((equal filename ".") ido-current-directory) - (t (concat ido-current-directory filename))))) - -;;;###autoload -(defun ido-completing-read (prompt choices &optional _predicate require-match - initial-input hist def _inherit-input-method) - "Ido replacement for the built-in `completing-read'. -Read a string in the minibuffer with Ido-style completion. -PROMPT is a string to prompt with; normally it ends in a colon and a space. -CHOICES is a list of strings which are the possible completions. -PREDICATE and INHERIT-INPUT-METHOD are currently ignored; they are included - to be compatible with `completing-read'. -If REQUIRE-MATCH is non-nil, the user is not allowed to exit unless - the input is (or completes to) an element of CHOICES or is null. - If the input is null, `ido-completing-read' returns DEF, or an empty - string if DEF is nil, regardless of the value of REQUIRE-MATCH. -If INITIAL-INPUT is non-nil, insert it in the minibuffer initially, - with point positioned at the end. -HIST, if non-nil, specifies a history list. -DEF, if non-nil, is the default value." - (let ((ido-current-directory nil) - (ido-directory-nonreadable nil) - (ido-directory-too-big nil) - (ido-context-switch-command 'ignore) - (ido-choice-list choices)) - ;; Initialize ido before invoking ido-read-internal - (ido-common-initialization) - (ido-read-internal 'list prompt hist def require-match initial-input))) - -(defun ido-unload-function () - "Unload the Ido library." - (ido-mode -1) - (setq minor-mode-map-alist (assq-delete-all 'ido-mode minor-mode-map-alist)) - ;; continue standard unloading - nil) - -(provide 'ido) - -;;; ido.el ends here diff --git a/lisp/misearch.el b/lisp/misearch.el index 5d41ae5fc15..2d8220a564e 100644 --- a/lisp/misearch.el +++ b/lisp/misearch.el @@ -237,20 +237,16 @@ set in `multi-isearch-buffers' or `multi-isearch-buffers-regexp'." (car buffers) (cadr (member buffer buffers))))) -(defvar ido-ignore-item-temp-list) ; from ido.el - (defun multi-isearch-read-buffers () "Return a list of buffers specified interactively, one by one." ;; Most code from `multi-occur'. (let* ((bufs (list (read-buffer "First buffer to search: " (current-buffer) t))) - (buf nil) - (ido-ignore-item-temp-list bufs)) + (buf nil)) (while (not (string-equal (setq buf (read-buffer (multi-occur--prompt) nil t)) "")) - (cl-pushnew buf bufs :test #'equal) - (setq ido-ignore-item-temp-list bufs)) + (cl-pushnew buf bufs :test #'equal)) (nreverse bufs))) (defun multi-isearch-read-matching-buffers () diff --git a/lisp/net/tramp-integration.el b/lisp/net/tramp-integration.el index 54bd71cba0b..a3f619c5925 100644 --- a/lisp/net/tramp-integration.el +++ b/lisp/net/tramp-integration.el @@ -47,7 +47,6 @@ (declare-function tramp-set-connection-local-variables-for-buffer "tramp") (declare-function tramp-tramp-file-p "tramp") (defvar eshell-path-env) -(defvar ido-read-file-name-non-ido) (defvar info-lookup-alist) (defvar ivy-completing-read-handlers-alist) (defvar recentf-exclude) @@ -188,18 +187,6 @@ NAME must be equal to `tramp-current-connection'." (remove-hook 'tramp-cleanup-all-connections-hook #'tramp-recentf-cleanup-all)))) -;;; Integration of ido.el: - -(with-eval-after-load 'ido - (add-to-list 'ido-read-file-name-non-ido #'tramp-rename-files) - (add-to-list 'ido-read-file-name-non-ido #'tramp-rename-these-files) - (add-hook 'tramp-integration-unload-hook - (lambda () - (setq ido-read-file-name-non-ido - (delq #'tramp-rename-these-files ido-read-file-name-non-ido) - ido-read-file-name-non-ido - (delq #'tramp-rename-files ido-read-file-name-non-ido))))) - ;;; Integration of ivy.el: (with-eval-after-load 'ivy diff --git a/lisp/replace.el b/lisp/replace.el index 73c3b523382..2d60dcae939 100644 --- a/lisp/replace.el +++ b/lisp/replace.el @@ -1824,21 +1824,6 @@ is not modified." (list ol))))) (occur-1 regexp nlines bufs))) -(defvar ido-ignore-item-temp-list) - -(defun multi-occur--prompt () - (concat - "Next buffer to search " - (cond - ((or (eq read-buffer-function #'ido-read-buffer) - (bound-and-true-p ido-everywhere)) - (substitute-command-keys - "(\\\\[ido-select-text] to end): ")) - ((bound-and-true-p fido-mode) - (substitute-command-keys - "(\\\\[icomplete-fido-exit] to end): ")) - (t "(RET to end): ")))) - (defun multi-occur (bufs regexp &optional nlines) "Show all lines in buffers BUFS containing a match for REGEXP. Optional argument NLINES specifies the number of context lines to show @@ -1849,15 +1834,12 @@ the buffer names that you want, one by one. See also `multi-occur-in-matching-buffers'." (interactive (cons - (let* ((bufs (list (read-buffer "First buffer to search: " - (current-buffer) t))) - (buf nil) - (ido-ignore-item-temp-list bufs)) + (let* ((bufs (list (read-buffer "First buffer to search: " (current-buffer) t))) + (buf nil)) (while (not (string-equal - (setq buf (read-buffer (multi-occur--prompt) nil t)) + (setq buf (read-buffer "Next buffer to search (RET to end): " nil t)) "")) - (cl-pushnew buf bufs) - (setq ido-ignore-item-temp-list bufs)) + (cl-pushnew buf bufs)) (nreverse (mapcar #'get-buffer bufs))) (occur-read-primary-args))) (occur-1 regexp nlines bufs)) diff --git a/test/lisp/ido-tests.el b/test/lisp/ido-tests.el deleted file mode 100644 index f5c85fc0621..00000000000 --- a/test/lisp/ido-tests.el +++ /dev/null @@ -1,54 +0,0 @@ -;;; ido-tests.el --- unit tests for ido.el -*- lexical-binding: t; -*- - -;; Copyright (C) 2017-2025 Free Software Foundation, Inc. - -;; Author: Philipp Stephani - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software: you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs. If not, see . - -;;; Commentary: - -;; Unit tests for ido.el. - -;;; Code: - -(require 'ido) - -(ert-deftest ido-tests--other-window-frame () - "Verifies that Bug#26360 is fixed." - (should-not ido-mode) - (unwind-protect - (progn - (ido-mode) - (should (equal ido-mode 'both)) - (should (equal (key-binding [remap find-alternate-file-other-window]) - #'ido-find-alternate-file-other-window)) - (should (commandp #'ido-find-alternate-file-other-window)) - (should (equal (key-binding (kbd "C-x 4 d")) #'ido-dired-other-window)) - (should (commandp #'ido-dired-other-window)) - (should (equal (key-binding (kbd "C-x 5 d")) #'ido-dired-other-frame)) - (should (commandp #'ido-dired-other-frame)) - (should (equal (key-binding (kbd "C-x 5 C-o")) - #'ido-display-buffer-other-frame)) - (should (commandp #'ido-display-buffer-other-frame))) - (ido-mode 0))) - -(ert-deftest ido-directory-too-big-p () - (should-not (ido-directory-too-big-p "/some/dir/")) - (let ((ido-big-directories (cons (rx "me/di") ido-big-directories))) - (should (ido-directory-too-big-p "/some/dir/")))) - -;;; ido-tests.el ends here -- 2.39.5