Function: ido-read-internal
ido-read-internal is a byte-compiled function defined in ido.el.gz.
Signature
(ido-read-internal ITEM PROMPT HIST &optional DEFAULT REQUIRE-MATCH INITIAL)
Documentation
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.
Source Code
;; Defined in /usr/src/emacs/lisp/ido.el.gz
;; 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))