;;; ido.el --- interactively do things with buffers and files.
-;; Copyright (C) 1996-2004 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+;; 2004, 2005, 2006 Free Software Foundation, Inc.
;; Author: Kim F. Storm <storm@cua.dk>
;; Based on: iswitchb by Stephen Eglen <stephen@cns.ed.ac.uk>
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
-
-;;; Acknowledgements
-
-;; Infinite amounts of gratitude goes to Stephen Eglen <stephen@cns.ed.ac.uk>
-;; 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 ackward 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 21.5 to use command remapping
-;; and optionally hooking the read-buffer and read-file-name functions.
-;;
-;; Prefix matching was added by Klaus Berndl <klaus.berndl@sdm.de> based on
-;; an idea of Yuji Minejima <ggb01164@nifty.ne.jp> and his mcomplete-package.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; most recent, when I use ido-switch-buffer, I first of all get
;; presented with the list of all the buffers
;;
-;; Buffer: {123456,123}
+;; Buffer: {123456 | 123}
;;
;; If I then press 2:
-;; Buffer: 2[3]{123456,123}
+;; 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 bring the put the first
-;; element at the end of the list by pressing C-s or [right], or put
-;; the last element at the head of the list by pressing C-r or [left].
+;; 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}
+;; 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
;; top of the list and then RET to select it.
;;
;; However, if I type 4, I only have one match left:
-;; Buffer: 234[123456] [Matched]
+;; Buffer: 234[123456]
;;
-;; Since there is only one matching buffer left, it is given in [] and we
-;; see the text [Matched] afterwards. I can now press TAB or RET to go
-;; to that buffer.
+;; 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 however, I now type "a":
+;; 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".
;; 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. This
-;; is the only difference between the substring and prefix matching.
+;; not match because "2" is not a PREFIX in any of the buffer-names.
;; Flexible matching
;; -----------------
;;
;; There is limited provision for regexp matching within ido,
;; enabled through `ido-enable-regexp' (toggle with C-t).
-;; This allows you to type `c$' for example and see all file names
-;; ending in `c'. This facility is quite limited though in two
-;; respects. First, you can't currently type in expressions like
-;; `[0-9]' directly -- you have to type them in when ido-enable-regexp
-;; is nil and then toggle on the regexp functionality. Likewise,
-;; don't enter an expression containing `\' in regexp mode. If you
-;; try, ido gets confused, so just hit C-g and try again. Secondly,
-;; no completion mechanism is currently offered with regexp searching.
+;; 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 the hook provided. For example:
-;;(add-hook 'ido-define-mode-map-hook 'ido-my-keys)
+;; To modify the keybindings, use the ido-setup-hook. For example:
+;;(add-hook 'ido-setup-hook 'ido-my-keys)
;;
;;(defun ido-my-keys ()
;; "Add my keybindings for ido."
-;; (define-key ido-mode-map " " 'ido-next-match)
+;; (define-key ido-completion-map " " 'ido-next-match)
;; )
;; Seeing all the matching buffers or files
;; ------------
;; The highlighting of matching items is controlled via ido-use-faces.
-;; The faces used are ido-first-match-face, ido-only-match-face and
-;; ido-subdir-face.
+;; The faces used are ido-first-match, ido-only-match and
+;; ido-subdir.
;; Colouring of the matching item was suggested by
;; Carsten Dominik (dominik@strw.leidenuniv.nl).
;; can be used by other packages to read a buffer name, a file name,
;; or a directory name in the `ido' way.
+;;; Acknowledgements
+
+;; Infinite amounts of gratitude goes to Stephen Eglen <stephen@cns.ed.ac.uk>
+;; 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 ackward 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 <klaus.berndl@sdm.de> based on
+;; an idea of Yuji Minejima <ggb01164@nifty.ne.jp> and his mcomplete-package.
+
;;; Code:
(provide 'ido)
+(defvar cua-inhibit-cua-keys)
+
;;; User Variables
;;
;; These are some things you might want to change.
"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"))
;;;###autoload
(defcustom ido-mode nil
"Determines for which functional group \(buffer and files) ido behavior
-should be enabled. The following values are possible:
+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...)
use either \\[customize] or the function `ido-mode'."
:set #'(lambda (symbol value)
(ido-mode value))
- :initialize 'custom-initialize-default
+ :initialize 'custom-initialize-set
:require 'ido
:link '(emacs-commentary-link "ido.el")
- :set-after '(ido-save-directory-list-file)
- :version "21.4"
+ :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)
Setting this variable directly does not work. Use `customize' or
call the function `ido-everywhere'."
:set #'(lambda (symbol value)
- (ido-everywhere value))
+ (ido-everywhere (if value 1 -1)))
:initialize 'custom-initialize-default
:type 'boolean
:group 'ido)
:type 'boolean
:group 'ido)
+(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)))
+ :group 'ido)
+
(defcustom ido-ignore-directories
'("\\`CVS/" "\\`\\.\\./" "\\`\\./")
"*List of regexps or functions matching sub-directory names to ignore."
`otherframe' Show new file in another frame
`maybe-frame' If a file is visible in another frame, prompt to ask if you
you want to see the file in the same window of the current
- frame or in the other frame.
+ frame or in the other frame
`always-frame' If a file is visible in another frame, raise that
- frame. Otherwise, visit the file in the same window."
+ frame; otherwise, visit the file in the same window"
:type '(choice (const samewindow)
(const otherwindow)
(const display)
(defcustom ido-default-buffer-method 'always-frame
"*How to switch to new buffer when using `ido-switch-buffer'.
-See ido-default-file-method for details."
+See `ido-default-file-method' for details."
:type '(choice (const samewindow)
(const otherwindow)
(const display)
:group 'ido)
(defcustom ido-enable-prefix nil
- "*Nil means that `ido' will match if the inserted text is an
-arbitrary substring (default). If non-nil `ido' will only match if the inserted
-text is a prefix \(this behavior is like the standard unix- or
-emacs-completion works).
+ "*Non-nil means only match if the entered text is a prefix of file name.
+This behavior is like the standard emacs-completion.
+Nil means to match if the entered text is an arbitrary substring.
Value can be toggled within `ido' using `ido-toggle-prefix'."
:type 'boolean
:group 'ido)
+(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
+ :group 'ido)
+
(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]
(defcustom ido-max-prospects 12
"*Non-zero means that the prospect list will be limited to than number of items.
For a long list of prospects, building the full list for the minibuffer can take a
-non-negletable amount of time; setting this variable reduces that time."
+non-negligible amount of time; setting this variable reduces that time."
:type 'integer
:group 'ido)
(defcustom ido-use-filename-at-point nil
"*Non-nil means that ido shall look for a filename at point.
+May use `ffap-guesser' to guess whether text at point is a filename.
If found, use that as the starting point for filename selection."
- :type 'boolean
+ :type '(choice
+ (const :tag "Disabled" nil)
+ (const :tag "Guess filename" guess)
+ (other :tag "Use literal filename" t))
:group 'ido)
(defcustom ido-cache-ftp-work-directory-time 1.0
"*Maximum time to cache contents of an ftp directory (in hours).
+Use C-l in prompt to refresh list.
If zero, ftp directories are not cached."
:type 'number
:group 'ido)
(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."
+equivalent function, e.g. `find-file' rather than `ido-find-file'."
:type '(repeat string)
:group 'ido)
:type '(repeat regexp)
:group 'ido)
+(defvar ido-unc-hosts-cache t
+ "Cached value from `ido-unc-hosts' function.")
+
+(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))
+ :group 'ido)
+
+(defcustom ido-downcase-unc-hosts t
+ "*Non-nil if UNC host names should be downcased."
+ :type 'boolean
+ :group 'ido)
+
+(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)
+ :group 'ido)
+
+(defcustom ido-cache-unc-host-shares-time 8.0
+ "*Maximum time to cache shares of an UNC host (in hours).
+Use C-l in prompt to refresh list.
+If zero, UNC host shares are not cached."
+ :type 'number
+ :group 'ido)
+
(defcustom ido-max-work-file-list 10
"*Maximum number of names of recently opened files to record.
This is the list the file names (sans directory) which have most recently
-been opened. See `ido-work-file-list' and `ido-save-directory-list-file'."
+been opened. See `ido-work-file-list' and `ido-save-directory-list-file'."
:type 'integer
:group 'ido)
:type 'integer
:group 'ido)
+(defcustom ido-max-directory-size 30000
+ "*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 C-a."
+ :type '(choice (const :tag "No limit" nil)
+ (integer :tag "Size in bytes" 30000))
+ :group 'ido)
+
(defcustom ido-rotate-file-list-default nil
"*Non-nil means that `ido' will always rotate file list to get default in front."
:type 'boolean
:group 'ido)
-(defcustom ido-enter-single-matching-directory 'slash
- "*Automatically enter sub-directory if it is the only matching item, if non-nil.
-If value is 'slash, only enter if typing final slash, else do it always."
+(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 "When typing /" slash)
- (other :tag "Always" t))
+ (const :tag "Slash enters first directory" first)
+ (const :tag "Slash enters first and only directory" only)
+ (other :tag "Always enter unique directory" t))
:group 'ido)
(defcustom ido-create-new-buffer 'prompt
(const never))
:group 'ido)
-(defcustom ido-define-mode-map-hook nil
- "*Hook to define keys in `ido-mode-map' for extra keybindings."
+(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
:group 'ido)
:type '(choice string (const nil))
:group 'ido)
-(defcustom ido-decorations '( "{" "}" " | " " | ..." "[" "]" " [No match]" " [Matched]" " [Not readable]")
+(defcustom ido-decorations '( "{" "}" " | " " | ..." "[" "]" " [No match]" " [Matched]" " [Not readable]" " [Too big]")
"*List of strings used by ido to display the alternatives in the minibuffer.
-There are 9 elements in this list:
+There are 10 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 a 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."
+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'."
:type '(repeat string)
:group 'ido)
:type 'boolean
:group 'ido)
-(defface ido-first-match-face '((t (:bold t)))
+(defface ido-first-match '((t (:bold t)))
"*Font used by ido for highlighting first match."
:group 'ido)
-(defface ido-only-match-face '((((class color))
+(defface ido-only-match '((((class color))
(:foreground "ForestGreen"))
(t (:italic t)))
"*Font used by ido for highlighting only match."
:group 'ido)
-(defface ido-subdir-face '((((class color))
+(defface ido-subdir '((((min-colors 88) (class color))
+ (:foreground "red1"))
+ (((class color))
(:foreground "red"))
(t (:underline t)))
"*Font used by ido for highlighting subdirs in the alternatives."
:group 'ido)
-(defface ido-indicator-face '((((class color))
+(defface ido-indicator '((((min-colors 88) (class color))
+ (:foreground "yellow1"
+ :background "red1"
+ :width condensed))
+ (((class color))
(:foreground "yellow"
:background "red"
:width condensed))
"*Font used by ido for highlighting its indicators."
:group 'ido)
+(defface ido-incomplete-regexp
+ '((t
+ (:inherit font-lock-warning-face)))
+ "Ido face for indicating incomplete regexps."
+ :group 'ido)
+
(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
:group 'ido)
(defcustom ido-read-file-name-as-directory-commands '()
- "List of commands which uses read-file-name to read a directory name.
+ "List of commands which uses `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."
+the directory using `ido-read-directory-name'."
:type '(repeat symbol)
:group 'ido)
(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."
+the file name using normal `read-file-name' style."
:type '(repeat symbol)
:group 'ido)
+(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
+ :group 'ido)
+
;;; Internal Variables
;; Persistent variables
-(defvar ido-mode-map nil
- "Keymap for `ido-find-file' and `ido-switch-buffer'.")
+(defvar ido-completion-map nil
+ "Currently active keymap for ido commands.")
+
+(defvar ido-common-completion-map nil
+ "Keymap for all ido commands.")
+
+(defvar ido-file-completion-map nil
+ "Keymap for ido file commands.")
+
+(defvar ido-file-dir-completion-map nil
+ "Keymap for ido file and directory commands.")
+
+(defvar ido-buffer-completion-map nil
+ "Keymap for ido buffer commands.")
(defvar ido-file-history nil
"History of files selected using `ido-find-file'.")
(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.")
+file is opened with `ido-find-file' and family.")
(defvar ido-work-file-list nil
"List of actual work file names.
(defvar ido-ignore-item-temp-list nil
"List of items to ignore in current ido invocation.
-Intended to be let-bound by functions which calls ido repeatedly.
+Intended to be let-bound by functions which call ido repeatedly.
Should never be set permanently.")
;; Temporary storage
(defvar ido-text-init nil
"The initial string for the users string it is typed in.")
+(defvar ido-input-stack nil
+ "Stores the users 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.")
+ "Report [No Match] when no completions matches `ido-text'.")
(defvar ido-exit nil
"Flag to monitor how `ido-find-file' exits.
selected.")
(defvar ido-current-directory nil
- "Current directory for ido-find-file.")
+ "Current directory for `ido-find-file'.")
(defvar ido-auto-merge-timer nil
"Delay timer for auto merge.")
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.")
;;; Variables with dynamic bindings.
;;; Declared here to keep the byte compiler quiet.
-;; Stores the current ido item type ('file, 'dir or 'buffer).
+;; Stores the current ido item type ('file, 'dir, 'buffer, or 'list).
(defvar ido-cur-item)
;; Stores the current list of items that will be searched through.
;; 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)
;; 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)
;;; FUNCTIONS
(pop-to-buffer b t t)
(setq truncate-lines t)))))
+(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)
- (setq dir (or dir ido-current-directory))
(and ido-enable-tramp-completion
- (string-match "\\`/[^/][^/]+:\\([^/:@]+@\\)?\\'" dir)))
+ (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 (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
+ ((ido-directory-too-big-p dir)
+ nil)
((and (ido-is-root-directory dir)
(or ido-enable-tramp-completion
(memq system-type '(windows-nt ms-dos))))
nil)
- ((not (ido-is-ftp-directory dir))
- t)
- ((ido-cache-ftp-valid)
- t)))
+ ((ido-is-unc-host dir)
+ (ido-cache-unc-valid))
+ ((ido-is-ftp-directory dir)
+ (ido-cache-ftp-valid))
+ (t t)))
(defun ido-pp (list &optional sep)
(let ((print-level nil) (eval-expression-print-level nil)
(defun ido-save-history ()
"Save ido history and cache information between sessions."
(interactive)
- (if (and ido-last-directory-list ido-save-directory-list-file)
- (save-excursion
- (save-window-excursion
- (if (find-buffer-visiting ido-save-directory-list-file)
- (kill-buffer (find-buffer-visiting ido-save-directory-list-file)))
- (if (file-exists-p ido-save-directory-list-file)
- (delete-file ido-save-directory-list-file))
- (set-buffer (let ((enable-local-variables nil))
- (find-file-noselect ido-save-directory-list-file t)))
- (goto-char (point-min))
- (delete-region (point-min) (point-max))
- (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 ")
- (insert "\n")
- (let ((version-control 'never))
+ (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)
+ (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"))
+ (insert "\n")
(write-file ido-save-directory-list-file nil))
- (kill-buffer (current-buffer))))))
+ (kill-buffer buf)))))
(defun ido-load-history (&optional arg)
"Load ido history and cache information from previous session.
(let ((file (expand-file-name ido-save-directory-list-file))
buf)
(when (file-readable-p file)
- (save-excursion
- (save-window-excursion
- (setq buf (set-buffer (let ((enable-local-variables nil))
- (find-file-noselect file))))
- (goto-char (point-min))
- (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)))
- (error nil))))
- (kill-buffer buf))))
+ (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 ()
(and
(stringp dir)
(consp time)
- (if (integerp (car time))
- (and (/= (car time) 0)
- (integerp (car (cdr time)))
- (/= (car (cdr time)) 0)
- (ido-may-cache-directory dir))
- (and (eq (car time) 'ftp)
- (numberp (cdr time))
+ (cond
+ ((integerp (car time))
+ (and (/= (car time) 0)
+ (integerp (car (cdr time)))
+ (/= (car (cdr time)) 0)
+ (ido-may-cache-directory dir)))
+ ((eq (car time) 'ftp)
+ (and (numberp (cdr time))
(ido-is-ftp-directory dir)
(ido-cache-ftp-valid (cdr time))))
+ ((eq (car time) 'unc)
+ (and (numberp (cdr time))
+ (ido-is-unc-host dir)
+ (ido-cache-unc-valid (cdr time))))
+ (t nil))
(let ((s files) (ok t))
(while s
(if (stringp (car s))
(while e
(setq d (car e) e (cdr e))
(if (not (consp d))
- (set-text-properties 0 (length d) nil d))))))
-)
+ (set-text-properties 0 (length d) nil d)))))))
(defun ido-kill-emacs-hook ()
(t nil)))
(ido-everywhere (if ido-everywhere 1 -1))
+ (when ido-mode
+ (ido-init-completion-maps))
(when ido-mode
(add-hook 'minibuffer-setup-hook 'ido-minibuffer-setup)
(add-hook 'kill-emacs-hook 'ido-kill-emacs-hook)
- (unless ido-minor-mode-map-entry
- (setq ido-minor-mode-map-entry (cons 'ido-mode (make-sparse-keymap)))
- (add-to-list 'minor-mode-map-alist ido-minor-mode-map-entry))
-
- (let ((map (cdr ido-minor-mode-map-entry)))
+ (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 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] 'ido-display-buffer))
+
+ (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)))))
+
(defun ido-everywhere (arg)
- "Enable ido everywhere file and directory names are read."
+ "Toggle using ido speed-ups everywhere file and directory names are read.
+With ARG, turn ido speed-up on if arg is positive, off otherwise."
(interactive "P")
(setq ido-everywhere (if arg
(> (prefix-numeric-value arg) 0)
(not ido-everywhere)))
- (setq read-file-name-function
- (and ido-everywhere (memq ido-mode '(both file))
- 'ido-read-file-name))
- (setq read-buffer-function
- (and ido-everywhere (memq ido-mode '(both buffer))
- 'ido-read-buffer)))
+ (when (get 'ido-everywhere 'file)
+ (setq read-file-name-function (car (get 'ido-everywhere 'file)))
+ (put 'ido-everywhere 'file nil))
+ (when (get 'ido-everywhere 'buffer)
+ (setq read-buffer-function (car (get 'ido-everywhere 'buffer)))
+ (put 'ido-everywhere 'buffer nil))
+ (when ido-everywhere
+ (when (memq ido-mode '(both file))
+ (put 'ido-everywhere 'file (cons read-file-name-function nil))
+ (setq read-file-name-function 'ido-read-file-name))
+ (when (memq ido-mode '(both buffer))
+ (put 'ido-everywhere 'buffer (cons read-buffer-function nil))
+ (setq read-buffer-function 'ido-read-buffer))))
;;; IDO KEYMAP
-(defun ido-define-mode-map ()
- "Set up the keymap for `ido'."
- (let (map)
- ;; generated every time so that it can inherit new functions.
+(defun ido-init-completion-maps ()
+ "Set up the completion keymaps used by `ido'."
- (setq map (copy-keymap minibuffer-local-map))
+ ;; Common map
+ (let ((map (make-sparse-keymap)))
(define-key map "\C-a" 'ido-toggle-ignore)
(define-key map "\C-c" 'ido-toggle-case)
(define-key map "\C-e" 'ido-edit-input)
(define-key map "\C-s" 'ido-next-match)
(define-key map "\C-t" 'ido-toggle-regexp)
(define-key map "\C-z" 'ido-undo-merge-work-directory)
- (define-key map [(control ? )] 'ido-restrict-to-matches)
+ (define-key map [(control ?\s)] 'ido-restrict-to-matches)
(define-key map [(control ?@)] 'ido-restrict-to-matches)
(define-key map [right] 'ido-next-match)
(define-key map [left] 'ido-prev-match)
(define-key map "?" 'ido-completion-help)
+ ;; Magic commands.
+ (define-key map "\C-b" 'ido-magic-backward-char)
+ (define-key map "\C-f" 'ido-magic-forward-char)
+ (define-key map "\C-d" 'ido-magic-delete-char)
+ (set-keymap-parent map minibuffer-local-map)
+ (setq ido-common-completion-map map))
+
+ ;; File and directory map
+ (let ((map (make-sparse-keymap)))
+ (define-key map "\C-x\C-b" 'ido-enter-switch-buffer)
+ (define-key map "\C-x\C-f" 'ido-fallback-command)
+ (define-key map "\C-x\C-d" 'ido-enter-dired)
+ (define-key map [down] 'ido-next-match-dir)
+ (define-key map [up] 'ido-prev-match-dir)
+ (define-key map [(meta up)] 'ido-prev-work-directory)
+ (define-key map [(meta down)] 'ido-next-work-directory)
+ (define-key map [backspace] 'ido-delete-backward-updir)
+ (define-key map "\d" 'ido-delete-backward-updir)
+ (define-key map [(meta backspace)] 'ido-delete-backward-word-updir)
+ (define-key map [(control backspace)] 'ido-up-directory)
+ (define-key map "\C-l" 'ido-reread-directory)
+ (define-key map [(meta ?d)] 'ido-wide-find-dir-or-delete-dir)
+ (define-key map [(meta ?b)] 'ido-push-dir)
+ (define-key map [(meta ?f)] 'ido-wide-find-file-or-pop-dir)
+ (define-key map [(meta ?k)] 'ido-forget-work-directory)
+ (define-key map [(meta ?m)] 'ido-make-directory)
+ (define-key map [(meta ?n)] 'ido-next-work-directory)
+ (define-key map [(meta ?o)] 'ido-prev-work-file)
+ (define-key map [(meta control ?o)] 'ido-next-work-file)
+ (define-key map [(meta ?p)] 'ido-prev-work-directory)
+ (define-key map [(meta ?s)] 'ido-merge-work-directories)
+ (set-keymap-parent map ido-common-completion-map)
+ (setq ido-file-dir-completion-map map))
+
+ ;; File only map
+ (let ((map (make-sparse-keymap)))
+ (define-key map "\C-k" 'ido-delete-file-at-head)
+ (define-key map "\C-o" 'ido-copy-current-word)
+ (define-key map "\C-w" 'ido-copy-current-file-name)
+ (define-key map [(meta ?l)] 'ido-toggle-literal)
+ (define-key map "\C-v" 'ido-toggle-vc)
+ (set-keymap-parent map ido-file-dir-completion-map)
+ (setq ido-file-completion-map map))
+
+ ;; Buffer map
+ (let ((map (make-sparse-keymap)))
+ (define-key map "\C-x\C-f" 'ido-enter-find-file)
+ (define-key map "\C-x\C-b" 'ido-fallback-command)
+ (define-key map "\C-k" 'ido-kill-buffer-at-head)
+ (set-keymap-parent map ido-common-completion-map)
+ (setq ido-buffer-completion-map map)))
+
+
+(defun ido-setup-completion-map ()
+ "Set up the keymap for `ido'."
- (when (memq ido-cur-item '(file dir))
- (define-key map "\C-b" 'ido-enter-switch-buffer)
- (define-key map "\C-d" 'ido-enter-dired)
- (define-key map "\C-f" 'ido-fallback-command)
- (define-key map [down] 'ido-next-match-dir)
- (define-key map [up] 'ido-prev-match-dir)
- (define-key map [(meta up)] 'ido-prev-work-directory)
- (define-key map [(meta down)] 'ido-next-work-directory)
- (define-key map [backspace] 'ido-delete-backward-updir)
- (define-key map "\d" 'ido-delete-backward-updir)
- (define-key map [(meta backspace)] 'ido-delete-backward-word-updir)
- (define-key map [(control backspace)] 'ido-up-directory)
- (define-key map "\C-l" 'ido-reread-directory)
- (define-key map [(meta ?b)] 'ido-next-work-file)
- (define-key map [(meta ?d)] 'ido-wide-find-dir)
- (define-key map [(meta ?f)] 'ido-wide-find-file)
- (define-key map [(meta ?k)] 'ido-forget-work-directory)
- (define-key map [(meta ?m)] 'ido-make-directory)
- (define-key map [(meta ?n)] 'ido-next-work-directory)
- (define-key map [(meta ?o)] 'ido-prev-work-file)
- (define-key map [(meta ?p)] 'ido-prev-work-directory)
- (define-key map [(meta ?s)] 'ido-merge-work-directories)
- )
-
- (when (eq ido-cur-item 'file)
- (define-key map "\C-k" 'ido-delete-file-at-head)
- (define-key map "\C-o" 'ido-copy-current-word)
- (define-key map "\C-w" 'ido-copy-current-file-name)
- (define-key map [(meta ?l)] 'ido-toggle-literal)
- (define-key map "\C-v" 'ido-toggle-vc)
- )
+ ;; generated every time so that it can inherit new functions.
+ (let ((map (make-sparse-keymap))
+ (viper-p (if (boundp 'viper-mode) viper-mode)))
- (when (eq ido-cur-item 'buffer)
- (define-key map "\C-b" 'ido-fallback-command)
- (define-key map "\C-f" 'ido-enter-find-file)
- (define-key map "\C-k" 'ido-kill-buffer-at-head)
- )
+ (when viper-p
+ (define-key map [remap viper-intercept-ESC-key] 'ignore))
- (when (if (boundp 'viper-mode) viper-mode)
- (define-key map [remap viper-intercept-ESC-key] 'ignore)
- (when (memq ido-cur-item '(file dir))
+ (cond
+ ((memq ido-cur-item '(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)))
+ (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)))
- (setq ido-mode-map map)
- (run-hooks 'ido-define-mode-map-hook)))
+ ((eq ido-cur-item '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))
+
+ (t
+ (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.
;; connect on incomplete tramp paths (after entring 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 entring just method:).
+ (let ((ido-enable-tramp-completion nil))
+ (and (numberp ido-max-directory-size)
+ (ido-final-slash dir)
+ (not (ido-is-unc-host dir))
+ (file-directory-p dir)
+ (> (nth 7 (file-attributes 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
- (setq dir (ido-final-slash dir t))
+ (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))
- (if subdir
- (setq dir (ido-final-slash (concat dir subdir) t)))
- (if (equal dir ido-current-directory)
- nil
+ (when subdir
+ (setq dir (concat dir subdir))
+ (unless (and ido-enable-tramp-completion
+ (string-match "\\`/[^/]*@\\'" dir))
+ (setq dir (ido-final-slash dir t))))
+ (if (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)
(if (get-buffer ido-completion-buffer)
(kill-buffer ido-completion-buffer))
(setq ido-directory-nonreadable (ido-nonreadable-directory-p dir))
- t))
+ (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
;; the relevant function is called (find-file, write-file, etc).
(defun ido-read-internal (item prompt history &optional default require-match initial)
- "Perform the ido-read-buffer and ido-read-file-name functions.
+ "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 directory to start with.
(ido-enable-regexp ido-enable-regexp)
)
- (ido-define-mode-map)
+ (ido-setup-completion-map)
(setq ido-text-init 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)
(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)
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-rescan nil))
((eq ido-cur-item 'file)
(setq ido-ignored-list nil
- ido-cur-list (ido-make-file-list ido-default-item)))
+ 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 (ido-make-dir-list ido-default-item)))
+ 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 (and ido-matches (eq ido-try-merged-list 'auto))
(setq ido-try-merged-list t))
(let
- ((minibuffer-local-completion-map ido-mode-map)
+ ((minibuffer-local-completion-map ido-completion-map)
+ (minibuffer-local-filename-completion-map ido-completion-map)
(max-mini-window-height (or ido-max-window-height
(and (boundp 'max-mini-window-height) max-mini-window-height)))
(ido-completing-read t)
(setq ido-text-init "")
(while new
(setq new (if edit
- (read-file-name (concat prompt "[EDIT] ")
- (expand-file-name d)
- (concat d f) nil f)
+ (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)
(setq ido-text-init f
new nil))))))
(t
- (setq ido-text-init (read-string (concat prompt "[EDIT] ") ido-final-text))))
+ (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 findfile findbuffer))
+ ((memq ido-exit '(dired fallback find-file switch-to-buffer insert-buffer insert-file))
(setq done t))
- ((eq ido-exit 'updir)
+ ((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)
(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 (ido-existing-item-p)))
+ ((and require-match
+ (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
(ido-name (car ido-matches))))
(cond
- ((eq item 'buffer)
+ ((memq item '(buffer list))
(setq done t))
((string-equal "./" ido-selected)
(setq ido-exit 'fallback
done t)
(setq ido-set-default-item t)))
+
((or (string-match "[/\\][^/\\]" ido-selected)
(and (memq system-type '(windows-nt ms-dos))
(string-match "\\`.:" 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)
- (setq ido-set-default-item t))
+ (if ido-input-stack
+ (while ido-input-stack
+ (let ((elt (car ido-input-stack)))
+ (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))))))
(defun ido-edit-input ()
"Edit absolute file name entered so far with ido; terminate by RET."
(interactive)
- (setq ido-text-init ido-text)
+ (setq ido-text-init (if ido-matches (car ido-matches) ido-text))
(setq ido-exit 'edit)
(exit-minibuffer))
;;; MAIN FUNCTIONS
-(defun ido-buffer-internal (method &optional fallback prompt default initial)
+(defun ido-buffer-internal (method &optional fallback prompt default initial switch-cmd)
;; Internal function for ido-switch-buffer and friends
(if (not ido-mode)
- (call-interactively (or fallback 'switch-to-buffer))
- (let ((buf (ido-read-buffer (or prompt "Buffer: ") default nil initial)))
+ (progn
+ (run-hook-with-args 'ido-before-fallback-functions
+ (or fallback 'switch-to-buffer))
+ (call-interactively (or fallback 'switch-to-buffer)))
+ (let* ((ido-context-switch-command switch-cmd)
+ (ido-current-directory nil)
+ (ido-directory-nonreadable nil)
+ (ido-directory-too-big nil)
+ (buf (ido-read-internal 'buffer (or prompt "Buffer: ") 'ido-buffer-history default nil initial)))
;; Choose the buffer name: either the text typed in, or the head
;; of the list of matches
(cond
- ((eq ido-exit 'findfile)
+ ((eq ido-exit 'find-file)
(ido-file-internal 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))
+ (run-hook-with-args 'ido-before-fallback-functions
+ (or fallback 'switch-to-buffer))
(call-interactively (or fallback 'switch-to-buffer))))
;; Check buf is non-nil.
(if (eq method 'insert)
(progn
(ido-record-command 'insert-buffer buf)
- (insert-buffer buf))
+ (push-mark
+ (save-excursion
+ (insert-buffer-substring (get-buffer buf))
+ (point))))
(ido-visit-buffer buf method t)))
;; buffer doesn't exist
(set-buffer-major-mode buf))
(ido-visit-buffer buf method t))))))
-;;;###autoload
-(defun ido-read-buffer (prompt &optional default require-match initial)
- "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.
-If INITIAL is non-nil, it specifies the initial input string."
- (let ((ido-current-directory nil)
- (ido-directory-nonreadable nil))
- (ido-read-internal 'buffer prompt 'ido-buffer-history default require-match initial)))
-
(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))
;; 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)
+(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))
- (let* ((ido-current-directory (ido-expand-directory default))
- (ido-directory-nonreadable (ido-nonreadable-directory-p ido-current-directory))
- filename)
-
- (cond
- ((or (not ido-mode) (ido-is-slow-ftp-host))
- (setq filename t
- ido-exit 'fallback))
-
- ((and (eq item 'file)
+ (let ((ido-current-directory (ido-expand-directory default))
+ (ido-context-switch-command switch-cmd)
+ ido-directory-nonreadable ido-directory-too-big
+ (minibuffer-completing-file-name t)
+ 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))))
+
+ (when (and (eq item 'file)
(or ido-use-url-at-point ido-use-filename-at-point))
(let (fn d)
(require 'ffap)
;; Duplicate code from ffap-guesser as we want different behaviour for files and URLs.
(cond
- ((and ido-use-url-at-point
- ffap-url-regexp
- (ffap-fixup-url (or (ffap-url-at-point)
- (ffap-gopher-at-point))))
+ ((with-no-warnings
+ (and ido-use-url-at-point
+ ffap-url-regexp
+ (ffap-fixup-url (or (ffap-url-at-point)
+ (ffap-gopher-at-point)))))
(setq ido-exit 'ffap
filename t))
((and ido-use-filename-at-point
- (setq fn (ffap-string-at-point))
+ (setq fn (if (eq ido-use-filename-at-point 'guess)
+ (with-no-warnings (ffap-guesser))
+ (ffap-string-at-point)))
(not (string-match "^http:/" fn))
(setq d (file-name-directory fn))
(file-directory-p d))
(setq ido-current-directory d)
- (setq initial (file-name-nondirectory fn)))))))
+ (setq initial (file-name-nondirectory fn))))))
(let (ido-saved-vc-hb
(vc-handled-backends (and (boundp 'vc-handled-backends) vc-handled-backends))
;; we don't want to change directory of current buffer.
(let ((default-directory ido-current-directory)
(read-file-name-function nil))
+ (run-hook-with-args 'ido-before-fallback-functions
+ (or fallback 'find-file))
(call-interactively (or fallback 'find-file))))
- ((eq ido-exit 'findbuffer)
+ ((eq ido-exit 'switch-to-buffer)
(ido-buffer-internal 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)
(dired (concat ido-current-directory (or ido-text ""))))
(ido-record-work-directory)
(funcall method ido-current-directory)
(if (eq method 'dired)
- (dired-goto-file (expand-file-name file))))
+ (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))
+ ((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-internal dirname)
(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)
(if ido-find-literal 'insert-file-literally 'insert-file)
filename)
(ido-record-work-directory)
- (if ido-find-literal
- (insert-file-contents-literally filename)
- (insert-file-contents filename)))
+ (insert-file-1 filename
+ (if ido-find-literal
+ #'insert-file-contents-literally
+ #'insert-file-contents)))
(filename
(ido-record-work-file filename)
(interactive)
(let (res)
(cond
+ (ido-incomplete-regexp
+ ;; Do nothing
+ )
((and (memq ido-cur-item '(file dir))
(string-match "[$]" ido-text))
(let ((evar (substitute-in-file-name (concat ido-current-directory ido-text))))
(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))))
((not ido-use-merged-list)
(ido-merge-work-directories))))
+;;; Magic C-f
+
+(defun ido-magic-forward-char ()
+ "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)
+ (cond
+ ((not (eobp))
+ (forward-char 1))
+ ((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 ()
+ "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)
+ (cond
+ ((> (point) (minibuffer-prompt-end))
+ (forward-char -1))
+ ((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 ()
+ "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)
+ (cond
+ ((not (eobp))
+ (delete-char 1))
+ (ido-context-switch-command
+ nil)
+ ((memq ido-cur-item '(file dir))
+ (ido-enter-dired))))
+
+
;;; TOGGLE FUNCTIONS
(defun ido-toggle-case ()
(defun ido-toggle-ignore ()
"Toggle ignoring files specified with `ido-ignore-files'."
(interactive)
- (setq ido-process-ignore-lists (not ido-process-ignore-lists))
+ (if ido-directory-too-big
+ (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))
(interactive)
(if (and ido-mode (eq ido-cur-item 'file))
(progn
- (ido-remove-cached-dir ido-current-directory)
+ (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)
(defun ido-exit-minibuffer ()
"Exit minibuffer, but make sure we have a match if one is needed."
(interactive)
- (if (or (not ido-require-match)
- (ido-existing-item-p))
- (throw 'exit nil)))
+ (if (and (or (not ido-require-match)
+ (ido-existing-item-p))
+ (not ido-incomplete-regexp))
+ (exit-minibuffer)))
(defun ido-select-text ()
"Select the buffer or file named by the prompt.
(defun ido-fallback-command ()
"Fallback to non-ido version of current command."
(interactive)
+ (let ((i (length ido-text)))
+ (while (> i 0)
+ (push (aref ido-text (setq i (1- i))) unread-command-events)))
(setq ido-exit 'fallback)
(exit-minibuffer))
(defun ido-enter-find-file ()
- "Drop into find-file from buffer switching."
+ "Drop into `find-file' from buffer switching."
(interactive)
- (setq ido-exit 'findfile)
+ (setq ido-exit 'find-file)
(exit-minibuffer))
(defun ido-enter-switch-buffer ()
- "Drop into ido-switch-buffer from file switching."
+ "Drop into `ido-switch-buffer' from file switching."
(interactive)
- (setq ido-exit 'findbuffer)
+ (setq ido-exit 'switch-to-buffer)
(exit-minibuffer))
(defun ido-enter-dired ()
(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."
(not (equal dir ido-current-directory))
(file-directory-p dir)
(or (not must-match)
- (ido-set-matches1
+ ;; TODO. check for nonreadable and too-big.
+ (ido-set-matches-1
(if (eq ido-cur-item 'file)
- (ido-make-file-list1 dir)
- (ido-make-dir-list1 dir)))))
+ (ido-make-file-list-1 dir)
+ (ido-make-dir-list-1 dir)))))
(setq j n)
(setq dir nil)))
(if dir
(unless file
(let ((enable-recursive-minibuffers t))
(setq file
- (read-string (concat "Wide find file: " ido-current-directory) ido-text))))
+ (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)
(unless dir
(let ((enable-recursive-minibuffers t))
(setq dir
- (read-string (concat "Wide find directory: " ido-current-directory) ido-text))))
+ (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-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-push-dir ()
+ "Move to previous directory in file name, push current input on stack."
+ (interactive)
+ (setq ido-exit 'push)
+ (exit-minibuffer))
+
+(defun ido-pop-dir (arg)
+ "Pop directory from input stack back to input.
+With \\[universal-argument], pop all element."
+ (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)
(defun ido-all-completions ()
;; Return unsorted list of all competions.
- (let ((ido-process-ignore-lists nil))
+ (let ((ido-process-ignore-lists nil)
+ (ido-directory-too-big nil))
(cond
((eq ido-cur-item 'file)
- (ido-make-file-list1 ido-current-directory))
+ (ido-make-file-list-1 ido-current-directory))
((eq ido-cur-item 'dir)
- (ido-make-dir-list1 ido-current-directory))
+ (ido-make-dir-list-1 ido-current-directory))
((eq ido-cur-item 'buffer)
- (ido-make-buffer-list1))
+ (ido-make-buffer-list-1))
+ ((eq ido-cur-item 'list)
+ ido-choice-list)
(t nil))))
-(defun ido-sort-list (items)
- ;; Simple list of file or buffer names
- (sort items (lambda (a b) (string-lessp (ido-no-final-slash a)
- (ido-no-final-slash b)))))
+;; File list sorting
+
+(defun ido-file-lessp (a b)
+ ;; Simple compare two file names.
+ (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.
+ (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
+ ((= oa ob)
+ lessp)
+ ((and oa ob)
+ (if lessp
+ (> oa ob)
+ (< 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.
(setq items (cdr items)))
res))
-(defun ido-make-merged-file-list (text auto wide)
+
+(defun ido-make-merged-file-list-1 (text auto wide)
(let (res)
- (message "Searching for `%s'...." text)
(if (and (ido-final-slash text) ido-dir-file-cache)
(if wide
(setq res (ido-wide-find-dirs-or-files
(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-list1 dir t)
- (ido-make-dir-list1 dir t))))
+ (ido-make-file-list-1 dir t)
+ (ido-make-dir-list-1 dir t))))
(if must-match
- (setq fl (ido-set-matches1 fl)))
+ (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))))))
- (if (and res (not (eq res t)))
- (setq res (ido-sort-merged-list res auto)))
+ 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))
(message nil)
res))
-(defun ido-make-buffer-list1 (&optional frame visible)
+(defun ido-make-buffer-list-1 (&optional frame visible)
;; Return list of non-ignored buffer names
(delq nil
(mapcar
(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-buflist-hook' is run after the list has been
+ ;; 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-list1 (selected-frame) ido-current-buffers)))
+ (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))
(run-hooks 'ido-make-buffer-list-hook)
ido-temp-list))
+(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'
(mapcar
(nconc ido-temp-list items)
(setq ido-temp-list items)))
-(defun ido-file-name-all-completions1 (dir)
+(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))
-
- ;; Trick tramp's file-name-all-completions handler to DTRT, as it
- ;; has some pretty obscure requirements. This seems to work...
- ;; /ftp: => (f-n-a-c "/ftp:" "")
- ;; /ftp:kfs: => (f-n-a-c "" "/ftp:kfs:")
- ;; /ftp:kfs@ => (f-n-a-c "ftp:kfs@" "/")
- ;; /ftp:kfs@kfs: => (f-n-a-c "" "/ftp:kfs@kfs:")
- ;; Currently no attempt is made to handle multi: stuff.
-
- (let* ((prefix (match-string 1 dir))
- (user-flag (match-beginning 2))
- (len (and prefix (length prefix)))
- compl)
- (if user-flag
- (setq dir (substring dir 1)))
- (require 'tramp nil t)
- (ido-trace "tramp complete" dir)
- (setq compl (file-name-all-completions dir (if user-flag "/" "")))
- (if (> len 0)
+ (or (fboundp 'tramp-completion-mode)
+ (require 'tramp nil t))
+ (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 (file-name-all-completions "" dir)
+ ;; work around bug in ange-ftp.
+ ;; /ftp:user@host: => nil
+ ;; /ftp:user@host:./ => ok
+ (and
+ (not (string= "/ftp:" dir))
+ (tramp-tramp-file-p dir)
+ (fboundp 'tramp-ftp-file-name-p)
+ (funcall '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
(defun ido-file-name-all-completions (dir)
;; Return name of all files in DIR
;; Uses and updates ido-dir-file-cache
- (if (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))
+ (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))
- (attr (if ftp nil (file-attributes dir)))
+ (unc (ido-is-unc-host dir))
+ (attr (if (or ftp unc) nil (file-attributes dir)))
(mtime (nth 5 attr))
valid)
(when cached ; should we use the cached entry ?
- (if ftp
- (setq valid (and (eq (car ctime) 'ftp)
- (ido-cache-ftp-valid (cdr ctime))))
+ (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 (and (= (car ctime) (car mtime))
- (= (car (cdr ctime)) (car (cdr mtime)))))))
- (if (not valid)
- (setq ido-dir-file-cache (delq cached ido-dir-file-cache)
- cached nil)))
+ (= (car (cdr ctime)) (car (cdr mtime))))))))
+ (unless valid
+ (setq ido-dir-file-cache (delq cached ido-dir-file-cache)
+ cached nil)))
(unless cached
- (if (and ftp (file-readable-p dir))
- (setq mtime (cons 'ftp (ido-time-stamp))))
+ (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-completions1 dir)))
+ (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))))
- (ido-file-name-all-completions1 dir)))
+ (cdr (cdr cached)))))
+ (t
+ (ido-file-name-all-completions-1 dir))))
(defun ido-remove-cached-dir (dir)
;; Remove dir from ido-dir-file-cache
(setq ido-dir-file-cache (delq cached ido-dir-file-cache))))))
-(defun ido-make-file-list1 (dir &optional merged)
+(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) (file-directory-p dir))
+ (and (or (ido-is-tramp-root dir) (ido-is-unc-root dir)
+ (file-directory-p dir))
(delq nil
(mapcar
(lambda (name)
;; 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-list1 ido-current-directory)))
- (setq ido-temp-list (ido-sort-list ido-temp-list))
- (let ((default-directory ido-current-directory))
- (ido-to-end ;; move ftp hosts and visited files to end
- (delq nil (mapcar
- (lambda (x) (if (or (string-match "..:\\'" x)
- (and (not (ido-final-slash x))
- (get-file-buffer x))) x))
- ido-temp-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 (string-match "..:\\'" x)
+ (and (not (ido-final-slash x))
+ (get-file-buffer x))) x))
+ ido-temp-list)))))
(ido-to-end ;; move . files to end
(delq nil (mapcar
(lambda (x) (if (string-equal (substring x 0 1) ".") x))
(run-hooks 'ido-make-file-list-hook)
ido-temp-list))
-(defun ido-make-dir-list1 (dir &optional merged)
+(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))
;; 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-list1 ido-current-directory)))
- (setq ido-temp-list (ido-sort-list ido-temp-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))
(setq ido-temp-list
(cons default ido-temp-list))))
(setq ido-temp-list (delete "." ido-temp-list))
- (setq ido-temp-list (cons "." 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))
;;; FIND MATCHING ITEMS
-(defun ido-set-matches1 (items &optional do-full)
+(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)))
(concat "\\`" re "\\'")))
(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
prefix-matches
matches)
- (mapcar
- (lambda (item)
- (let ((name (ido-name item)))
- (if (string-match re name)
- (cond
- ((and full-re (string-match full-re name))
- (setq full-matches (cons item full-matches)))
- ((and prefix-re (string-match prefix-re name))
- (setq prefix-matches (cons item prefix-matches)))
- (t (setq matches (cons item matches))))))
- t)
- items)
+ (setq ido-incomplete-regexp nil)
+ (condition-case error
+ (mapcar
+ (lambda (item)
+ (let ((name (ido-name item)))
+ (if (and (or non-prefix-dot
+ (if (= (aref ido-text 0) ?.)
+ (= (aref name 0) ?.)
+ (/= (aref name 0) ?.)))
+ (string-match re name))
+ (cond
+ ((and full-re (string-match full-re name))
+ (setq full-matches (cons item full-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))))
(if prefix-matches
(setq matches (nconc prefix-matches matches)))
(if full-matches
(defun ido-set-matches ()
;; Set `ido-matches' to the list of items matching prompt
(when ido-rescan
- (setq ido-matches (ido-set-matches1 (reverse ido-cur-list) (not ido-rotate))
+ (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)
(or (member name ido-ignore-item-temp-list)
(and
ido-process-ignore-lists re-list
- (let ((data (match-data))
- (ext-list (and ignore-ext ido-ignore-extensions
+ (save-match-data
+ (let ((ext-list (and ignore-ext ido-ignore-extensions
completion-ignored-extensions))
- 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)))
- ((fboundp 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))
- ((fboundp 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)))
- (set-match-data data)
- ignorep))))
-
+ (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)))
+ ((fboundp 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))
+ ((fboundp 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)
(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))
- (set (make-local-variable 'ido-completion-buffer-full) t)
+ (with-no-warnings
+ (set (make-local-variable 'ido-completion-buffer-full) t))
(setq full-list t
display-it t))
(scroll-other-window))
(setq display-it t))
(if display-it
(with-output-to-temp-buffer ido-completion-buffer
- (let ((completion-list (ido-sort-list
+ (let ((completion-list (sort
(cond
(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)))))))
+ (copy-sequence (or ido-matches ido-cur-list))))
+ #'ido-file-lessp)))
(if (featurep 'xemacs)
;; XEmacs extents are put on by default, doesn't seem to be
;; any way of switching them off.
(file-exists-p file)
(not (file-directory-p file))
(file-writable-p ido-current-directory)
- (yes-or-no-p (concat "Delete " file " ")))
+ (yes-or-no-p (concat "Delete " file "? ")))
(delete-file file)
;; Check if file still exists.
(if (file-exists-p file)
;;; VISIT CHOSEN BUFFER
(defun ido-visit-buffer (buffer method &optional record)
"Visit file named FILE according to METHOD.
-Record command in command-history if optional RECORD is non-nil."
+Record command in `command-history' if optional RECORD is non-nil."
(let (win newframe)
(cond
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: \\<ido-mode-map>
+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: \\<ido-buffer-completion-map>
RET Select the buffer at the front of the list of matches. If the
list is empty, possibly prompt to create new buffer.
\\[ido-toggle-prefix] Toggle between substring and prefix matching.
\\[ido-toggle-case] Toggle case-sensitive searching of buffer names.
\\[ido-completion-help] Show list of matching buffers in separate window.
-\\[ido-enter-find-file] Drop into ido-find-file.
+\\[ido-enter-find-file] Drop into `ido-find-file'.
\\[ido-kill-buffer-at-head] Kill buffer at head of buffer list.
\\[ido-toggle-ignore] Toggle ignoring buffers listed in `ido-ignore-buffers'."
(interactive)
The buffer name is selected interactively by typing a substring.
For details of keybindings, do `\\[describe-function] ido'."
(interactive)
- (ido-buffer-internal 'display 'display-buffer))
+ (ido-buffer-internal 'display 'display-buffer nil nil nil 'ignore))
;;;###autoload
(defun ido-kill-buffer ()
The buffer name is selected interactively by typing a substring.
For details of keybindings, do `\\[describe-function] ido'."
(interactive)
- (ido-buffer-internal 'kill 'kill-buffer "Kill buffer: " (buffer-name (current-buffer))))
+ (ido-buffer-internal 'kill 'kill-buffer "Kill buffer: " (buffer-name (current-buffer)) nil 'ignore))
;;;###autoload
(defun ido-insert-buffer ()
The buffer name is selected interactively by typing a substring.
For details of keybindings, do `\\[describe-function] ido'."
(interactive)
- (ido-buffer-internal 'insert 'insert-buffer "Insert buffer: "))
+ (ido-buffer-internal 'insert 'insert-buffer "Insert buffer: " nil nil 'ido-enter-insert-file))
;;;###autoload
(defun ido-switch-buffer-other-frame ()
(interactive "DDir: ")
(if (not (equal (substring dir -1) "/"))
(setq dir (concat dir "/")))
- (ido-file-internal ido-default-file-method nil dir))
+ (ido-file-internal ido-default-file-method nil dir nil nil nil 'ignore))
;;;###autoload
(defun ido-find-file ()
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: \\<ido-mode-map>
+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: \\<ido-file-completion-map>
RET Select the file at the front of the list of matches. If the
list is empty, possibly prompt to create new file.
\\[ido-merge-work-directories] search for file in the work directory history.
\\[ido-forget-work-directory] removes current directory from the work directory history.
\\[ido-prev-work-file] or \\[ido-next-work-file] cycle through the work file history.
-\\[ido-wide-find-file] and \\[ido-wide-find-dir] prompts and uses find to locate files or directories.
+\\[ido-wide-find-file-or-pop-dir] and \\[ido-wide-find-dir-or-delete-dir] prompts and uses find to locate files or directories.
\\[ido-make-directory] prompts for a directory to create in current directory.
\\[ido-fallback-command] Fallback to non-ido version of current command.
\\[ido-toggle-regexp] Toggle regexp searching.
The file name is selected interactively by typing a substring.
For details of keybindings, do `\\[describe-function] ido-find-file'."
(interactive)
- (ido-file-internal 'display))
+ (ido-file-internal 'display nil nil nil nil nil 'ignore))
;;;###autoload
(defun ido-find-file-other-frame ()
(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: ")))
+ (ido-file-internal 'write 'write-file nil "Write file: " nil nil 'ignore)))
;;;###autoload
(defun ido-insert-file ()
The file name is selected interactively by typing a substring.
For details of keybindings, do `\\[describe-function] ido-find-file'."
(interactive)
- (ido-file-internal 'insert 'insert-file nil "Insert file: "))
+ (ido-file-internal 'insert 'insert-file nil "Insert file: " nil nil 'ido-enter-insert-buffer))
;;;###autoload
(defun ido-dired ()
;; Handle explicit directory changes
(cond
- ((eq ido-cur-item 'buffer)
+ ((memq ido-cur-item '(buffer list))
)
((= (length contents) 0)
)
((= (length contents) 1)
- (when (and (ido-is-tramp-root) (string-equal contents "/"))
+ (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
(expand-file-name "/" ido-current-directory)
"/"))
(setq refresh t))
- ((and ido-directory-nonreadable
+ ((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)))
(ido-set-matches)
(ido-trace "new " ido-matches)
- (when (and ido-enter-single-matching-directory
+ (when (and ido-enter-matching-directory
ido-matches
- (null (cdr ido-matches))
+ (or (eq ido-enter-matching-directory 'first)
+ (null (cdr ido-matches)))
(ido-final-slash (car ido-matches))
(or try-single-dir-match
- (eq ido-enter-single-matching-directory t)))
+ (eq ido-enter-matching-directory t)))
(ido-trace "single match" (car ido-matches))
(ido-set-current-directory
(concat ido-current-directory (car ido-matches)))
(when (and (not ido-matches)
(not ido-directory-nonreadable)
+ (not ido-directory-too-big)
;; ido-rescan ?
ido-process-ignore-lists
ido-ignored-list)
(not (ido-is-root-directory))
(> (length contents) 1)
(not (string-match "[$]" contents))
- (not ido-directory-nonreadable))
+ (not ido-directory-nonreadable)
+ (not ido-directory-too-big))
(ido-trace "merge?")
(if ido-use-merged-list
(ido-undo-merge-work-directory contents nil)
first)
(if (and ind ido-use-faces)
- (put-text-property 0 1 'face 'ido-indicator-face ind))
+ (put-text-property 0 1 'face 'ido-indicator ind))
(if (and ido-use-faces comps)
(let* ((fn (ido-name (car comps)))
(setq first (format "%s" fn))
(put-text-property 0 ln 'face
(if (= (length comps) 1)
- 'ido-only-match-face
- 'ido-first-match-face)
+ (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
(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 (> (length (ido-name (car comps))) (length name))
- ;; when there is one match, show the matching file name in full
- (concat (nth 4 ido-decorations) ;; [ ... ]
- (ido-name (car comps))
- (nth 5 ido-decorations))
- "")
+ (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 one match, show the matching file name in full
+ (concat (nth 4 ido-decorations) ;; [ ... ]
+ (ido-name (car comps))
+ (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))
(if (and ido-use-faces
(not (string= str first))
(ido-final-slash str))
- (put-text-property 0 (length str) 'face 'ido-subdir-face str))
+ (put-text-property 0 (length str) 'face 'ido-subdir str))
str)))))
comps))))))
;;; Helper functions for other programs
(put 'dired-do-rename 'ido 'ignore)
+(put 'ibuffer-find-file 'ido 'find-file)
+(put 'dired-other-window 'ido 'dir)
+
+;;;###autoload
+(defun ido-read-buffer (prompt &optional default require-match)
+ "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."
+ (let* ((ido-current-directory nil)
+ (ido-directory-nonreadable nil)
+ (ido-directory-too-big nil)
+ (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))
+ buf)))
;;;###autoload
(defun ido-read-file-name (prompt &optional dir default-filename mustmatch initial predicate)
- "Read file name, prompting with PROMPT and completing in directory DIR.
+ "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."
- (cond
- ((or (eq predicate 'file-directory-p)
- (eq (get this-command 'ido) 'dir)
- (memq this-command ido-read-file-name-as-directory-commands))
- (ido-read-directory-name prompt dir default-filename mustmatch initial))
- ((and (not (eq (get this-command 'ido) 'ignore))
- (not (memq this-command ido-read-file-name-non-ido))
- (or (null predicate) (eq predicate 'file-exists-p)))
- (let* (filename
- ido-saved-vc-hb
- (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-work-directory-index -1)
- (ido-work-file-index -1)
- (ido-find-literal nil))
- (setq filename
- (ido-read-internal 'file prompt 'ido-file-history default-filename mustmatch initial))
- (if filename
- (concat ido-current-directory filename))))
- (t
- (let ((read-file-name-function nil))
- (read-file-name prompt dir default-filename mustmatch initial predicate)))))
+ (let (filename)
+ (cond
+ ((or (eq predicate 'file-directory-p)
+ (eq (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))
+ (if (eq ido-exit 'fallback)
+ (setq filename 'fallback)))
+ ((and (not (eq (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 (get this-command 'ido) 'find-file) nil 'ignore))
+ (vc-handled-backends (and (boundp 'vc-handled-backends) vc-handled-backends))
+ (minibuffer-completing-file-name t)
+ (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)
+ (ido-find-literal nil))
+ (setq ido-exit nil)
+ (setq filename
+ (ido-read-internal 'file prompt 'ido-file-history default-filename mustmatch initial))
+ (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)
- "Read directory name, prompting with PROMPT and completing in directory DIR.
-See `read-file-name' for additional parameters."
+ "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
+ (minibuffer-completing-file-name t)
+ (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-current-directory
(concat ido-current-directory filename)))))
+;;;###autoload
+(defun ido-completing-read (prompt choices &optional predicate require-match initial-input hist def)
+ "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 is currently ignored; it is 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))
+ (ido-read-internal 'list prompt hist def require-match initial-input)))
+
+
;;; arch-tag: b63a3500-1735-41bd-8a01-05373f0864da
;;; ido.el ends here