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))))