+++ /dev/null
-;;; icomplete.el --- minibuffer completion incremental feedback -*- lexical-binding: t -*-
-
-;; Copyright (C) 1992-2025 Free Software Foundation, Inc.
-
-;; Author: Ken Manheimer <ken dot manheimer at gmail...>
-;; 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 <https://www.gnu.org/licenses/>.
-
-;;; 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
- "<remap> <minibuffer-complete-and-exit>" #'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
- "<right>" #'icomplete-forward-completions
- "<left>" #'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
- "<down>" #'icomplete-forward-completions
- "<up>" #'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)))
-
-\f
-
-
-;;;_* 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
+++ /dev/null
-;;; ido.el --- interactively do things with buffers and files -*- lexical-binding: t -*-
-
-;; Copyright (C) 1996-2025 Free Software Foundation, Inc.
-
-;; Author: Kim F. Storm <storm@cua.dk>
-;; Based on: iswitchb by Stephen Eglen <stephen@cns.ed.ac.uk>
-;; 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 <https://www.gnu.org/licenses/>.
-
-
-;;; 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 <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 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 <klaus.berndl@sdm.de> based on
-;; an idea of Yuji Minejima <ggb01164@nifty.ne.jp> 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).
-\\<ido-file-completion-map>
-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).
-\\<ido-file-completion-map>
-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.
-\\<ido-file-completion-map>
-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.
-\\<ido-completion-map>
-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
- "<right>" #'ido-next-match
- "<left>" #'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
- "<down>" #'ido-next-match-dir
- "<up>" #'ido-prev-match-dir
- "M-<up>" #'ido-prev-work-directory
- "M-<down>" #'ido-next-work-directory
- "<backspace>" #'ido-delete-backward-updir
- "DEL" #'ido-delete-backward-updir
- "<remap> <delete-backward-char>" #'ido-delete-backward-updir
- "<remap> <backward-kill-word>" #'ido-delete-backward-word-updir
- "C-<backspace>" #'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: \\<ido-buffer-completion-map>
-
-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: \\<ido-file-completion-map>
-
-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