Function: read-file-name-default
read-file-name-default is a byte-compiled function defined in
minibuffer.el.gz.
Signature
(read-file-name-default PROMPT &optional DIR DEFAULT-FILENAME MUSTMATCH INITIAL PREDICATE)
Documentation
Default method for reading file names.
See read-file-name for the meaning of the arguments.
Source Code
;; Defined in /usr/src/emacs/lisp/minibuffer.el.gz
;; minibuffer-completing-file-name is a variable used internally in minibuf.c
;; to determine whether to use minibuffer-local-filename-completion-map or
;; minibuffer-local-completion-map. It shouldn't be exported to Elisp.
;; FIXME: Actually, it is also used in rfn-eshadow.el we'd otherwise have to
;; use (eq minibuffer-completion-table #'read-file-name-internal), which is
;; probably even worse. Maybe We should add some read-file-name-setup-hook
;; instead, but for now, let's keep this non-obsolete.
;;(make-obsolete-variable 'minibuffer-completing-file-name nil "future" 'get)
(defun read-file-name-default (prompt &optional dir default-filename mustmatch initial predicate)
"Default method for reading file names.
See `read-file-name' for the meaning of the arguments."
(unless dir (setq dir (or default-directory "~/")))
(unless (file-name-absolute-p dir) (setq dir (expand-file-name dir)))
(unless default-filename
(setq default-filename
(cond
((null initial) buffer-file-name)
;; Special-case "" because (expand-file-name "" "/tmp/") returns
;; "/tmp" rather than "/tmp/" (bug#39057).
((equal "" initial) dir)
(t (expand-file-name initial dir)))))
;; If dir starts with user's homedir, change that to ~.
(setq dir (abbreviate-file-name dir))
;; Likewise for default-filename.
(if default-filename
(setq default-filename
(if (consp default-filename)
(mapcar 'abbreviate-file-name default-filename)
(abbreviate-file-name default-filename))))
(let ((insdef (cond
((and insert-default-directory (stringp dir))
(if initial
(cons (minibuffer-maybe-quote-filename (concat dir initial))
(length (minibuffer-maybe-quote-filename dir)))
(minibuffer-maybe-quote-filename dir)))
(initial (cons (minibuffer-maybe-quote-filename initial) 0)))))
(let ((ignore-case read-file-name-completion-ignore-case)
(minibuffer-completing-file-name t)
(pred (or predicate 'file-exists-p))
(add-to-history nil)
(require-match (if (functionp mustmatch)
(lambda (input)
(funcall mustmatch
;; User-supplied MUSTMATCH expects an unquoted filename
(substitute-in-file-name input)))
mustmatch)))
(let* ((val
(if (or (not (next-read-file-uses-dialog-p))
;; Graphical file dialogs can't handle remote
;; files (Bug#99).
(file-remote-p dir))
;; We used to pass `dir' to `read-file-name-internal' by
;; abusing the `predicate' argument. It's better to
;; just use `default-directory', but in order to avoid
;; changing `default-directory' in the current buffer,
;; we don't let-bind it.
(let ((dir (file-name-as-directory
(expand-file-name dir))))
(minibuffer-with-setup-hook
(lambda ()
(setq default-directory dir)
;; When the first default in `minibuffer-default'
;; duplicates initial input `insdef',
;; reset `minibuffer-default' to nil.
(when (equal (or (car-safe insdef) insdef)
(or (car-safe minibuffer-default)
minibuffer-default))
(setq minibuffer-default
(cdr-safe minibuffer-default)))
(setq-local completion-ignore-case ignore-case)
;; On the first request on `M-n' fill
;; `minibuffer-default' with a list of defaults
;; relevant for file-name reading.
(setq-local minibuffer-default-add-function
(lambda ()
(with-current-buffer
(window-buffer (minibuffer-selected-window))
(read-file-name--defaults dir initial))))
(set-syntax-table minibuffer-local-filename-syntax))
(completing-read prompt 'read-file-name-internal
pred require-match insdef
'file-name-history default-filename)))
;; If DEFAULT-FILENAME not supplied and DIR contains
;; a file name, split it.
(let ((file (file-name-nondirectory dir))
;; When using a dialog, revert to nil and non-nil
;; interpretation of mustmatch. confirm options
;; need to be interpreted as nil, otherwise
;; it is impossible to create new files using
;; dialogs with the default settings.
(dialog-mustmatch
(not (memq mustmatch
'(nil confirm confirm-after-completion)))))
(when (and (not default-filename)
(not (zerop (length file))))
(setq default-filename file)
(setq dir (file-name-directory dir)))
(when default-filename
(setq default-filename
(expand-file-name (if (consp default-filename)
(car default-filename)
default-filename)
dir)))
(setq add-to-history t)
(x-file-dialog prompt dir default-filename
dialog-mustmatch
(eq predicate 'file-directory-p)))))
(replace-in-history (eq (car-safe file-name-history) val)))
;; If completing-read returned the inserted default string itself
;; (rather than a new string with the same contents),
;; it has to mean that the user typed RET with the minibuffer empty.
;; In that case, we really want to return ""
;; so that commands such as set-visited-file-name can distinguish.
(when (consp default-filename)
(setq default-filename (car default-filename)))
(when (eq val default-filename)
;; In this case, completing-read has not added an element
;; to the history. Maybe we should.
(if (not replace-in-history)
(setq add-to-history t))
(setq val ""))
(unless val (error "No file name specified"))
(if (and default-filename
(string-equal val (if (consp insdef) (car insdef) insdef)))
(setq val default-filename))
(setq val (substitute-in-file-name val))
(if replace-in-history
;; Replace what Fcompleting_read added to the history
;; with what we will actually return. As an exception,
;; if that's the same as the second item in
;; file-name-history, it's really a repeat (Bug#4657).
(let ((val1 (minibuffer-maybe-quote-filename val)))
(if history-delete-duplicates
(setcdr file-name-history
(delete val1 (cdr file-name-history))))
(if (string= val1 (cadr file-name-history))
(pop file-name-history)
(setcar file-name-history val1)))
(when add-to-history
(add-to-history 'file-name-history
(minibuffer-maybe-quote-filename val))))
val))))