;;; files.el --- file input and output commands for Emacs
;; Copyright (C) 1985, 1986, 1987, 1992, 1993, 1994, 1995, 1996,
-;; 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-;; 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+;; 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+;; 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
;; Maintainer: FSF
+;; Package: emacs
;; This file is part of GNU Emacs.
A list of elements of the form (FROM . TO), each meaning to replace
FROM with TO when it appears in a directory name. This replacement is
done when setting up the default directory of a newly visited file.
-*Every* FROM string should start with \"\\\\`\".
+
+FROM is matched against directory names anchored at the first
+character, so it should start with a \"\\\\`\", or, if directory
+names cannot have embedded newlines, with a \"^\".
FROM and TO should be equivalent names, which refer to the
same directory. Do not use `~' in the TO strings;
via absolute symbolic links. Make TO the name of the link, and FROM
the name it is linked to."
:type '(repeat (cons :format "%v"
- :value ("" . "")
+ :value ("\\`" . "")
(regexp :tag "From")
- (regexp :tag "To")))
+ (string :tag "To")))
:group 'abbrev
:group 'find-file)
:type 'boolean
:group 'backup)
-(defcustom backup-by-copying-when-mismatch nil
+(defcustom backup-by-copying-when-mismatch t
"Non-nil means create backups by copying if this preserves owner or group.
Renaming may still be used (subject to control of other variables)
when it would not result in changing the owner or group of the file;
that is, for files which are owned by you and whose group matches
the default for a new file created there by you.
This variable is relevant only if `backup-by-copying' is nil."
+ :version "24.1"
:type 'boolean
:group 'backup)
+(put 'backup-by-copying-when-mismatch 'permanent-local t)
(defcustom backup-by-copying-when-privileged-mismatch 200
"Non-nil means create backups by copying to preserve a privileged owner.
"Non-nil if visited file was read-only when visited.")
(make-variable-buffer-local 'buffer-file-read-only)
-(defcustom temporary-file-directory
- (file-name-as-directory
- (cond ((memq system-type '(ms-dos windows-nt))
- (or (getenv "TEMP") (getenv "TMPDIR") (getenv "TMP") "c:/temp"))
- (t
- (or (getenv "TMPDIR") (getenv "TMP") (getenv "TEMP") "/tmp"))))
- "The directory for writing temporary files."
- :group 'files
- :initialize 'custom-initialize-delay
- :type 'directory)
-
(defcustom small-temporary-file-directory
(if (eq system-type 'ms-dos) (getenv "TMPDIR"))
"The directory for writing small temporary files.
(let ((x (file-name-directory suffix)))
(if x (1- (length x)) (length suffix))))))
(t
- (let ((names nil)
+ (let ((names '())
+ ;; If we have files like "foo.el" and "foo.elc", we could load one of
+ ;; them with "foo.el", "foo.elc", or "foo", where just "foo" is the
+ ;; preferred way. So if we list all 3, that gives a lot of redundant
+ ;; entries for the poor soul looking just for "foo". OTOH, sometimes
+ ;; the user does want to pay attention to the extension. We try to
+ ;; diffuse this tension by stripping the suffix, except when the
+ ;; result is a single element (i.e. usually we only list "foo" unless
+ ;; it's the only remaining element in the list, in which case we do
+ ;; list "foo", "foo.elc" and "foo.el").
+ (fullnames '())
(suffix (concat (regexp-opt suffixes t) "\\'"))
(string-dir (file-name-directory string))
(string-file (file-name-nondirectory string)))
(dolist (dir dirs)
- (unless dir
- (setq dir default-directory))
- (if string-dir (setq dir (expand-file-name string-dir dir)))
- (when (file-directory-p dir)
- (dolist (file (file-name-all-completions
- string-file dir))
- (push file names)
- (when (string-match suffix file)
- (setq file (substring file 0 (match-beginning 0)))
- (push file names)))))
+ (unless dir
+ (setq dir default-directory))
+ (if string-dir (setq dir (expand-file-name string-dir dir)))
+ (when (file-directory-p dir)
+ (dolist (file (file-name-all-completions
+ string-file dir))
+ (if (not (string-match suffix file))
+ (push file names)
+ (push file fullnames)
+ (push (substring file 0 (match-beginning 0)) names)))))
+ ;; Switching from names to names+fullnames creates a non-monotonicity
+ ;; which can cause problems with things like partial-completion.
+ ;; To minimize the problem, filter out completion-regexp-list, so that
+ ;; M-x load-library RET t/x.e TAB finds some files. Also remove elements
+ ;; from `names' which only matched `string' when they still had
+ ;; their suffix.
+ (setq names (all-completions string names))
+ ;; Remove duplicates of the first element, so that we can easily check
+ ;; if `names' really only contains a single element.
+ (when (cdr names) (setcdr names (delete (car names) (cdr names))))
+ (unless (cdr names)
+ ;; There's no more than one matching non-suffixed element, so expand
+ ;; the list by adding the suffixed elements as well.
+ (setq names (nconc names fullnames)))
(completion-table-with-context
string-dir names string-file pred action)))))
(funcall handler 'file-remote-p file identification connected)
nil)))
+(defcustom remote-file-name-inhibit-cache 10
+ "Whether to use the remote file-name cache for read access.
+
+When `nil', always use the cached values.
+When `t', never use them.
+A number means use them for that amount of seconds since they were
+cached.
+
+File attributes of remote files are cached for better performance.
+If they are changed out of Emacs' control, the cached values
+become invalid, and must be invalidated.
+
+In case a remote file is checked regularly, it might be
+reasonable to let-bind this variable to a value less then the
+time period between two checks.
+Example:
+
+ \(defun display-time-file-nonempty-p \(file)
+ \(let \(\(remote-file-name-inhibit-cache \(- display-time-interval 5)))
+ \(and \(file-exists-p file)
+ \(< 0 \(nth 7 \(file-attributes \(file-chase-links file)))))))"
+ :group 'files
+ :version "24.1"
+ :type `(choice
+ (const :tag "Do not inhibit file name cache" nil)
+ (const :tag "Do not use file name cache" t)
+ (integer :tag "Do not use file name cache"
+ :format "Do not use file name cache older then %v seconds"
+ :value 10)))
+
(defun file-local-copy (file)
"Copy the file FILE into a temporary file on this machine.
Returns the name of the local copy, or nil, if FILE is directly
(error "Aborted"))
(when (and (buffer-modified-p) buffer-file-name)
(if (yes-or-no-p (format "Buffer %s is modified; save it first? "
- (buffer-name)))
+ (buffer-name)))
(save-buffer)
(unless (yes-or-no-p "Kill and replace the buffer without saving it? ")
(error "Aborted"))))
"If file SIZE larger than `large-file-warning-threshold', allow user to abort.
OP-TYPE specifies the file operation being performed (for message to user)."
(when (and large-file-warning-threshold size
- (> size large-file-warning-threshold)
- (not (y-or-n-p
- (format "File %s is large (%dMB), really %s? "
- (file-name-nondirectory filename)
- (/ size 1048576) op-type))))
- (error "Aborted")))
+ (> size large-file-warning-threshold)
+ (not (y-or-n-p (format "File %s is large (%dMB), really %s? "
+ (file-name-nondirectory filename)
+ (/ size 1048576) op-type))))
+ (error "Aborted")))
(defun find-file-noselect (filename &optional nowarn rawfile wildcards)
"Read file FILENAME into a buffer and return the buffer.
(lambda (elt)
(cons (purecopy (car elt)) (cdr elt)))
`(;; do this first, so that .html.pl is Polish html, not Perl
- ("\\.s?html?\\(\\.[a-zA-Z_]+\\)?\\'" . html-mode)
+ ("\\.[sx]?html?\\(\\.[a-zA-Z_]+\\)?\\'" . html-mode)
+ ("\\.svgz?\\'" . image-mode)
+ ("\\.svgz?\\'" . xml-mode)
+ ("\\.x[bp]m\\'" . image-mode)
+ ("\\.x[bp]m\\'" . c-mode)
+ ("\\.p[bpgn]m\\'" . image-mode)
+ ("\\.tiff?\\'" . image-mode)
+ ("\\.gif\\'" . image-mode)
+ ("\\.png\\'" . image-mode)
+ ("\\.jpe?g\\'" . image-mode)
("\\.te?xt\\'" . text-mode)
("\\.[tT]e[xX]\\'" . tex-mode)
("\\.ins\\'" . tex-mode) ;Installation files for TeX packages.
("\\.te?xi\\'" . texinfo-mode)
("\\.[sS]\\'" . asm-mode)
("\\.asm\\'" . asm-mode)
+ ("\\.css\\'" . css-mode)
+ ("\\.mixal\\'" . mixal-mode)
+ ("\\.gcov\\'" . compilation-mode)
+ ;; Besides .gdbinit, gdb documents other names to be usable for init
+ ;; files, cross-debuggers can use something like
+ ;; .PROCESSORNAME-gdbinit so that the host and target gdbinit files
+ ;; don't interfere with each other.
+ ("/\\.[a-z0-9-]*gdbinit" . gdb-script-mode)
("[cC]hange\\.?[lL]og?\\'" . change-log-mode)
("[cC]hange[lL]og[-.][0-9]+\\'" . change-log-mode)
("\\$CHANGE_LOG\\$\\.TXT" . change-log-mode)
("\\.cl[so]\\'" . latex-mode) ;LaTeX 2e class option
("\\.bbl\\'" . latex-mode)
("\\.bib\\'" . bibtex-mode)
+ ("\\.bst\\'" . bibtex-style-mode)
("\\.sql\\'" . sql-mode)
("\\.m[4c]\\'" . m4-mode)
("\\.mf\\'" . metafont-mode)
("\\.oak\\'" . scheme-mode)
("\\.sgml?\\'" . sgml-mode)
("\\.x[ms]l\\'" . xml-mode)
+ ("\\.dbk\\'" . xml-mode)
("\\.dtd\\'" . sgml-mode)
("\\.ds\\(ss\\)?l\\'" . dsssl-mode)
("\\.js\\'" . js-mode) ; javascript-mode would be better
("[:/]_emacs\\'" . emacs-lisp-mode)
("/crontab\\.X*[0-9]+\\'" . shell-script-mode)
("\\.ml\\'" . lisp-mode)
+ ;; Linux-2.6.9 uses some different suffix for linker scripts:
+ ;; "ld", "lds", "lds.S", "lds.in", "ld.script", and "ld.script.balo".
+ ;; eCos uses "ld" and "ldi". Netbsd uses "ldscript.*".
+ ("\\.ld[si]?\\'" . ld-script-mode)
+ ("ld\\.?script\\'" . ld-script-mode)
+ ;; .xs is also used for ld scripts, but seems to be more commonly
+ ;; associated with Perl .xs files (C with Perl bindings). (Bug#7071)
+ ("\\.xs\\'" . c-mode)
+ ;; Explained in binutils ld/genscripts.sh. Eg:
+ ;; A .x script file is the default script.
+ ;; A .xr script is for linking without relocation (-r flag). Etc.
+ ("\\.x[abdsru]?[cnw]?\\'" . ld-script-mode)
+ ("\\.zone\\'" . dns-mode)
+ ("\\.soa\\'" . dns-mode)
;; Common Lisp ASDF package system.
("\\.asd\\'" . lisp-mode)
("\\.\\(asn\\|mib\\|smi\\)\\'" . snmp-mode)
("\\.\\(diffs?\\|patch\\|rej\\)\\'" . diff-mode)
("\\.\\(dif\\|pat\\)\\'" . diff-mode) ; for MSDOG
("\\.[eE]?[pP][sS]\\'" . ps-mode)
- ("\\.\\(?:PDF\\|DVI\\|pdf\\|dvi\\)\\'" . doc-view-mode)
+ ("\\.\\(?:PDF\\|DVI\\|OD[FGPST]\\|DOCX?\\|XLSX?\\|PPTX?\\|pdf\\|dvi\\|od[fgpst]\\|docx?\\|xlsx?\\|pptx?\\)\\'" . doc-view-mode-maybe)
("configure\\.\\(ac\\|in\\)\\'" . autoconf-mode)
("\\.s\\(v\\|iv\\|ieve\\)\\'" . sieve-mode)
("BROWSE\\'" . ebrowse-tree-mode)
(no-update-autoloads . booleanp)
(tab-width . integerp) ;; C source code
(truncate-lines . booleanp) ;; C source code
+ (word-wrap . booleanp) ;; C source code
(bidi-display-reordering . booleanp))) ;; C source code
+(put 'bidi-paragraph-direction 'safe-local-variable
+ (lambda (v) (memq v '(nil right-to-left left-to-right))))
+
(put 'c-set-style 'safe-local-eval-function t)
(defvar file-local-variables-alist nil
specified. The actual value in the buffer may differ from VALUE,
if it is changed by the major or minor modes, or by the user.")
(make-variable-buffer-local 'file-local-variables-alist)
+(put 'file-local-variables-alist 'permanent-local t)
(defvar dir-local-variables-alist nil
"Alist of directory-local variable settings in the current buffer.
directory-local variables, or nil otherwise."
(if noninteractive
nil
- (let ((name (or dir-name
- (if buffer-file-name
- (file-name-nondirectory buffer-file-name)
- (concat "buffer " (buffer-name)))))
- (offer-save (and (eq enable-local-variables t) unsafe-vars))
- prompt char)
- (save-window-excursion
- (let ((buf (get-buffer-create "*Local Variables*")))
- (pop-to-buffer buf)
- (set (make-local-variable 'cursor-type) nil)
- (erase-buffer)
- (if unsafe-vars
- (insert "The local variables list in " name
- "\ncontains values that may not be safe (*)"
- (if risky-vars
- ", and variables that are risky (**)."
- "."))
- (if risky-vars
- (insert "The local variables list in " name
- "\ncontains variables that are risky (**).")
- (insert "A local variables list is specified in " name ".")))
- (insert "\n\nDo you want to apply it? You can type
+ (save-window-excursion
+ (let* ((name (or dir-name
+ (if buffer-file-name
+ (file-name-nondirectory buffer-file-name)
+ (concat "buffer " (buffer-name)))))
+ (offer-save (and (eq enable-local-variables t)
+ unsafe-vars))
+ (exit-chars
+ (if offer-save '(?! ?y ?n ?\s ?\C-g) '(?y ?n ?\s ?\C-g)))
+ (buf (pop-to-buffer "*Local Variables*"))
+ prompt char)
+ (set (make-local-variable 'cursor-type) nil)
+ (erase-buffer)
+ (cond
+ (unsafe-vars
+ (insert "The local variables list in " name
+ "\ncontains values that may not be safe (*)"
+ (if risky-vars
+ ", and variables that are risky (**)."
+ ".")))
+ (risky-vars
+ (insert "The local variables list in " name
+ "\ncontains variables that are risky (**)."))
+ (t
+ (insert "A local variables list is specified in " name ".")))
+ (insert "\n\nDo you want to apply it? You can type
y -- to apply the local variables list.
n -- to ignore the local variables list.")
- (if offer-save
- (insert "
+ (if offer-save
+ (insert "
! -- to apply the local variables list, and permanently mark these
values (*) as safe (in the future, they will be set automatically.)\n\n")
- (insert "\n\n"))
- (dolist (elt all-vars)
- (cond ((member elt unsafe-vars)
- (insert " * "))
- ((member elt risky-vars)
- (insert " ** "))
- (t
- (insert " ")))
- (princ (car elt) buf)
- (insert " : ")
- ;; Make strings with embedded whitespace easier to read.
- (let ((print-escape-newlines t))
- (prin1 (cdr elt) buf))
- (insert "\n"))
- (setq prompt
- (format "Please type %s%s: "
- (if offer-save "y, n, or !" "y or n")
- (if (< (line-number-at-pos) (window-body-height))
- ""
- ", or C-v to scroll")))
- (goto-char (point-min))
- (let ((cursor-in-echo-area t)
- (executing-kbd-macro executing-kbd-macro)
- (exit-chars
- (if offer-save '(?! ?y ?n ?\s ?\C-g) '(?y ?n ?\s ?\C-g)))
- done)
- (while (not done)
- (message "%s" prompt)
- (setq char (read-event))
- (if (numberp char)
- (cond ((eq char ?\C-v)
- (condition-case nil
- (scroll-up)
- (error (goto-char (point-min)))))
- ;; read-event returns -1 if we are in a kbd
- ;; macro and there are no more events in the
- ;; macro. In that case, attempt to get an
- ;; event interactively.
- ((and executing-kbd-macro (= char -1))
- (setq executing-kbd-macro nil))
- (t (setq done (memq (downcase char) exit-chars)))))))
- (setq char (downcase char))
- (when (and offer-save (= char ?!) unsafe-vars)
- (dolist (elt unsafe-vars)
- (add-to-list 'safe-local-variable-values elt))
- ;; When this is called from desktop-restore-file-buffer,
- ;; coding-system-for-read may be non-nil. Reset it before
- ;; writing to .emacs.
- (if (or custom-file user-init-file)
- (let ((coding-system-for-read nil))
- (customize-save-variable
- 'safe-local-variable-values
- safe-local-variable-values))))
- (kill-buffer buf)
- (or (= char ?!)
- (= char ?\s)
- (= char ?y)))))))
+ (insert "\n\n"))
+ (dolist (elt all-vars)
+ (cond ((member elt unsafe-vars)
+ (insert " * "))
+ ((member elt risky-vars)
+ (insert " ** "))
+ (t
+ (insert " ")))
+ (princ (car elt) buf)
+ (insert " : ")
+ ;; Make strings with embedded whitespace easier to read.
+ (let ((print-escape-newlines t))
+ (prin1 (cdr elt) buf))
+ (insert "\n"))
+ (setq prompt
+ (format "Please type %s%s: "
+ (if offer-save "y, n, or !" "y or n")
+ (if (< (line-number-at-pos) (window-body-height))
+ ""
+ (push ?\C-v exit-chars)
+ ", or C-v to scroll")))
+ (goto-char (point-min))
+ (while (null char)
+ (setq char (read-char-choice prompt exit-chars t))
+ (when (eq char ?\C-v)
+ (condition-case nil
+ (scroll-up)
+ (error (goto-char (point-min))))
+ (setq char nil)))
+ (kill-buffer buf)
+ (when (and offer-save (= char ?!) unsafe-vars)
+ (dolist (elt unsafe-vars)
+ (add-to-list 'safe-local-variable-values elt))
+ ;; When this is called from desktop-restore-file-buffer,
+ ;; coding-system-for-read may be non-nil. Reset it before
+ ;; writing to .emacs.
+ (if (or custom-file user-init-file)
+ (let ((coding-system-for-read nil))
+ (customize-save-variable
+ 'safe-local-variable-values
+ safe-local-variable-values))))
+ (memq char '(?! ?\s ?y))))))
(defun hack-local-variables-prop-line (&optional mode-only)
"Return local variables specified in the -*- line.
evaluates to a non-nil value with VAL as an argument."
(or (member (cons sym val) safe-local-variable-values)
(let ((safep (get sym 'safe-local-variable)))
- (and (functionp safep) (funcall safep val)))))
+ (and (functionp safep)
+ ;; If the function signals an error, that means it
+ ;; can't assure us that the value is safe.
+ (with-demoted-errors (funcall safep val))))))
(defun risky-local-variable-p (sym &optional ignored)
"Non-nil if SYM could be dangerous as a file-local variable.
Return the new variables list."
(let* ((file-name (buffer-file-name))
(sub-file-name (if file-name
+ ;; FIXME: Why not use file-relative-name?
(substring file-name (length root)))))
- (dolist (entry class-variables variables)
- (let ((key (car entry)))
- (cond
- ((stringp key)
- ;; Don't include this in the previous condition, because we
- ;; want to filter all strings before the next condition.
- (when (and sub-file-name
- (>= (length sub-file-name) (length key))
- (string= key (substring sub-file-name 0 (length key))))
- (setq variables (dir-locals-collect-variables
- (cdr entry) root variables))))
- ((or (not key)
- (derived-mode-p key))
- (setq variables (dir-locals-collect-mode-variables
- (cdr entry) variables))))))))
+ (condition-case err
+ (dolist (entry class-variables variables)
+ (let ((key (car entry)))
+ (cond
+ ((stringp key)
+ ;; Don't include this in the previous condition, because we
+ ;; want to filter all strings before the next condition.
+ (when (and sub-file-name
+ (>= (length sub-file-name) (length key))
+ (string-prefix-p key sub-file-name))
+ (setq variables (dir-locals-collect-variables
+ (cdr entry) root variables))))
+ ((or (not key)
+ (derived-mode-p key))
+ (setq variables (dir-locals-collect-mode-variables
+ (cdr entry) variables))))))
+ (error
+ ;; The file's content might be invalid (e.g. have a merge conflict), but
+ ;; that shouldn't prevent the user from opening the file.
+ (message ".dir-locals error: %s" (error-message-string err))
+ nil))))
(defun dir-locals-set-directory-class (directory class &optional mtime)
"Declare that the DIRECTORY root is an instance of CLASS.
(dir-name nil))
(cond
((stringp variables-file)
- (setq dir-name (if (buffer-file-name) (file-name-directory (buffer-file-name)) default-directory))
+ (setq dir-name (if (buffer-file-name)
+ (file-name-directory (buffer-file-name))
+ default-directory))
(setq class (dir-locals-read-from-file variables-file)))
((consp variables-file)
(setq dir-name (nth 0 variables-file))
(and buffer (not (eq buffer (current-buffer)))
(not no-query)
(not (y-or-n-p (format "A buffer is visiting %s; proceed? "
- filename)))
+ filename)))
(error "Aborted")))
(or (equal filename buffer-file-name)
(progn
(rename-file real-file-name backupname t)
(setq setmodes (list modes context backupname)))
(file-error
- ;; If trouble writing the backup, write it in ~.
- (setq backupname (expand-file-name
- (convert-standard-filename
- "~/%backup%~")))
+ ;; If trouble writing the backup, write it in
+ ;; .emacs.d/%backup%.
+ (setq backupname (locate-user-emacs-file "%backup%~"))
(message "Cannot write backup file; backing up in %s"
backupname)
(sleep-for 1)
(and context
(set-file-selinux-context to-name context)))
+(defvar file-name-version-regexp
+ "\\(?:~\\|\\.~[-[:alnum:]:#@^._]+~\\)"
+ "Regular expression matching the backup/version part of a file name.
+Used by `file-name-sans-versions'.")
+
(defun file-name-sans-versions (name &optional keep-backup-version)
"Return file NAME sans backup versions or strings.
This is a separate procedure so your site-init or startup file can
redefine it.
If the optional argument KEEP-BACKUP-VERSION is non-nil,
-we do not remove backup version numbers, only true file version numbers."
+we do not remove backup version numbers, only true file version numbers.
+See also `file-name-version-regexp'."
(let ((handler (find-file-name-handler name 'file-name-sans-versions)))
(if handler
(funcall handler 'file-name-sans-versions name keep-backup-version)
(substring name 0
- (if keep-backup-version
- (length name)
- (or (string-match "\\.~[-[:alnum:]:#@^._]+~\\'" name)
- (string-match "~\\'" name)
- (length name)))))))
+ (unless keep-backup-version
+ (string-match (concat file-name-version-regexp "\\'")
+ name))))))
(defun file-ownership-preserved-p (file)
"Return t if deleting FILE and rewriting it would preserve the owner."
(dremote (file-remote-p directory)))
(if ;; Conditions for separate trees
(or
- ;; Test for different drives on DOS/Windows
+ ;; Test for different filesystems on DOS/Windows
(and
;; Should `cygwin' really be included here? --stef
(memq system-type '(ms-dos cygwin windows-nt))
- (not (eq t (compare-strings filename 0 2 directory 0 2))))
+ (or
+ ;; Test for different drive letters
+ (not (eq t (compare-strings filename 0 2 directory 0 2)))
+ ;; Test for UNCs on different servers
+ (not (eq t (compare-strings
+ (progn
+ (if (string-match "\\`//\\([^:/]+\\)/" filename)
+ (match-string 1 filename)
+ ;; Windows file names cannot have ? in
+ ;; them, so use that to detect when
+ ;; neither FILENAME nor DIRECTORY is a
+ ;; UNC.
+ "?"))
+ 0 nil
+ (progn
+ (if (string-match "\\`//\\([^:/]+\\)/" directory)
+ (match-string 1 directory)
+ "?"))
+ 0 nil t)))))
;; Test for different remote file system identification
(not (equal fremote dremote)))
filename
(or (verify-visited-file-modtime (current-buffer))
(not (file-exists-p buffer-file-name))
(yes-or-no-p
- (format "%s has changed since visited or saved. Save anyway? "
- (file-name-nondirectory buffer-file-name)))
+ (format
+ "%s has changed since visited or saved. Save anyway? "
+ (file-name-nondirectory buffer-file-name)))
(error "Save not confirmed"))
(save-restriction
(widen)
(if (not (file-exists-p buffer-file-name))
(error "Directory %s write-protected" dir)
(if (yes-or-no-p
- (format "File %s is write-protected; try to save anyway? "
- (file-name-nondirectory
- buffer-file-name)))
+ (format
+ "File %s is write-protected; try to save anyway? "
+ (file-name-nondirectory
+ buffer-file-name)))
(setq tempsetmodes t)
(error "Attempt to save to a file which you aren't allowed to write"))))))
(or buffer-backed-up
(setq buffer-backed-up nil))))))
setmodes))
-(defun diff-buffer-with-file (&optional buffer)
- "View the differences between BUFFER and its associated file.
-This requires the external program `diff' to be in your `exec-path'."
- (interactive "bBuffer: ")
- (with-current-buffer (get-buffer (or buffer (current-buffer)))
- (if (and buffer-file-name
- (file-exists-p buffer-file-name))
- (let ((tempfile (make-temp-file "buffer-content-")))
- (unwind-protect
- (progn
- (write-region nil nil tempfile nil 'nomessage)
- (diff buffer-file-name tempfile nil t)
- (sit-for 0))
- (when (file-exists-p tempfile)
- (delete-file tempfile))))
- (message "Buffer %s has no associated file on disc" (buffer-name))
- ;; Display that message for 1 second so that user can read it
- ;; in the minibuffer.
- (sit-for 1)))
- ;; return always nil, so that save-buffers-kill-emacs will not move
- ;; over to the next unsaved buffer when calling `d'.
- nil)
+(declare-function diff-no-select "diff"
+ (old new &optional switches no-async buf))
(defvar save-some-buffers-action-alist
`((?\C-r
(?d ,(lambda (buf)
(if (null (buffer-file-name buf))
(message "Not applicable: no file")
- (save-window-excursion (diff-buffer-with-file buf))
- (if (not enable-recursive-minibuffers)
- (progn (display-buffer (get-buffer-create "*Diff*"))
- (setq other-window-scroll-buffer "*Diff*"))
- (view-buffer (get-buffer-create "*Diff*")
- (lambda (_) (exit-recursive-edit)))
- (recursive-edit)))
+ (require 'diff) ;for diff-no-select.
+ (let ((diffbuf (diff-no-select (buffer-file-name buf) buf
+ nil 'noasync)))
+ (if (not enable-recursive-minibuffers)
+ (progn (display-buffer diffbuf)
+ (setq other-window-scroll-buffer diffbuf))
+ (view-buffer diffbuf (lambda (_) (exit-recursive-edit)))
+ (recursive-edit))))
;; Return nil to ask about BUF again.
nil)
,(purecopy "view changes in this buffer")))
(progn
(if (or arg
(eq save-abbrevs 'silently)
- (y-or-n-p (format "Save abbrevs in %s? "
- abbrev-file-name)))
+ (y-or-n-p (format "Save abbrevs in %s? " abbrev-file-name)))
(write-abbrev-file nil))
;; Don't keep bothering user if he says no.
(setq abbrevs-changed nil)
(force-mode-line-update))))
(defun make-directory (dir &optional parents)
- "Create the directory DIR and any nonexistent parent dirs.
-If DIR already exists as a directory, signal an error, unless PARENTS is set.
+ "Create the directory DIR and optionally any nonexistent parent dirs.
+If DIR already exists as a directory, signal an error, unless
+PARENTS is non-nil.
-Interactively, the default choice of directory to create
-is the current default directory for file names.
-That is useful when you have visited a file in a nonexistent directory.
+Interactively, the default choice of directory to create is the
+current buffer's default directory. That is useful when you have
+visited a file in a nonexistent directory.
-Noninteractively, the second (optional) argument PARENTS says whether
-to create parent directories if they don't exist. Interactively,
-this happens by default."
+Noninteractively, the second (optional) argument PARENTS, if
+non-nil, says whether to create parent directories that don't
+exist. Interactively, this happens by default."
(interactive
(list (read-file-name "Make directory: " default-directory default-directory
nil nil)
(defconst directory-files-no-dot-files-regexp
"^\\([^.]\\|\\.\\([^.]\\|\\..\\)\\).*"
- "Regexp of file names excluging \".\" an \"..\".")
+ "Regexp matching any file name except \".\" and \"..\".")
(defun delete-directory (directory &optional recursive trash)
"Delete the directory named DIRECTORY. Does not follow symlinks.
(defun kill-buffer-ask (buffer)
"Kill BUFFER if confirmed."
- (when (yes-or-no-p
- (format "Buffer %s %s. Kill? " (buffer-name buffer)
- (if (buffer-modified-p buffer)
- "HAS BEEN EDITED" "is unmodified")))
+ (when (yes-or-no-p (format "Buffer %s %s. Kill? "
+ (buffer-name buffer)
+ (if (buffer-modified-p buffer)
+ "HAS BEEN EDITED" "is unmodified")))
(kill-buffer buffer)))
(defun kill-some-buffers (&optional list)
(defun get-free-disk-space (dir)
"Return the amount of free space on directory DIR's file system.
-The result is a string that gives the number of free 1KB blocks,
-or nil if the system call or the program which retrieve the information
-fail. It returns also nil when DIR is a remote directory.
-
-This function calls `file-system-info' if it is available, or invokes the
-program specified by `directory-free-space-program' if that is non-nil."
+The return value is a string describing the amount of free
+space (normally, the number of free 1KB blocks).
+
+This function calls `file-system-info' if it is available, or
+invokes the program specified by `directory-free-space-program'
+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)
;; Try to find the number of free blocks. Non-Posix systems don't
;; always have df, but might have an equivalent system call.
directory-free-space-args
dir)
0)))
- ;; Usual format is a header line followed by a line of
- ;; numbers.
+ ;; Assume that the "available" column is before the
+ ;; "capacity" column. Find the "%" and scan backward.
(goto-char (point-min))
(forward-line 1)
- (if (not (eobp))
- (progn
- ;; Move to the end of the "available blocks" number.
- (skip-chars-forward "^ \t")
- (forward-word 3)
- ;; Copy it into AVAILABLE.
- (let ((end (point)))
- (forward-word -1)
- (buffer-substring (point) end))))))))))
+ (when (re-search-forward
+ "[[:space:]]+[^[:space:]]+%[^%]*$"
+ (line-end-position) t)
+ (goto-char (match-beginning 0))
+ (let ((endpt (point)))
+ (skip-chars-backward "^[:space:]")
+ (buffer-substring-no-properties (point) endpt)))))))))
;; The following expression replaces `dired-move-to-filename-regexp'.
(defvar directory-listing-before-filename-regexp
(define-key ctl-x-5-map "r" 'find-file-read-only-other-frame)
(define-key ctl-x-5-map "\C-o" 'display-buffer-other-frame)
-;; arch-tag: bc68d3ea-19ca-468b-aac6-3a4a7766101f
;;; files.el ends here