;;; files.el --- file input and output commands for Emacs -*- lexical-binding:t -*-
-;; Copyright (C) 1985-1987, 1992-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1985-1987, 1992-2016 Free Software Foundation, Inc.
;; Maintainer: emacs-devel@gnu.org
;; Package: emacs
(error "No such directory found via CDPATH environment variable"))))
(defsubst directory-name-p (name)
- "Return non-nil if NAME ends with a slash character."
- (and (> (length name) 0)
- (char-equal (aref name (1- (length name))) ?/)))
-
-(defun directory-files-recursively (dir match &optional include-directories)
- "Return all files under DIR that have file names matching MATCH (a regexp).
+ "Return non-nil if NAME ends with a directory separator character."
+ (let ((len (length name))
+ (lastc ?.))
+ (if (> len 0)
+ (setq lastc (aref name (1- len))))
+ (or (= lastc ?/)
+ (and (memq system-type '(windows-nt ms-dos))
+ (= lastc ?\\)))))
+
+(defun directory-files-recursively (dir regexp &optional include-directories)
+ "Return list of all files under DIR that have file names matching REGEXP.
This function works recursively. Files are returned in \"depth first\"
-and alphabetical order.
-If INCLUDE-DIRECTORIES, also include directories that have matching names."
+order, and files from each directory are sorted in alphabetical order.
+Each file name appears in the returned list in its absolute form.
+Optional argument INCLUDE-DIRECTORIES non-nil means also include in the
+output directories whose names match REGEXP."
(let ((result nil)
(files nil)
;; When DIR is "/", remote file names like "/method:" could
;; also be offered. We shall suppress them.
- (tramp-mode (and tramp-mode (file-remote-p dir))))
+ (tramp-mode (and tramp-mode (file-remote-p (expand-file-name dir)))))
(dolist (file (sort (file-name-all-completions "" dir)
'string<))
(unless (member file '("./" "../"))
(unless (file-symlink-p full-file)
(setq result
(nconc result (directory-files-recursively
- full-file match include-directories))))
+ full-file regexp include-directories))))
(when (and include-directories
- (string-match match leaf))
+ (string-match regexp leaf))
(setq result (nconc result (list full-file)))))
- (when (string-match match file)
+ (when (string-match regexp file)
(push (expand-file-name file dir) files)))))
(nconc result (nreverse files))))
+(defvar module-file-suffix)
+
(defun load-file (file)
"Load the Lisp file named FILE."
- ;; This is a case where .elc makes a lot of sense.
+ ;; This is a case where .elc and .so/.dll make a lot of sense.
(interactive (list (let ((completion-ignored-extensions
- (remove ".elc" completion-ignored-extensions)))
+ (remove module-file-suffix
+ (remove ".elc"
+ completion-ignored-extensions))))
(read-file-name "Load file: " nil nil 'lambda))))
(load (expand-file-name file) nil nil t))
PATH should be a list of directories to look in, like the lists in
`exec-path' or `load-path'.
If SUFFIXES is non-nil, it should be a list of suffixes to append to
-file name when searching. If SUFFIXES is nil, it is equivalent to '(\"\").
-Use '(\"/\") to disable PATH search, but still try the suffixes in SUFFIXES.
+file name when searching. If SUFFIXES is nil, it is equivalent to (\"\").
+Use (\"/\") to disable PATH search, but still try the suffixes in SUFFIXES.
If non-nil, PREDICATE is used instead of `file-readable-p'.
This function will normally skip directories, so if you want it to find
(put 'user-emacs-directory-warning 'this-session t)
(display-warning 'initialization
(format "\
-Unable to %s ‘user-emacs-directory’ (%s).
+Unable to %s `user-emacs-directory' (%s).
Any data that would normally be written there may be lost!
If you never want to see this message again,
-customize the variable ‘user-emacs-directory-warning’."
+customize the variable `user-emacs-directory-warning'."
errtype user-emacs-directory)))))
bestname))))
(defun load-library (library)
"Load the Emacs Lisp library named LIBRARY.
+LIBRARY should be a string.
This is an interface to the function `load'. LIBRARY is searched
for in `load-path', both with and without `load-suffixes' (as
well as `load-file-rep-suffixes').
See Info node `(emacs)Lisp Libraries' for more details.
See `load-file' for a different interface to `load'."
(interactive
- (list (completing-read "Load library: "
- (apply-partially 'locate-file-completion-table
- load-path
- (get-load-suffixes)))))
+ (let (completion-ignored-extensions)
+ (list (completing-read "Load library: "
+ (apply-partially 'locate-file-completion-table
+ load-path
+ (get-load-suffixes))))))
(load library))
(defun file-remote-p (file &optional identification connected)
to derive a new remote file name from an existing one. For
example, if FILE is \"/sudo::/path/to/file\" then
- \(concat \(file-remote-p FILE) \"/bin/sh\")
+ (concat (file-remote-p FILE) \"/bin/sh\")
returns a remote file name for file \"/bin/sh\" that has the
same remote identifier as FILE but expanded; a name such as
(defmacro minibuffer-with-setup-hook (fun &rest body)
"Temporarily add FUN to `minibuffer-setup-hook' while executing BODY.
-FUN can also be (:append FUN1), in which case FUN1 is appended to
-`minibuffer-setup-hook'.
+
+By default, FUN is prepended to `minibuffer-setup-hook'. But if FUN is of
+the form `(:append FUN1)', FUN1 will be appended to `minibuffer-setup-hook'
+instead of prepending it.
BODY should use the minibuffer at most once.
Recursive uses of the minibuffer are unaffected (FUN is not
(user-error "Aborted"))
(and (buffer-modified-p) buffer-file-name
(not (yes-or-no-p
- (format-message "Kill and replace buffer ‘%s’ without saving it? "
+ (format-message "Kill and replace buffer `%s' without saving it? "
(buffer-name))))
(user-error "Aborted"))
(let ((obuf (current-buffer))
\f
(defun insert-file-contents-literally (filename &optional visit beg end replace)
"Like `insert-file-contents', but only reads in the file literally.
+See `insert-file-contents' for an explanation of the parameters.
A buffer may be modified in several ways after reading into the buffer,
due to Emacs features such as format decoding, character code
conversion, `find-file-hook', automatic uncompression, etc.
(view-mode-enter))
(run-hooks 'find-file-hook)))
-(defmacro report-errors (format &rest body)
- "Eval BODY and turn any error into a FORMAT message.
-FORMAT can have a %s escape which will be replaced with the actual error.
-If `debug-on-error' is set, errors are not caught, so that you can
-debug them.
-Avoid using a large BODY since it is duplicated."
- (declare (debug t) (indent 1))
- `(if debug-on-error
- (progn . ,body)
- (condition-case err
- (progn . ,body)
- (error (message ,format (prin1-to-string err))))))
+(define-obsolete-function-alias 'report-errors 'with-demoted-errors "25.1")
(defun normal-mode (&optional find-file)
"Choose the major mode for this buffer automatically.
(let ((enable-local-variables (or (not find-file) enable-local-variables)))
;; FIXME this is less efficient than it could be, since both
;; s-a-m and h-l-v may parse the same regions, looking for "mode:".
- (report-errors "File mode specification error: %s"
+ (with-demoted-errors "File mode specification error: %s"
(set-auto-mode))
- (report-errors "File local-variables error: %s"
+ (with-demoted-errors "File local-variables error: %s"
(hack-local-variables)))
;; Turn font lock off and on, to make sure it takes account of
;; whatever file local variables are relevant to it.
(catch 'nop
(dolist (mode (nreverse modes))
(if (not (functionp mode))
- (message "Ignoring unknown mode ‘%s’" mode)
+ (message "Ignoring unknown mode `%s'" mode)
(setq done t)
(or (set-auto-mode-0 mode keep-mode-if-same)
;; continuing would call minor modes again, toggling them off
(setq mode (hack-local-variables t))
(not (memq mode modes)) ; already tried and failed
(if (not (functionp mode))
- (message "Ignoring unknown mode ‘%s’" mode)
+ (message "Ignoring unknown mode `%s'" mode)
(setq done t)
(set-auto-mode-0 mode keep-mode-if-same)))
;; If we didn't, look for an interpreter specified in the first line.
result)
(unless mode-only
(setq file-local-variables-alist nil)
- (report-errors "Directory-local variables error: %s"
+ (with-demoted-errors "Directory-local variables error: %s"
;; Note this is a no-op if enable-local-variables is nil.
(hack-dir-local-variables)))
;; This entire function is basically a no-op if enable-local-variables
(unless hack-local-variables--warned-lexical
(setq hack-local-variables--warned-lexical t)
(display-warning
- :warning
+ 'files
(format-message
- "%s: ‘lexical-binding’ at end of file unreliable"
+ "%s: `lexical-binding' at end of file unreliable"
(file-name-nondirectory
- (or buffer-file-name ""))))))
+ ;; We are called from
+ ;; 'with-temp-buffer', so we need
+ ;; to use 'thisbuf's name in the
+ ;; warning message.
+ (or (buffer-file-name thisbuf) ""))))))
(t
(ignore-errors
(push (cons (if (eq var 'eval)
var (if since (format " (since %s)" since))
(if (stringp instead)
(substitute-command-keys instead)
- (format-message "use ‘%s’ instead" instead)))))))
+ (format-message "use `%s' instead" instead)))))))
(defun hack-one-local-variable (var val)
"Set local variable VAR with value VAL.
for a class are defined using `dir-locals-set-class-variables'."
(setq directory (file-name-as-directory (expand-file-name directory)))
(unless (assq class dir-locals-class-alist)
- (error "No such class ‘%s’" (symbol-name class)))
+ (error "No such class `%s'" (symbol-name class)))
(push (list directory class mtime) dir-locals-directory-cache))
(defun dir-locals-set-class-variables (class variables)
(if (eq (car elt) 'coding)
(unless hack-dir-local-variables--warned-coding
(setq hack-dir-local-variables--warned-coding t)
- (display-warning :warning
+ (display-warning 'files
"Coding cannot be specified by dir-locals"))
(unless (memq (car elt) '(eval mode))
(setq dir-local-variables-alist
However, the mode will not be changed if
\(1) a local variables list or the `-*-' line specifies a major mode, or
\(2) the current major mode is a \"special\" mode,
-\ not suitable for ordinary files, or
+ not suitable for ordinary files, or
\(3) the new file name does not particularly specify any mode."
:type 'boolean
:group 'editing-basics)
(listp last-nonmenu-event)
use-dialog-box))
(or (y-or-n-p (format-message
- "File ‘%s’ exists; overwrite? " filename))
+ "File `%s' exists; overwrite? " filename))
(user-error "Canceled")))
(set-visited-file-name filename (not confirm))))
(set-buffer-modified-p t)
(save-buffer)
;; It's likely that the VC status at the new location is different from
;; the one at the old location.
- (vc-find-file-hook))
+ (vc-refresh-state))
\f
(defun file-extended-attributes (filename)
"Return an alist of extended attributes of file FILENAME.
"Set extended attributes of file FILENAME to ATTRIBUTES.
ATTRIBUTES must be an alist of file attributes as returned by
-`file-extended-attributes'."
- (dolist (elt attributes)
- (let ((attr (car elt))
- (val (cdr elt)))
- (cond ((eq attr 'acl)
- (set-file-acl filename val))
- ((eq attr 'selinux-context)
- (set-file-selinux-context filename val))))))
+`file-extended-attributes'.
+Value is t if the function succeeds in setting the attributes."
+ (let (result rv)
+ (dolist (elt attributes)
+ (let ((attr (car elt))
+ (val (cdr elt)))
+ (cond ((eq attr 'acl)
+ (setq rv (set-file-acl filename val)))
+ ((eq attr 'selinux-context)
+ (setq rv (set-file-selinux-context filename val))))
+ (setq result (or result rv))))
+
+ result))
\f
(defun backup-buffer ()
"Make a backup of the disk file visited by the current buffer, if appropriate.
(defun file-name-sans-extension (filename)
"Return FILENAME sans final \"extension\".
-The extension, in a file name, is the part that follows the last `.',
-except that a leading `.', if any, doesn't count."
+The extension, in a file name, is the part that begins with the last `.',
+except that a leading `.' of the file name, if there is one, doesn't count."
(save-match-data
(let ((file (file-name-sans-versions (file-name-nondirectory filename)))
directory)
(defun file-name-extension (filename &optional period)
"Return FILENAME's final \"extension\".
-The extension, in a file name, is the part that follows the last `.',
-excluding version numbers and backup suffixes,
-except that a leading `.', if any, doesn't count.
+The extension, in a file name, is the part that begins with the last `.',
+excluding version numbers and backup suffixes, except that a leading `.'
+of the file name, if there is one, doesn't count.
Return nil for extensionless file names such as `foo'.
Return the empty string for file names such as `foo.'.
-If PERIOD is non-nil, then the returned value includes the period
-that delimits the extension, and if FILENAME has no extension,
-the value is \"\"."
+By default, the returned value excludes the period that starts the
+extension, but if the optional argument PERIOD is non-nil, the period
+is included in the value, and in that case, if FILENAME has no
+extension, the value is \"\"."
(save-match-data
(let ((file (file-name-sans-versions (file-name-nondirectory filename))))
(if (and (string-match "\\.[^.]*\\'" file)
;; existing directory.
(error "%s is a directory" filename)
(unless (y-or-n-p (format-message
- "File ‘%s’ exists; overwrite? "
+ "File `%s' exists; overwrite? "
filename))
(error "Canceled"))))
(set-visited-file-name filename)))
(unless (file-exists-p dir)
(if (y-or-n-p
(format-message
- "Directory ‘%s’ does not exist; create? " dir))
+ "Directory `%s' does not exist; create? " dir))
(make-directory dir t)
(error "Canceled")))
(setq setmodes (basic-save-buffer-1))))
\f
(defun clear-visited-file-modtime ()
"Clear out records of last mod time of visited file.
-Next attempt to save will certainly not complain of a discrepancy."
+Next attempt to save will not complain of a discrepancy."
(set-visited-file-modtime 0))
(defun not-modified (&optional arg)
(list dir
(if (directory-files dir nil directory-files-no-dot-files-regexp)
(y-or-n-p
- (format-message "Directory ‘%s’ is not empty, really %s? "
+ (format-message "Directory `%s' is not empty, really %s? "
dir (if trashing "trash" "delete")))
nil)
(null current-prefix-arg))))
default-directory default-directory nil nil)
current-prefix-arg t nil)))
(when (file-in-directory-p newname directory)
- (error "Cannot copy ‘%s’ into its subdirectory ‘%s’"
+ (error "Cannot copy `%s' into its subdirectory `%s'"
directory newname))
;; If default-directory is a remote directory, make sure we find its
;; copy-directory handler.
Then you'll be asked about a number of files to recover."
(interactive)
(if (null auto-save-list-file-prefix)
- (error "You set ‘auto-save-list-file-prefix’ to disable making session files"))
+ (error "You set `auto-save-list-file-prefix' to disable making session files"))
(let ((dir (file-name-directory auto-save-list-file-prefix))
(nd (file-name-nondirectory auto-save-list-file-prefix)))
(unless (file-directory-p dir)
(condition-case nil
(save-excursion (recover-file file))
(error
- "Failed to recover ‘%s’" file)))
+ "Failed to recover `%s'" file)))
files
'("file" "files" "recover"))
(message "No files can be recovered from this session now")))
(defun file-expand-wildcards (pattern &optional full)
"Expand wildcard pattern PATTERN.
This returns a list of file names which match the pattern.
+Files are sorted in `string<' order.
If PATTERN is written as an absolute file name,
the values are absolute also.
PATTERN is assumed to represent a file-name wildcard suitable for the
underlying filesystem. For Unix and GNU/Linux, each character from the
-set [ \\t\\n;<>&|()`'\"#$] is quoted with a backslash; for DOS/Windows, all
+set [ \\t\\n;<>&|()\\=`\\='\"#$] is quoted with a backslash; for DOS/Windows, all
the parts of the pattern which don't include wildcard characters are
quoted with double quotes.
and `directory-free-space-args'. If the system call or program
is unsuccessful, or if DIR is a remote directory, this function
returns nil."
- (unless (file-remote-p dir)
+ (unless (file-remote-p (expand-file-name dir))
;; Try to find the number of free blocks. Non-Posix systems don't
;; always have df, but might have an equivalent system call.
(if (fboundp 'file-system-info)
file result)
;; Unix. Access the file to get a suitable error.
(access-file file "Reading directory")
- (error "Listing directory failed but ‘access-file’ worked")))
+ (error "Listing directory failed but `access-file' worked")))
(when (if (stringp switches)
(string-match "--dired\\>" switches)
(setq error-lines (nreverse error-lines))
;; Now read the numeric positions of file names.
(goto-char linebeg)
- (forward-word 1)
+ (forward-word-strictly 1)
(forward-char 3)
(while (< (point) end)
(let ((start (insert-directory-adj-pos
((= char ?g) #o2070)
((= char ?o) #o1007)
((= char ?a) #o7777)
- (t (error "%c: bad ‘who’ character" char))))
+ (t (error "%c: bad `who' character" char))))
(defun file-modes-char-to-right (char &optional from)
"Convert CHAR to a numeric value of mode bits.
(cond ((= char ?r) #o0444)
((= char ?w) #o0222)
((= char ?x) #o0111)
- ((= char ?s) #o1000)
- ((= char ?t) #o6000)
+ ((= char ?s) #o6000)
+ ((= char ?t) #o1000)
;; Rights relative to the previous file modes.
((= char ?X) (if (= (logand from #o111) 0) 0 #o0111))
((= char ?u) (let ((uright (logand #o4700 from)))
(mapcar 'file-modes-char-to-who
(match-string 1 modes)))))
(when (= num-who 0)
- (setq num-who (default-file-modes)))
+ (setq num-who (logior #o7000 (default-file-modes))))
(setq num-modes
(file-modes-rights-to-number (substring modes (match-end 1))
num-who num-modes)
modes (substring modes (match-end 3))))
- (error "Parse error in modes near ‘%s’" (substring modes 0))))
+ (error "Parse error in modes near `%s'" (substring modes 0))))
num-modes)))
(defun read-file-modes (&optional prompt orig-file)
"Read file modes in octal or symbolic notation and return its numeric value.
-PROMPT is used as the prompt, default to `File modes (octal or symbolic): '.
+PROMPT is used as the prompt, default to \"File modes (octal or symbolic): \".
ORIG-FILE is the name of a file on whose mode bits to base returned
permissions if what user types requests to add, remove, or set permissions
based on existing mode bits, as in \"og+rX-w\"."
trash-dir)))
;; We can't trash a parent directory of trash-directory.
(if (string-prefix-p fn trash-dir)
- (error "Trash directory ‘%s’ is a subdirectory of ‘%s’"
+ (error "Trash directory `%s' is a subdirectory of `%s'"
trash-dir filename))
(unless (file-directory-p trash-dir)
(make-directory trash-dir t))