Switch to recommended form of GPLv3 permissions notice.
[bpt/emacs.git] / lisp / files.el
CommitLineData
c0274f38
ER
1;;; files.el --- file input and output commands for Emacs
2
aaef169d
TTN
3;; Copyright (C) 1985, 1986, 1987, 1992, 1993, 1994, 1995, 1996,
4;; 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
409cc4a3 5;; 2006, 2007, 2008 Free Software Foundation, Inc.
b4da00e9 6
3a801d0c
ER
7;; Maintainer: FSF
8
b4da00e9
RM
9;; This file is part of GNU Emacs.
10
eb3fa2cf 11;; GNU Emacs is free software: you can redistribute it and/or modify
b4da00e9 12;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
b4da00e9
RM
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
eb3fa2cf 22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
b4da00e9 23
e41b2db1
ER
24;;; Commentary:
25
26;; Defines most of Emacs's file- and directory-handling functions,
27;; including basic file visiting, backup generation, link handling,
28;; ITS-id version control, load- and write-hook handling, and the like.
29
e5167999
ER
30;;; Code:
31
26138670
JB
32(defvar font-lock-keywords)
33
34
21540597
RS
35(defgroup backup nil
36 "Backups of edited data files."
2a9fe1e2 37 :group 'files)
b4da00e9 38
21540597 39(defgroup find-file nil
2a9fe1e2
RS
40 "Finding files."
41 :group 'files)
21540597
RS
42
43
44(defcustom delete-auto-save-files t
ba83982b 45 "Non-nil means delete auto-save file when a buffer is saved or killed.
92631216 46
564af258 47Note that the auto-save file will not be deleted if the buffer is killed
92631216 48when it has unsaved changes."
21540597
RS
49 :type 'boolean
50 :group 'auto-save)
51
52(defcustom directory-abbrev-alist
b4da00e9 53 nil
ba83982b 54 "Alist of abbreviations for file directories.
b4da00e9
RM
55A list of elements of the form (FROM . TO), each meaning to replace
56FROM with TO when it appears in a directory name. This replacement is
57done when setting up the default directory of a newly visited file.
58*Every* FROM string should start with `^'.
59
4b690a83
RS
60FROM and TO should be equivalent names, which refer to the
61same directory. Do not use `~' in the TO strings;
62they should be ordinary absolute directory names.
65151a1b 63
b4da00e9
RM
64Use this feature when you have directories which you normally refer to
65via absolute symbolic links. Make TO the name of the link, and FROM
21540597
RS
66the name it is linked to."
67 :type '(repeat (cons :format "%v"
68 :value ("" . "")
69 (regexp :tag "From")
70 (regexp :tag "To")))
71 :group 'abbrev
72 :group 'find-file)
b4da00e9 73
5c6d31a4 74;; Turn off backup files on VMS since it has version numbers.
21540597 75(defcustom make-backup-files (not (eq system-type 'vax-vms))
ba83982b 76 "Non-nil means make a backup of a file the first time it is saved.
b4da00e9
RM
77This can be done by renaming the file or by copying.
78
79Renaming means that Emacs renames the existing file so that it is a
80backup file, then writes the buffer into a new file. Any other names
81that the old file had will now refer to the backup file. The new file
82is owned by you and its group is defaulted.
83
84Copying means that Emacs copies the existing file into the backup
85file, then writes the buffer on top of the existing file. Any other
86names that the old file had will now refer to the new (edited) file.
87The file's owner and group are unchanged.
88
89The choice of renaming or copying is controlled by the variables
ffc0e1ca
AS
90`backup-by-copying', `backup-by-copying-when-linked',
91`backup-by-copying-when-mismatch' and
92`backup-by-copying-when-privileged-mismatch'. See also `backup-inhibited'."
21540597
RS
93 :type 'boolean
94 :group 'backup)
b4da00e9
RM
95
96;; Do this so that local variables based on the file name
97;; are not overridden by the major mode.
98(defvar backup-inhibited nil
f862241d
RS
99 "Non-nil means don't make a backup, regardless of the other parameters.
100This variable is intended for use by making it local to a buffer.
101But it is local only if you make it local.")
b4da00e9
RM
102(put 'backup-inhibited 'permanent-local t)
103
21540597 104(defcustom backup-by-copying nil
ba83982b 105 "Non-nil means always use copying to create backup files.
21540597
RS
106See documentation of variable `make-backup-files'."
107 :type 'boolean
108 :group 'backup)
b4da00e9 109
21540597 110(defcustom backup-by-copying-when-linked nil
ba83982b 111 "Non-nil means use copying to create backups for files with multiple names.
b4da00e9 112This causes the alternate names to refer to the latest version as edited.
21540597
RS
113This variable is relevant only if `backup-by-copying' is nil."
114 :type 'boolean
115 :group 'backup)
b4da00e9 116
21540597 117(defcustom backup-by-copying-when-mismatch nil
ba83982b 118 "Non-nil means create backups by copying if this preserves owner or group.
b4da00e9
RM
119Renaming may still be used (subject to control of other variables)
120when it would not result in changing the owner or group of the file;
121that is, for files which are owned by you and whose group matches
122the default for a new file created there by you.
21540597
RS
123This variable is relevant only if `backup-by-copying' is nil."
124 :type 'boolean
125 :group 'backup)
b4da00e9 126
ffc0e1ca 127(defcustom backup-by-copying-when-privileged-mismatch 200
ba83982b 128 "Non-nil means create backups by copying to preserve a privileged owner.
ffc0e1ca
AS
129Renaming may still be used (subject to control of other variables)
130when it would not result in changing the owner of the file or if the owner
131has a user id greater than the value of this variable. This is useful
132when low-numbered uid's are used for special system users (such as root)
133that must maintain ownership of certain files.
134This variable is relevant only if `backup-by-copying' and
135`backup-by-copying-when-mismatch' are nil."
136 :type '(choice (const nil) integer)
137 :group 'backup)
138
ffc0e1ca 139(defvar backup-enable-predicate 'normal-backup-enable-predicate
b4da00e9 140 "Predicate that looks at a file name and decides whether to make backups.
37193ee6 141Called with an absolute file name as argument, it returns t to enable backup.")
b4da00e9 142
21540597 143(defcustom buffer-offer-save nil
ba83982b 144 "Non-nil in a buffer means always offer to save buffer on exit.
ffc0e1ca 145Do so even if the buffer is not visiting a file.
21540597
RS
146Automatically local in all buffers."
147 :type 'boolean
148 :group 'backup)
b4da00e9
RM
149(make-variable-buffer-local 'buffer-offer-save)
150
21540597 151(defcustom find-file-existing-other-name t
ba83982b 152 "Non-nil means find a file under alternative names, in existing buffers.
f3e23606 153This means if any existing buffer is visiting the file you want
21540597
RS
154under another name, you get the existing buffer instead of a new buffer."
155 :type 'boolean
156 :group 'find-file)
f3e23606 157
21540597 158(defcustom find-file-visit-truename nil
f3e23606
RS
159 "*Non-nil means visit a file under its truename.
160The truename of a file is found by chasing all links
21540597
RS
161both at the file level and at the levels of the containing directories."
162 :type 'boolean
163 :group 'find-file)
290c2be5 164(put 'find-file-visit-truename 'safe-local-variable 'booleanp)
f3e23606 165
26b9ecbc 166(defcustom revert-without-query nil
ba83982b 167 "Specify which files should be reverted without query.
ebeb898f
RS
168The value is a list of regular expressions.
169If the file name matches one of these regular expressions,
db8c4866 170then `revert-buffer' reverts the file without querying
21540597 171if the file has changed on disk and you have not edited the buffer."
a0d809f2 172 :type '(repeat regexp)
21540597 173 :group 'find-file)
ebeb898f 174
f3e23606
RS
175(defvar buffer-file-number nil
176 "The device number and file number of the file visited in the current buffer.
177The value is a list of the form (FILENUM DEVNUM).
178This pair of numbers uniquely identifies the file.
179If the buffer is visiting a new file, the value is nil.")
180(make-variable-buffer-local 'buffer-file-number)
181(put 'buffer-file-number 'permanent-local t)
182
de88363f 183(defvar buffer-file-numbers-unique (not (memq system-type '(windows-nt)))
26b9ecbc 184 "Non-nil means that `buffer-file-number' uniquely identifies files.")
de88363f 185
e554eeb7
RS
186(defvar buffer-file-read-only nil
187 "Non-nil if visited file was read-only when visited.")
188(make-variable-buffer-local 'buffer-file-read-only)
189
388d6ab5 190(defcustom temporary-file-directory
eb61b61b
RS
191 (file-name-as-directory
192 (cond ((memq system-type '(ms-dos windows-nt))
193 (or (getenv "TEMP") (getenv "TMPDIR") (getenv "TMP") "c:/temp"))
194 ((memq system-type '(vax-vms axp-vms))
195 (or (getenv "TMPDIR") (getenv "TMP") (getenv "TEMP") "SYS$SCRATCH:"))
196 (t
197 (or (getenv "TMPDIR") (getenv "TMP") (getenv "TEMP") "/tmp"))))
388d6ab5
RS
198 "The directory for writing temporary files."
199 :group 'files
200 :type 'directory)
eb61b61b 201
388d6ab5 202(defcustom small-temporary-file-directory
eb61b61b
RS
203 (if (eq system-type 'ms-dos) (getenv "TMPDIR"))
204 "The directory for writing small temporary files.
205If non-nil, this directory is used instead of `temporary-file-directory'
206by programs that create small temporary files. This is for systems that
388d6ab5
RS
207have fast storage with limited space, such as a RAM disk."
208 :group 'files
bab6eadb 209 :type '(choice (const nil) directory))
eb61b61b
RS
210
211;; The system null device. (Should reference NULL_DEVICE from C.)
212(defvar null-device "/dev/null" "The system null device.")
213
73e6adaa
DN
214(declare-function msdos-long-file-names "msdos.c")
215(declare-function w32-long-file-name "w32proc.c")
e8ffb999
DN
216(declare-function dired-get-filename "dired" (&optional localp no-error-if-not-filep))
217(declare-function dired-unmark "dired" (arg))
218(declare-function dired-do-flagged-delete "dired" (&optional nomessage))
219(declare-function dos-8+3-filename "dos-fns" (filename))
220(declare-function vms-read-directory "vms-patch" (dirname switches buffer))
221(declare-function view-mode-disable "view" ())
222
30966847
EZ
223(defvar file-name-invalid-regexp
224 (cond ((and (eq system-type 'ms-dos) (not (msdos-long-file-names)))
9959c16e 225 (concat "^\\([^A-Z[-`a-z]\\|..+\\)?:\\|" ; colon except after drive
30966847 226 "[+, ;=|<>\"?*]\\|\\[\\|\\]\\|" ; invalid characters
12f68d3f 227 "[\000-\037]\\|" ; control characters
30966847
EZ
228 "\\(/\\.\\.?[^/]\\)\\|" ; leading dots
229 "\\(/[^/.]+\\.[^/.]*\\.\\)")) ; more than a single dot
c60ee5e7 230 ((memq system-type '(ms-dos windows-nt cygwin))
9959c16e 231 (concat "^\\([^A-Z[-`a-z]\\|..+\\)?:\\|" ; colon except after drive
12f68d3f 232 "[|<>\"?*\000-\037]")) ; invalid characters
30966847
EZ
233 (t "[\000]"))
234 "Regexp recognizing file names which aren't allowed by the filesystem.")
235
21540597 236(defcustom file-precious-flag nil
ba83982b 237 "Non-nil means protect against I/O errors while saving files.
560f4415 238Some modes set this non-nil in particular buffers.
4b7271c1
KH
239
240This feature works by writing the new contents into a temporary file
241and then renaming the temporary file to replace the original.
242In this way, any I/O error in writing leaves the original untouched,
243and there is never any instant where the file is nonexistent.
244
245Note that this feature forces backups to be made by copying.
560f4415 246Yet, at the same time, saving a precious file
21540597
RS
247breaks any hard links between it and other files."
248 :type 'boolean
249 :group 'backup)
b4da00e9 250
21540597 251(defcustom version-control nil
ba83982b 252 "Control use of version numbers for backup files.
93e7eeb4
JB
253When t, make numeric backup versions unconditionally.
254When nil, make them for files that have some already.
255The value `never' means do not make them."
e48807d1
AS
256 :type '(choice (const :tag "Never" never)
257 (const :tag "If existing" nil)
258 (other :tag "Always" t))
21540597
RS
259 :group 'backup
260 :group 'vc)
e48335de
RS
261(put 'version-control 'safe-local-variable
262 '(lambda (x) (or (booleanp x) (equal x 'never))))
21540597
RS
263
264(defcustom dired-kept-versions 2
ba83982b 265 "When cleaning directory, number of versions to keep."
21540597
RS
266 :type 'integer
267 :group 'backup
268 :group 'dired)
269
270(defcustom delete-old-versions nil
ba83982b 271 "If t, delete excess backup versions silently.
21540597
RS
272If nil, ask confirmation. Any other value prevents any trimming."
273 :type '(choice (const :tag "Delete" t)
274 (const :tag "Ask" nil)
e48807d1 275 (other :tag "Leave" other))
21540597
RS
276 :group 'backup)
277
278(defcustom kept-old-versions 2
ba83982b 279 "Number of oldest versions to keep when a new numbered backup is made."
21540597
RS
280 :type 'integer
281 :group 'backup)
631c8020 282(put 'kept-old-versions 'safe-local-variable 'integerp)
21540597
RS
283
284(defcustom kept-new-versions 2
ba83982b 285 "Number of newest versions to keep when a new numbered backup is made.
21540597
RS
286Includes the new backup. Must be > 0"
287 :type 'integer
288 :group 'backup)
631c8020 289(put 'kept-new-versions 'safe-local-variable 'integerp)
b4da00e9 290
21540597 291(defcustom require-final-newline nil
ba83982b 292 "Whether to add a newline automatically at the end of the file.
f4206092
RS
293
294A value of t means do this only when the file is about to be saved.
295A value of `visit' means do this right after the file is visited.
296A value of `visit-save' means do it at both of those times.
297Any other non-nil value means ask user whether to add a newline, when saving.
756c496f 298A value of nil means don't add newlines.
f4206092
RS
299
300Certain major modes set this locally to the value obtained
301from `mode-require-final-newline'."
302 :type '(choice (const :tag "When visiting" visit)
303 (const :tag "When saving" t)
304 (const :tag "When visiting or saving" visit-save)
93d1963d 305 (const :tag "Don't add newlines" nil)
0776da52 306 (other :tag "Ask each time" ask))
21540597 307 :group 'editing-basics)
b4da00e9 308
f4206092 309(defcustom mode-require-final-newline t
ba83982b 310 "Whether to add a newline at end of file, in certain major modes.
f4206092 311Those modes set `require-final-newline' to this value when you enable them.
0776da52 312They do so because they are often used for files that are supposed
f4206092
RS
313to end in newlines, and the question is how to arrange that.
314
315A value of t means do this only when the file is about to be saved.
316A value of `visit' means do this right after the file is visited.
317A value of `visit-save' means do it at both of those times.
5e9961be 318Any other non-nil value means ask user whether to add a newline, when saving.
5e9961be 319
756c496f
JB
320A value of nil means do not add newlines. That is a risky choice in this
321variable since this value is used for modes for files that ought to have
322final newlines. So if you set this to nil, you must explicitly check and
323add a final newline, whenever you save a file that really needs one."
f4206092
RS
324 :type '(choice (const :tag "When visiting" visit)
325 (const :tag "When saving" t)
326 (const :tag "When visiting or saving" visit-save)
93d1963d
RS
327 (const :tag "Don't add newlines" nil)
328 (other :tag "Ask each time" ask))
f4206092 329 :group 'editing-basics
bf247b6e 330 :version "22.1")
f4206092 331
21540597 332(defcustom auto-save-default t
ba83982b 333 "Non-nil says by default do auto-saving of every file-visiting buffer."
21540597
RS
334 :type 'boolean
335 :group 'auto-save)
b4da00e9 336
21540597 337(defcustom auto-save-visited-file-name nil
ba83982b 338 "Non-nil says auto-save a buffer in the file it is visiting, when practical.
21540597
RS
339Normally auto-save files are written under other names."
340 :type 'boolean
341 :group 'auto-save)
b4da00e9 342
ffc0e1ca 343(defcustom auto-save-file-name-transforms
b1e5937c 344 `(("\\`/[^/]*:\\([^/]*/\\)*\\([^/]*\\)\\'"
747981b0
EZ
345 ;; Don't put "\\2" inside expand-file-name, since it will be
346 ;; transformed to "/2" on DOS/Windows.
a0b60c33 347 ,(concat temporary-file-directory "\\2") t))
ba83982b 348 "Transforms to apply to buffer file name before making auto-save file name.
a0b60c33 349Each transform is a list (REGEXP REPLACEMENT UNIQUIFY):
ffc0e1ca
AS
350REGEXP is a regular expression to match against the file name.
351If it matches, `replace-match' is used to replace the
352matching part with REPLACEMENT.
a0b60c33 353If the optional element UNIQUIFY is non-nil, the auto-save file name is
36236b72 354constructed by taking the directory part of the replaced file-name,
a0b60c33
GM
355concatenated with the buffer file name with all directory separators
356changed to `!' to prevent clashes. This will not work
357correctly if your filesystem truncates the resulting name.
358
ffc0e1ca
AS
359All the transforms in the list are tried, in the order they are listed.
360When one transform applies, its result is final;
361no further transforms are tried.
362
a2899d6c
KG
363The default value is set up to put the auto-save file into the
364temporary directory (see the variable `temporary-file-directory') for
a0b60c33
GM
365editing a remote file.
366
367On MS-DOS filesystems without long names this variable is always
368ignored."
ffc0e1ca 369 :group 'auto-save
a0b60c33
GM
370 :type '(repeat (list (string :tag "Regexp") (string :tag "Replacement")
371 (boolean :tag "Uniquify")))
ffc0e1ca
AS
372 :version "21.1")
373
88b36776 374(defcustom save-abbrevs t
ba83982b 375 "Non-nil means save word abbrevs too when files are saved.
02c6a1cc
EZ
376If `silently', don't ask the user before saving."
377 :type '(choice (const t) (const nil) (const silently))
21540597 378 :group 'abbrev)
b4da00e9 379
21540597 380(defcustom find-file-run-dired t
ba83982b 381 "Non-nil means allow `find-file' to visit directories.
ffc0e1ca 382To visit the directory, `find-file' runs `find-directory-functions'."
21540597
RS
383 :type 'boolean
384 :group 'find-file)
b4da00e9 385
ffc0e1ca 386(defcustom find-directory-functions '(cvs-dired-noselect dired-noselect)
ba83982b 387 "List of functions to try in sequence to visit a directory.
ffc0e1ca
AS
388Each function is called with the directory name as the sole argument
389and should return either a buffer or nil."
390 :type '(hook :options (cvs-dired-noselect dired-noselect))
391 :group 'find-file)
392
92966e6f
RS
393;;;It is not useful to make this a local variable.
394;;;(put 'find-file-not-found-hooks 'permanent-local t)
0370fe77 395(defvar find-file-not-found-functions nil
b4da00e9
RM
396 "List of functions to be called for `find-file' on nonexistent file.
397These functions are called as soon as the error is detected.
ffc0e1ca 398Variable `buffer-file-name' is already set up.
b4da00e9 399The functions are called in the order given until one of them returns non-nil.")
26b9ecbc
JB
400(define-obsolete-variable-alias 'find-file-not-found-hooks
401 'find-file-not-found-functions "22.1")
b4da00e9 402
92966e6f
RS
403;;;It is not useful to make this a local variable.
404;;;(put 'find-file-hooks 'permanent-local t)
cd6ef82d 405(define-obsolete-variable-alias 'find-file-hooks 'find-file-hook "22.1")
564af258 406(defcustom find-file-hook nil
b4da00e9
RM
407 "List of functions to be called after a buffer is loaded from a file.
408The buffer's local variables (if any) will have been processed before the
564af258
DL
409functions are called."
410 :group 'find-file
411 :type 'hook
412 :options '(auto-insert)
bf247b6e 413 :version "22.1")
b4da00e9 414
0370fe77 415(defvar write-file-functions nil
b4da00e9
RM
416 "List of functions to be called before writing out a buffer to a file.
417If one of them returns non-nil, the file is considered already written
8c0e7b73
JB
418and the rest are not called.
419These hooks are considered to pertain to the visited file.
0370fe77
SM
420So any buffer-local binding of this variable is discarded if you change
421the visited file name with \\[set-visited-file-name], but not when you
422change the major mode.
423
0eb0202f
LT
424This hook is not run if any of the functions in
425`write-contents-functions' returns non-nil. Both hooks pertain
426to how to save a buffer to file, for instance, choosing a suitable
427coding system and setting mode bits. (See Info
428node `(elisp)Saving Buffers'.) To perform various checks or
26b9ecbc 429updates before the buffer is saved, use `before-save-hook'.")
0370fe77 430(put 'write-file-functions 'permanent-local t)
26b9ecbc 431(define-obsolete-variable-alias 'write-file-hooks 'write-file-functions "22.1")
0370fe77
SM
432
433(defvar local-write-file-hooks nil)
b19f1da4
BF
434(make-variable-buffer-local 'local-write-file-hooks)
435(put 'local-write-file-hooks 'permanent-local t)
bf247b6e 436(make-obsolete-variable 'local-write-file-hooks 'write-file-functions "22.1")
8c0e7b73 437
0370fe77 438(defvar write-contents-functions nil
8c0e7b73
JB
439 "List of functions to be called before writing out a buffer to a file.
440If one of them returns non-nil, the file is considered already written
7dd11b37
LH
441and the rest are not called and neither are the functions in
442`write-file-functions'.
f82966e4
KH
443
444This variable is meant to be used for hooks that pertain to the
445buffer's contents, not to the particular visited file; thus,
446`set-visited-file-name' does not clear this variable; but changing the
693f800d
RS
447major mode does clear it.
448
0eb0202f
LT
449For hooks that _do_ pertain to the particular visited file, use
450`write-file-functions'. Both this variable and
451`write-file-functions' relate to how a buffer is saved to file.
452To perform various checks or updates before the buffer is saved,
453use `before-save-hook'.")
0370fe77 454(make-variable-buffer-local 'write-contents-functions)
26b9ecbc
JB
455(define-obsolete-variable-alias 'write-contents-hooks
456 'write-contents-functions "22.1")
b4da00e9 457
21540597 458(defcustom enable-local-variables t
ba83982b 459 "Control use of local variables in files you visit.
d355b270 460The value can be t, nil, :safe, :all, or something else.
5a6c1d87
CY
461
462A value of t means file local variables specifications are obeyed
a251756e
RS
463if all the specified variable values are safe; if any values are
464not safe, Emacs queries you, once, whether to set them all.
a5ce12c3
RS
465\(When you say yes to certain values, they are remembered as safe.)
466
467:safe means set the safe variables, and ignore the rest.
e58cec15
RS
468:all means set all variables, whether safe or not.
469 (Don't set it permanently to :all.)
756c496f 470A value of nil means always ignore the file local variables.
a251756e 471
a251756e 472Any other value means always query you once whether to set them all.
a5ce12c3
RS
473\(When you say yes to certain values, they are remembered as safe, but
474this has no effect when `enable-local-variables' is \"something else\".)
5a6c1d87 475
aa5fcebf
KH
476This variable also controls use of major modes specified in
477a -*- line.
b4da00e9 478
aa5fcebf
KH
479The command \\[normal-mode], when used interactively,
480always obeys file local variable specifications and the -*- line,
481and ignores this variable."
e58cec15 482 :type '(choice (const :tag "Query Unsafe" t)
a5ce12c3 483 (const :tag "Safe Only" :safe)
e58cec15 484 (const :tag "Do all" :all)
21540597 485 (const :tag "Ignore" nil)
e48807d1 486 (other :tag "Query" other))
21540597 487 :group 'find-file)
b4da00e9 488
da09b92b
RS
489(defvar local-enable-local-variables t
490 "Like `enable-local-variables' but meant for buffer-local bindings.
aa5fcebf 491The meaningful values are nil and non-nil. The default is non-nil.
da09b92b 492If a major mode sets this to nil, buffer-locally, then any local
aa5fcebf
KH
493variables list in the file will be ignored.
494
495This variable does not affect the use of major modes
496specified in a -*- line.")
da09b92b 497
21540597 498(defcustom enable-local-eval 'maybe
e442c62b 499 "Control processing of the \"variable\" `eval' in a file's local variables.
d207b766
RS
500The value can be t, nil or something else.
501A value of t means obey `eval' variables;
756c496f 502A value of nil means ignore them; anything else means query."
21540597
RS
503 :type '(choice (const :tag "Obey" t)
504 (const :tag "Ignore" nil)
e48807d1 505 (other :tag "Query" other))
21540597 506 :group 'find-file)
b4da00e9
RM
507
508;; Avoid losing in versions where CLASH_DETECTION is disabled.
509(or (fboundp 'lock-buffer)
231c4e10 510 (defalias 'lock-buffer 'ignore))
b4da00e9 511(or (fboundp 'unlock-buffer)
231c4e10 512 (defalias 'unlock-buffer 'ignore))
a7305f6e
RS
513(or (fboundp 'file-locked-p)
514 (defalias 'file-locked-p 'ignore))
93fe0a35 515
cb211eb2 516(defcustom view-read-only nil
ba83982b 517 "Non-nil means buffers visiting files read-only do so in view mode.
4c91443d
RS
518In fact, this means that all read-only buffers normally have
519View mode enabled, including buffers that are read-only because
520you visit a file you cannot alter, and buffers you make read-only
521using \\[toggle-read-only]."
cb211eb2
SM
522 :type 'boolean
523 :group 'view)
2a9fe1e2 524
5c471b12 525(defvar file-name-history nil
426aa4f0
EZ
526 "History list of file names entered in the minibuffer.
527
528Maximum length of the history list is determined by the value
529of `history-length', which see.")
5c471b12 530\f
1aa8fe46 531(put 'ange-ftp-completion-hook-function 'safe-magic t)
93fe0a35 532(defun ange-ftp-completion-hook-function (op &rest args)
ffc0e1ca
AS
533 "Provides support for ange-ftp host name completion.
534Runs the usual ange-ftp hook, but only for completion operations."
535 ;; Having this here avoids the need to load ange-ftp when it's not
536 ;; really in use.
93fe0a35
RS
537 (if (memq op '(file-name-completion file-name-all-completions))
538 (apply 'ange-ftp-hook-function op args)
57e81f57
RS
539 (let ((inhibit-file-name-handlers
540 (cons 'ange-ftp-completion-hook-function
541 (and (eq inhibit-file-name-operation op)
542 inhibit-file-name-handlers)))
543 (inhibit-file-name-operation op))
93fe0a35 544 (apply op args))))
567c1ca9
RS
545
546(defun convert-standard-filename (filename)
a576d8e2 547 "Convert a standard file's name to something suitable for the OS.
915b0bf0
JB
548This means to guarantee valid names and perhaps to canonicalize
549certain patterns.
550
f2430a0d
SM
551FILENAME should be an absolute file name since the conversion rules
552sometimes vary depending on the position in the file name. E.g. c:/foo
553is a valid DOS file name, but c:/bar/c:/foo is not.
554
915b0bf0
JB
555This function's standard definition is trivial; it just returns
556the argument. However, on Windows and DOS, replace invalid
18b28ef1
EZ
557characters. On DOS, make sure to obey the 8.3 limitations.
558In the native Windows build, turn Cygwin names into native names,
559and also turn slashes into backslashes if the shell requires it (see
a576d8e2
LT
560`w32-shell-dos-semantics').
561
562See Info node `(elisp)Standard File Names' for more details."
18b28ef1
EZ
563 (if (eq system-type 'cygwin)
564 (let ((name (copy-sequence filename))
565 (start 0))
566 ;; Replace invalid filename characters with !
567 (while (string-match "[?*:<>|\"\000-\037]" name start)
4b690a83 568 (aset name (match-beginning 0) ?!)
18b28ef1
EZ
569 (setq start (match-end 0)))
570 name)
571 filename))
5d4d17b8
KS
572
573(defun read-directory-name (prompt &optional dir default-dirname mustmatch initial)
574 "Read directory name, prompting with PROMPT and completing in directory DIR.
575Value is not expanded---you must call `expand-file-name' yourself.
25802eac
LT
576Default name to DEFAULT-DIRNAME if user exits with the same
577non-empty string that was inserted by this function.
44dce0fb
RS
578 (If DEFAULT-DIRNAME is omitted, DIR combined with INITIAL is used,
579 or just DIR if INITIAL is nil.)
25802eac
LT
580If the user exits with an empty minibuffer, this function returns
581an empty string. (This can only happen if the user erased the
582pre-inserted contents or if `insert-default-directory' is nil.)
5d4d17b8
KS
583Fourth arg MUSTMATCH non-nil means require existing directory's name.
584 Non-nil and non-t means also require confirmation after completion.
585Fifth arg INITIAL specifies text to start with.
25802eac
LT
586DIR should be an absolute directory name. It defaults to
587the value of `default-directory'."
5d4d17b8
KS
588 (unless dir
589 (setq dir default-directory))
54005870 590 (read-file-name prompt dir (or default-dirname
44dce0fb
RS
591 (if initial (expand-file-name initial dir)
592 dir))
593 mustmatch initial
5d4d17b8
KS
594 'file-directory-p))
595
b4da00e9
RM
596\f
597(defun pwd ()
598 "Show the current default directory."
599 (interactive nil)
600 (message "Directory %s" default-directory))
601
231c4e10
ER
602(defvar cd-path nil
603 "Value of the CDPATH environment variable, as a list.
9ee45b2c 604Not actually set up until the first time you use it.")
231c4e10
ER
605
606(defun parse-colon-path (cd-path)
ae135939 607 "Explode a search path into a list of directory names.
c5994cfa
JB
608Directories are separated by occurrences of `path-separator'
609\(which is colon in GNU and GNU-like systems)."
ffc0e1ca 610 ;; We could use split-string here.
231c4e10 611 (and cd-path
818286f4 612 (let (cd-list (cd-start 0) cd-colon)
306faa42
RS
613 (setq cd-path (concat cd-path path-separator))
614 (while (setq cd-colon (string-match path-separator cd-path cd-start))
231c4e10 615 (setq cd-list
9daefb36 616 (nconc cd-list
c52e4104
RS
617 (list (if (= cd-start cd-colon)
618 nil
619 (substitute-in-file-name
e33e80e4
RS
620 (file-name-as-directory
621 (substring cd-path cd-start cd-colon)))))))
231c4e10
ER
622 (setq cd-start (+ cd-colon 1)))
623 cd-list)))
624
625(defun cd-absolute (dir)
30c5ce9c 626 "Change current directory to given absolute file name DIR."
f4a0f59b
RS
627 ;; Put the name into directory syntax now,
628 ;; because otherwise expand-file-name may give some bad results.
b4da00e9
RM
629 (if (not (eq system-type 'vax-vms))
630 (setq dir (file-name-as-directory dir)))
f4a0f59b 631 (setq dir (abbreviate-file-name (expand-file-name dir)))
b4da00e9 632 (if (not (file-directory-p dir))
83c6f446
RS
633 (if (file-exists-p dir)
634 (error "%s is not a directory" dir)
31c691c1 635 (error "%s: no such directory" dir))
cfef87ad
TTN
636 (unless (file-executable-p dir)
637 (error "Cannot cd to %s: Permission denied" dir))
638 (setq default-directory dir)
639 (set (make-local-variable 'list-buffers-directory) dir)))
b4da00e9 640
231c4e10
ER
641(defun cd (dir)
642 "Make DIR become the current buffer's default directory.
ae135939
JB
643If your environment includes a `CDPATH' variable, try each one of
644that list of directories (separated by occurrences of
c5994cfa
JB
645`path-separator') when resolving a relative directory name.
646The path separator is colon in GNU and GNU-like systems."
dac4ea74 647 (interactive
5d4d17b8 648 (list (read-directory-name "Change default directory: "
2121cd9c
RM
649 default-directory default-directory
650 (and (member cd-path '(nil ("./")))
651 (null (getenv "CDPATH"))))))
30c5ce9c
RS
652 (if (file-name-absolute-p dir)
653 (cd-absolute (expand-file-name dir))
654 (if (null cd-path)
655 (let ((trypath (parse-colon-path (getenv "CDPATH"))))
656 (setq cd-path (or trypath (list "./")))))
657 (if (not (catch 'found
458c46fc 658 (mapc
30c5ce9c
RS
659 (function (lambda (x)
660 (let ((f (expand-file-name (concat x dir))))
661 (if (file-directory-p f)
662 (progn
663 (cd-absolute f)
664 (throw 'found t))))))
665 cd-path)
666 nil))
667 (error "No such directory found via CDPATH environment variable"))))
231c4e10 668
b4da00e9
RM
669(defun load-file (file)
670 "Load the Lisp file named FILE."
58195faa
DL
671 ;; This is a case where .elc makes a lot of sense.
672 (interactive (list (let ((completion-ignored-extensions
9ab80679 673 (remove ".elc" completion-ignored-extensions)))
58195faa
DL
674 (read-file-name "Load file: "))))
675 (load (expand-file-name file) nil nil t))
b4da00e9 676
38eea7c7
SM
677(defun locate-file (filename path &optional suffixes predicate)
678 "Search for FILENAME through PATH.
c7c4bc11
EZ
679If found, return the absolute file name of FILENAME, with its suffixes;
680otherwise return nil.
681PATH should be a list of directories to look in, like the lists in
682`exec-path' or `load-path'.
38eea7c7
SM
683If SUFFIXES is non-nil, it should be a list of suffixes to append to
684file name when searching. If SUFFIXES is nil, it is equivalent to '(\"\").
c7c4bc11 685Use '(\"/\") to disable PATH search, but still try the suffixes in SUFFIXES.
38eea7c7 686If non-nil, PREDICATE is used instead of `file-readable-p'.
e6f0ff92
RS
687PREDICATE can also be an integer to pass to the `access' system call,
688in which case file-name handlers are ignored. This usage is deprecated.
689
690For compatibility, PREDICATE can also be one of the symbols
691`executable', `readable', `writable', or `exists', or a list of
692one or more of those symbols."
38eea7c7
SM
693 (if (and predicate (symbolp predicate) (not (functionp predicate)))
694 (setq predicate (list predicate)))
695 (when (and (consp predicate) (not (functionp predicate)))
696 (setq predicate
697 (logior (if (memq 'executable predicate) 1 0)
698 (if (memq 'writable predicate) 2 0)
699 (if (memq 'readable predicate) 4 0))))
700 (locate-file-internal filename path suffixes predicate))
701
e8dab975
SM
702(defun locate-file-completion-table (dirs suffixes string pred action)
703 "Do completion for file names passed to `locate-file'."
2c3d8820 704 (if (file-name-absolute-p string)
e8dab975
SM
705 (let ((read-file-name-predicate pred))
706 (read-file-name-internal string nil action))
2c3d8820 707 (let ((names nil)
e8dab975 708 (suffix (concat (regexp-opt suffixes t) "\\'"))
2c3d8820 709 (string-dir (file-name-directory string)))
e8dab975 710 (dolist (dir dirs)
f2440e42
RS
711 (unless dir
712 (setq dir default-directory))
2c3d8820
SM
713 (if string-dir (setq dir (expand-file-name string-dir dir)))
714 (when (file-directory-p dir)
715 (dolist (file (file-name-all-completions
716 (file-name-nondirectory string) dir))
e1cac570 717 (add-to-list 'names (if string-dir (concat string-dir file) file))
2c3d8820
SM
718 (when (string-match suffix file)
719 (setq file (substring file 0 (match-beginning 0)))
720 (push (if string-dir (concat string-dir file) file) names)))))
e8dab975
SM
721 (complete-with-action action names string pred))))
722
723(defun locate-file-completion (string path-and-suffixes action)
724 "Do completion for file names passed to `locate-file'.
725PATH-AND-SUFFIXES is a pair of lists, (DIRECTORIES . SUFFIXES)."
726 (locate-file-completion-table (car path-and-suffixes)
727 (cdr path-and-suffixes)
728 string nil action))
729(make-obsolete 'locate-file-completion 'locate-file-completion-table "23.1")
2c3d8820 730
418fd375
SM
731(defun locate-dominating-file (file regexp)
732 "Look up the directory hierarchy from FILE for a file matching REGEXP."
418fd375 733 (catch 'found
5ffc4c05
SM
734 ;; `user' is not initialized yet because `file' may not exist, so we may
735 ;; have to walk up part of the hierarchy before we find the "initial UID".
736 (let ((user nil)
418fd375
SM
737 ;; Abbreviate, so as to stop when we cross ~/.
738 (dir (abbreviate-file-name (file-name-as-directory file)))
739 files)
5ffc4c05
SM
740 (while (and dir
741 ;; As a heuristic, we stop looking up the hierarchy of
742 ;; directories as soon as we find a directory belonging to
743 ;; another user. This should save us from looking in
744 ;; things like /net and /afs. This assumes that all the
745 ;; files inside a project belong to the same user.
746 (let ((prev-user user))
747 (setq user (nth 2 (file-attributes file)))
a02bf0c3 748 (or (null prev-user) (equal user prev-user))))
418fd375
SM
749 (if (setq files (directory-files dir 'full regexp))
750 (throw 'found (car files))
751 (if (equal dir
752 (setq dir (file-name-directory
753 (directory-file-name dir))))
754 (setq dir nil))))
755 nil)))
756
c3f6aa20
SM
757(defun executable-find (command)
758 "Search for COMMAND in `exec-path' and return the absolute file name.
759Return nil if COMMAND is not found anywhere in `exec-path'."
760 ;; Use 1 rather than file-executable-p to better match the behavior of
761 ;; call-process.
762 (locate-file command exec-path exec-suffixes 1))
763
b4da00e9
RM
764(defun load-library (library)
765 "Load the library named LIBRARY.
766This is an interface to the function `load'."
38eea7c7
SM
767 (interactive
768 (list (completing-read "Load library: "
e8dab975
SM
769 (apply-partially 'locate-file-completion-table
770 load-path
771 (get-load-suffixes)))))
b4da00e9 772 (load library))
5d68c2c2 773
ac25542d 774(defun file-remote-p (file &optional identification connected)
3f788773 775 "Test whether FILE specifies a location on a remote system.
8299c8a5
SM
776Returns nil or a string identifying the remote connection (ideally
777a prefix of FILE). For example, the remote identification for filename
778\"/user@host:/foo\" could be \"/user@host:\".
779A file is considered \"remote\" if accessing it is likely to be slower or
780less reliable than accessing local files.
781Furthermore, relative file names do not work across remote connections.
00d6fd04 782
ac25542d
MA
783IDENTIFICATION specifies which part of the identification shall
784be returned as string. IDENTIFICATION can be the symbol
785`method', `user' or `host'; any other value is handled like nil
786and means to return the complete identification string.
787
00d6fd04
MA
788If CONNECTED is non-nil, the function returns an identification only
789if FILE is located on a remote system, and a connection is established
790to that remote system.
791
792`file-remote-p' will never open a connection on its own."
04621aaa 793 (let ((handler (find-file-name-handler file 'file-remote-p)))
ff7affeb 794 (if handler
ac25542d 795 (funcall handler 'file-remote-p file identification connected)
04621aaa 796 nil)))
ff7affeb 797
ffc0e1ca 798(defun file-local-copy (file)
5d68c2c2
RS
799 "Copy the file FILE into a temporary file on this machine.
800Returns the name of the local copy, or nil, if FILE is directly
801accessible."
ffc0e1ca
AS
802 ;; This formerly had an optional BUFFER argument that wasn't used by
803 ;; anything.
6eaebaa2 804 (let ((handler (find-file-name-handler file 'file-local-copy)))
5d68c2c2
RS
805 (if handler
806 (funcall handler 'file-local-copy file)
807 nil)))
f3e23606 808
05ef1cda 809(defun file-truename (filename &optional counter prev-dirs)
f3e23606
RS
810 "Return the truename of FILENAME, which should be absolute.
811The truename of a file name is found by chasing symbolic links
812both at the level of the file and at the level of the directories
05ef1cda
RS
813containing it, until no links are left at any level.
814
89bf74f8 815\(fn FILENAME)" ;; Don't document the optional arguments.
b9963e32
JB
816 ;; COUNTER and PREV-DIRS are only used in recursive calls.
817 ;; COUNTER can be a cons cell whose car is the count of how many
818 ;; more links to chase before getting an error.
05ef1cda
RS
819 ;; PREV-DIRS can be a cons cell whose car is an alist
820 ;; of truenames we've just recently computed.
f2440e42
RS
821 (cond ((or (string= filename "") (string= filename "~"))
822 (setq filename (expand-file-name filename))
823 (if (string= filename "")
824 (setq filename "/")))
825 ((and (string= (substring filename 0 1) "~")
826 (string-match "~[^/]*/?" filename))
827 (let ((first-part
828 (substring filename 0 (match-end 0)))
829 (rest (substring filename (match-end 0))))
830 (setq filename (concat (expand-file-name first-part) rest)))))
831
05ef1cda 832 (or counter (setq counter (list 100)))
b505828b
RS
833 (let (done
834 ;; For speed, remove the ange-ftp completion handler from the list.
835 ;; We know it's not needed here.
836 ;; For even more speed, do this only on the outermost call.
837 (file-name-handler-alist
838 (if prev-dirs file-name-handler-alist
839 (let ((tem (copy-sequence file-name-handler-alist)))
840 (delq (rassq 'ange-ftp-completion-hook-function tem) tem)))))
841 (or prev-dirs (setq prev-dirs (list nil)))
b1667e6c
GV
842
843 ;; andrewi@harlequin.co.uk - none of the following code (except for
844 ;; invoking the file-name handler) currently applies on Windows
845 ;; (ie. there are no native symlinks), but there is an issue with
846 ;; case differences being ignored by the OS, and short "8.3 DOS"
847 ;; name aliases existing for all files. (The short names are not
848 ;; reported by directory-files, but can be used to refer to files.)
849 ;; It seems appropriate for file-truename to resolve these issues in
850 ;; the most natural way, which on Windows is to call the function
851 ;; `w32-long-file-name' - this returns the exact name of a file as
852 ;; it is stored on disk (expanding short name aliases with the full
853 ;; name in the process).
854 (if (eq system-type 'windows-nt)
06dd5ef7 855 (let ((handler (find-file-name-handler filename 'file-truename)))
b1667e6c
GV
856 ;; For file name that has a special handler, call handler.
857 ;; This is so that ange-ftp can save time by doing a no-op.
858 (if handler
859 (setq filename (funcall handler 'file-truename filename))
860 ;; If filename contains a wildcard, newname will be the old name.
06dd5ef7 861 (unless (string-match "[[*?]" filename)
5b373bd3
JB
862 ;; If filename exists, use the long name
863 (setq filename (or (w32-long-file-name filename) filename))))
b1667e6c
GV
864 (setq done t)))
865
05ef1cda
RS
866 ;; If this file directly leads to a link, process that iteratively
867 ;; so that we don't use lots of stack.
868 (while (not done)
869 (setcar counter (1- (car counter)))
870 (if (< (car counter) 0)
871 (error "Apparent cycle of symbolic links for %s" filename))
872 (let ((handler (find-file-name-handler filename 'file-truename)))
873 ;; For file name that has a special handler, call handler.
874 ;; This is so that ange-ftp can save time by doing a no-op.
875 (if handler
876 (setq filename (funcall handler 'file-truename filename)
877 done t)
fb145562 878 (let ((dir (or (file-name-directory filename) default-directory))
05ef1cda
RS
879 target dirfile)
880 ;; Get the truename of the directory.
881 (setq dirfile (directory-file-name dir))
882 ;; If these are equal, we have the (or a) root directory.
883 (or (string= dir dirfile)
884 ;; If this is the same dir we last got the truename for,
885 ;; save time--don't recalculate.
886 (if (assoc dir (car prev-dirs))
887 (setq dir (cdr (assoc dir (car prev-dirs))))
888 (let ((old dir)
889 (new (file-name-as-directory (file-truename dirfile counter prev-dirs))))
890 (setcar prev-dirs (cons (cons old new) (car prev-dirs)))
891 (setq dir new))))
892 (if (equal ".." (file-name-nondirectory filename))
893 (setq filename
894 (directory-file-name (file-name-directory (directory-file-name dir)))
895 done t)
896 (if (equal "." (file-name-nondirectory filename))
897 (setq filename (directory-file-name dir)
898 done t)
899 ;; Put it back on the file name.
900 (setq filename (concat dir (file-name-nondirectory filename)))
901 ;; Is the file name the name of a link?
902 (setq target (file-symlink-p filename))
903 (if target
904 ;; Yes => chase that link, then start all over
905 ;; since the link may point to a directory name that uses links.
906 ;; We can't safely use expand-file-name here
907 ;; since target might look like foo/../bar where foo
908 ;; is itself a link. Instead, we handle . and .. above.
909 (setq filename
910 (if (file-name-absolute-p target)
911 target
912 (concat dir target))
913 done nil)
914 ;; No, we are done!
915 (setq done t))))))))
916 filename))
5dbfdacd 917
302fcc98 918(defun file-chase-links (filename &optional limit)
5dadeb29 919 "Chase links in FILENAME until a name that is not a link.
302fcc98
RS
920Unlike `file-truename', this does not check whether a parent
921directory name is a symbolic link.
922If the optional argument LIMIT is a number,
923it means chase no more than that many links and then stop."
924 (let (tem (newname filename)
92464ae6 925 (count 0))
302fcc98
RS
926 (while (and (or (null limit) (< count limit))
927 (setq tem (file-symlink-p newname)))
9695aac6 928 (save-match-data
92464ae6 929 (if (and (null limit) (= count 100))
9695aac6
RS
930 (error "Apparent cycle of symbolic links for %s" filename))
931 ;; In the context of a link, `//' doesn't mean what Emacs thinks.
932 (while (string-match "//+" tem)
933 (setq tem (replace-match "/" nil nil tem)))
934 ;; Handle `..' by hand, since it needs to work in the
935 ;; target of any directory symlink.
936 ;; This code is not quite complete; it does not handle
937 ;; embedded .. in some cases such as ./../foo and foo/bar/../../../lose.
938 (while (string-match "\\`\\.\\./" tem)
939 (setq tem (substring tem 3))
940 (setq newname (expand-file-name newname))
941 ;; Chase links in the default dir of the symlink.
942 (setq newname
943 (file-chase-links
944 (directory-file-name (file-name-directory newname))))
945 ;; Now find the parent of that dir.
946 (setq newname (file-name-directory newname)))
947 (setq newname (expand-file-name tem (file-name-directory newname)))
92464ae6 948 (setq count (1+ count))))
5dadeb29 949 newname))
9bdbd98e 950
9e8bb7f7
RS
951(defun make-temp-file (prefix &optional dir-flag suffix)
952 "Create a temporary file.
953The returned file name (created by appending some random characters at the end
954of PREFIX, and expanding against `temporary-file-directory' if necessary),
955is guaranteed to point to a newly created empty file.
956You can then use `write-region' to write new data into the file.
957
958If DIR-FLAG is non-nil, create a new empty directory instead of a file.
959
960If SUFFIX is non-nil, add that at the end of the file name."
961 (let ((umask (default-file-modes))
962 file)
963 (unwind-protect
964 (progn
965 ;; Create temp files with strict access rights. It's easy to
966 ;; loosen them later, whereas it's impossible to close the
967 ;; time-window of loose permissions otherwise.
968 (set-default-file-modes ?\700)
969 (while (condition-case ()
970 (progn
971 (setq file
972 (make-temp-name
973 (expand-file-name prefix temporary-file-directory)))
974 (if suffix
975 (setq file (concat file suffix)))
976 (if dir-flag
977 (make-directory file)
978 (write-region "" nil file nil 'silent nil 'excl))
979 nil)
980 (file-already-exists t))
981 ;; the file was somehow created by someone else between
982 ;; `make-temp-name' and `write-region', let's try again.
983 nil)
984 file)
985 ;; Reset the umask.
986 (set-default-file-modes umask))))
987
9bdbd98e
KH
988(defun recode-file-name (file coding new-coding &optional ok-if-already-exists)
989 "Change the encoding of FILE's name from CODING to NEW-CODING.
990The value is a new name of FILE.
991Signals a `file-already-exists' error if a file of the new name
26b9ecbc
JB
992already exists unless optional fourth argument OK-IF-ALREADY-EXISTS
993is non-nil. A number as fourth arg means request confirmation if
9bdbd98e
KH
994the new name already exists. This is what happens in interactive
995use with M-x."
996 (interactive
997 (let ((default-coding (or file-name-coding-system
998 default-file-name-coding-system))
999 (filename (read-file-name "Recode filename: " nil nil t))
1000 from-coding to-coding)
1001 (if (and default-coding
1002 ;; We provide the default coding only when it seems that
1003 ;; the filename is correctly decoded by the default
1004 ;; coding.
1005 (let ((charsets (find-charset-string filename)))
1006 (and (not (memq 'eight-bit-control charsets))
1007 (not (memq 'eight-bit-graphic charsets)))))
1008 (setq from-coding (read-coding-system
1009 (format "Recode filename %s from (default %s): "
1010 filename default-coding)
1011 default-coding))
1012 (setq from-coding (read-coding-system
1013 (format "Recode filename %s from: " filename))))
cdec2ad7 1014
9bdbd98e
KH
1015 ;; We provide the default coding only when a user is going to
1016 ;; change the encoding not from the default coding.
1017 (if (eq from-coding default-coding)
1018 (setq to-coding (read-coding-system
1019 (format "Recode filename %s from %s to: "
1020 filename from-coding)))
1021 (setq to-coding (read-coding-system
1022 (format "Recode filename %s from %s to (default %s): "
1023 filename from-coding default-coding)
1024 default-coding)))
1025 (list filename from-coding to-coding)))
1026
1027 (let* ((default-coding (or file-name-coding-system
1028 default-file-name-coding-system))
1029 ;; FILE should have been decoded by DEFAULT-CODING.
1030 (encoded (encode-coding-string file default-coding))
1031 (newname (decode-coding-string encoded coding))
1032 (new-encoded (encode-coding-string newname new-coding))
1033 ;; Suppress further encoding.
1034 (file-name-coding-system nil)
1035 (default-file-name-coding-system nil)
1036 (locale-coding-system nil))
1037 (rename-file encoded new-encoded ok-if-already-exists)
1038 newname))
b4da00e9 1039\f
e4c0cccf
JL
1040(defun read-buffer-to-switch (prompt)
1041 "Read the name of a buffer to switch to and return as a string.
1042It is intended for `switch-to-buffer' family of commands since they
28bb43e1 1043need to omit the name of current buffer from the list of completions
e4c0cccf 1044and default values."
28bb43e1
SM
1045 (let ((rbts-completion-table (internal-complete-buffer-except)))
1046 (minibuffer-with-setup-hook
1047 (lambda () (setq minibuffer-completion-table rbts-completion-table))
1048 (read-buffer prompt (other-buffer (current-buffer))))))
e4c0cccf 1049
467ff692
RS
1050(defun switch-to-buffer-other-window (buffer &optional norecord)
1051 "Select buffer BUFFER in another window.
839857c7
LT
1052If BUFFER does not identify an existing buffer, then this function
1053creates a buffer with that name.
1054
1055When called from Lisp, BUFFER can be a buffer, a string \(a buffer name),
1056or nil. If BUFFER is nil, then this function chooses a buffer
1057using `other-buffer'.
467ff692 1058Optional second arg NORECORD non-nil means
4c6a4739 1059do not put this buffer at the front of the list of recently selected ones.
839857c7 1060This function returns the buffer it switched to.
4c6a4739
EZ
1061
1062This uses the function `display-buffer' as a subroutine; see its
1063documentation for additional customization information."
e4c0cccf
JL
1064 (interactive
1065 (list (read-buffer-to-switch "Switch to buffer in other window: ")))
cf44b9b7
RS
1066 (let ((pop-up-windows t)
1067 ;; Don't let these interfere.
1068 same-window-buffer-names same-window-regexps)
467ff692 1069 (pop-to-buffer buffer t norecord)))
b4da00e9 1070
467ff692
RS
1071(defun switch-to-buffer-other-frame (buffer &optional norecord)
1072 "Switch to buffer BUFFER in another frame.
1073Optional second arg NORECORD non-nil means
4c6a4739 1074do not put this buffer at the front of the list of recently selected ones.
a769e627 1075This function returns the buffer it switched to.
4c6a4739
EZ
1076
1077This uses the function `display-buffer' as a subroutine; see its
1078documentation for additional customization information."
e4c0cccf
JL
1079 (interactive
1080 (list (read-buffer-to-switch "Switch to buffer in other frame: ")))
cf44b9b7
RS
1081 (let ((pop-up-frames t)
1082 same-window-buffer-names same-window-regexps)
a769e627
AS
1083 (prog1
1084 (pop-to-buffer buffer t norecord)
1085 (raise-frame (window-frame (selected-window))))))
5bbbceb1 1086
ab9b3866
RS
1087(defun display-buffer-other-frame (buffer)
1088 "Switch to buffer BUFFER in another frame.
1089This uses the function `display-buffer' as a subroutine; see its
1090documentation for additional customization information."
1091 (interactive "BDisplay buffer in other frame: ")
1092 (let ((pop-up-frames t)
1093 same-window-buffer-names same-window-regexps
1094 (old-window (selected-window))
1095 new-window)
1096 (setq new-window (display-buffer buffer t))
38a79e33
SM
1097 ;; This may have been here in order to prevent the new frame from hiding
1098 ;; the old frame. But it does more harm than good.
1099 ;; Maybe we should call `raise-window' on the old-frame instead? --Stef
1100 ;;(lower-frame (window-frame new-window))
1101
1102 ;; This may have been here in order to make sure the old-frame gets the
1103 ;; focus. But not only can it cause an annoying flicker, with some
1104 ;; window-managers it just makes the window invisible, with no easy
1105 ;; way to recover it. --Stef
1106 ;;(make-frame-invisible (window-frame old-window))
1107 ;;(make-frame-visible (window-frame old-window))
1108 ))
ab9b3866 1109
a49a58f9
RS
1110(defvar find-file-default nil
1111 "Used within `find-file-read-args'.")
1112
a42e7db0
SM
1113(defmacro minibuffer-with-setup-hook (fun &rest body)
1114 "Add FUN to `minibuffer-setup-hook' while executing BODY.
1115BODY should use the minibuffer at most once.
1116Recursive uses of the minibuffer will not be affected."
1117 (declare (indent 1) (debug t))
1118 (let ((hook (make-symbol "setup-hook")))
44dce0fb
RS
1119 `(let (,hook)
1120 (setq ,hook
1121 (lambda ()
1122 ;; Clear out this hook so it does not interfere
1123 ;; with any recursive minibuffer usage.
1124 (remove-hook 'minibuffer-setup-hook ,hook)
2bd49e46 1125 (funcall ,fun)))
a42e7db0
SM
1126 (unwind-protect
1127 (progn
1128 (add-hook 'minibuffer-setup-hook ,hook)
1129 ,@body)
1130 (remove-hook 'minibuffer-setup-hook ,hook)))))
1131
75f6af19 1132(defcustom find-file-confirm-nonexistent-file nil
ad3d50ef
RS
1133 "If non-nil, `find-file' requires confirmation before visiting a new file."
1134 :group 'find-file
1135 :version "23.1"
1136 :type 'boolean)
14fd09e5 1137
05a7cb3d 1138(defun find-file-read-args (prompt mustmatch)
e6f0ff92
RS
1139 (list (let ((find-file-default
1140 (and buffer-file-name
a42e7db0
SM
1141 (abbreviate-file-name buffer-file-name))))
1142 (minibuffer-with-setup-hook
1143 (lambda () (setq minibuffer-default find-file-default))
1144 (read-file-name prompt nil default-directory mustmatch)))
b2a26f4e 1145 t))
e6f0ff92 1146
243ce842 1147(defun find-file (filename &optional wildcards)
b4da00e9
RM
1148 "Edit file FILENAME.
1149Switch to a buffer visiting file FILENAME,
243ce842 1150creating one if none already exists.
e6f0ff92
RS
1151Interactively, the default if you just type RET is the current directory,
1152but the visited file name is available through the minibuffer history:
1153type M-n to pull it into the minibuffer.
1154
4d4efd30
EZ
1155You can visit files on remote machines by specifying something
1156like /ssh:SOME_REMOTE_MACHINE:FILE for the file name. You can
1157also visit local files as a different user by specifying
6f174d77
EZ
1158/sudo::FILE for the file name.
1159See the Info node `(tramp)Filename Syntax' in the Tramp Info
1160manual, for more about this.
4d4efd30 1161
243ce842 1162Interactively, or if WILDCARDS is non-nil in a call from Lisp,
91174d63 1163expand wildcards (if any) and visit multiple files. You can
518dc5be 1164suppress wildcard expansion by setting `find-file-wildcards' to nil.
91174d63
RS
1165
1166To visit a file without any kind of conversion and without
1167automatically choosing a major mode, use \\[find-file-literally]."
14fd09e5
SM
1168 (interactive
1169 (find-file-read-args "Find file: "
75f6af19 1170 (if find-file-confirm-nonexistent-file 'confirm-only)))
5b8ed07b
RS
1171 (let ((value (find-file-noselect filename nil nil wildcards)))
1172 (if (listp value)
1173 (mapcar 'switch-to-buffer (nreverse value))
1174 (switch-to-buffer value))))
82d0954a 1175
243ce842 1176(defun find-file-other-window (filename &optional wildcards)
b4da00e9 1177 "Edit file FILENAME, in another window.
4d4efd30
EZ
1178
1179Like \\[find-file] (which see), but creates a new window or reuses
1180an existing one. See the function `display-buffer'.
e6f0ff92
RS
1181
1182Interactively, the default if you just type RET is the current directory,
1183but the visited file name is available through the minibuffer history:
1184type M-n to pull it into the minibuffer.
1185
243ce842
RS
1186Interactively, or if WILDCARDS is non-nil in a call from Lisp,
1187expand wildcards (if any) and visit multiple files."
14fd09e5
SM
1188 (interactive
1189 (find-file-read-args "Find file in other window: "
75f6af19 1190 (if find-file-confirm-nonexistent-file 'confirm-only)))
5b8ed07b
RS
1191 (let ((value (find-file-noselect filename nil nil wildcards)))
1192 (if (listp value)
1193 (progn
1194 (setq value (nreverse value))
a9d6a617
JL
1195 (cons (switch-to-buffer-other-window (car value))
1196 (mapcar 'switch-to-buffer (cdr value))))
5b8ed07b 1197 (switch-to-buffer-other-window value))))
243ce842
RS
1198
1199(defun find-file-other-frame (filename &optional wildcards)
f98955ea 1200 "Edit file FILENAME, in another frame.
4d4efd30
EZ
1201
1202Like \\[find-file] (which see), but creates a new frame or reuses
1203an existing one. See the function `display-buffer'.
e6f0ff92
RS
1204
1205Interactively, the default if you just type RET is the current directory,
1206but the visited file name is available through the minibuffer history:
1207type M-n to pull it into the minibuffer.
1208
243ce842
RS
1209Interactively, or if WILDCARDS is non-nil in a call from Lisp,
1210expand wildcards (if any) and visit multiple files."
14fd09e5
SM
1211 (interactive
1212 (find-file-read-args "Find file in other frame: "
75f6af19 1213 (if find-file-confirm-nonexistent-file 'confirm-only)))
5b8ed07b
RS
1214 (let ((value (find-file-noselect filename nil nil wildcards)))
1215 (if (listp value)
1216 (progn
1217 (setq value (nreverse value))
a9d6a617
JL
1218 (cons (switch-to-buffer-other-frame (car value))
1219 (mapcar 'switch-to-buffer (cdr value))))
5b8ed07b 1220 (switch-to-buffer-other-frame value))))
243ce842 1221
63c8abc4
EZ
1222(defun find-file-existing (filename)
1223 "Edit the existing file FILENAME.
4d4efd30 1224Like \\[find-file], but only allow a file that exists, and do not allow
63c8abc4
EZ
1225file names with wildcards."
1226 (interactive (nbutlast (find-file-read-args "Find existing file: " t)))
1227 (if (and (not (interactive-p)) (not (file-exists-p filename)))
1228 (error "%s does not exist" filename)
1229 (find-file filename)
1230 (current-buffer)))
46bfc73b 1231
243ce842 1232(defun find-file-read-only (filename &optional wildcards)
b4da00e9 1233 "Edit file FILENAME but don't allow changes.
4d4efd30 1234Like \\[find-file], but marks buffer as read-only.
b4da00e9 1235Use \\[toggle-read-only] to permit editing."
14fd09e5
SM
1236 (interactive
1237 (find-file-read-args "Find file read-only: "
75f6af19 1238 (if find-file-confirm-nonexistent-file 'confirm-only)))
a9d6a617
JL
1239 (unless (or (and wildcards find-file-wildcards
1240 (not (string-match "\\`/:" filename))
1241 (string-match "[[*?]" filename))
1242 (file-exists-p filename))
1243 (error "%s does not exist" filename))
1244 (let ((value (find-file filename wildcards)))
1245 (mapc (lambda (b) (with-current-buffer b (toggle-read-only 1)))
1246 (if (listp value) value (list value)))
1247 value))
b4da00e9 1248
243ce842 1249(defun find-file-read-only-other-window (filename &optional wildcards)
b4da00e9 1250 "Edit file FILENAME in another window but don't allow changes.
4d4efd30 1251Like \\[find-file-other-window], but marks buffer as read-only.
b4da00e9 1252Use \\[toggle-read-only] to permit editing."
14fd09e5
SM
1253 (interactive
1254 (find-file-read-args "Find file read-only other window: "
75f6af19 1255 (if find-file-confirm-nonexistent-file 'confirm-only)))
a9d6a617
JL
1256 (unless (or (and wildcards find-file-wildcards
1257 (not (string-match "\\`/:" filename))
1258 (string-match "[[*?]" filename))
1259 (file-exists-p filename))
1260 (error "%s does not exist" filename))
1261 (let ((value (find-file-other-window filename wildcards)))
1262 (mapc (lambda (b) (with-current-buffer b (toggle-read-only 1)))
1263 (if (listp value) value (list value)))
1264 value))
b4da00e9 1265
243ce842 1266(defun find-file-read-only-other-frame (filename &optional wildcards)
f98955ea 1267 "Edit file FILENAME in another frame but don't allow changes.
4d4efd30 1268Like \\[find-file-other-frame], but marks buffer as read-only.
5bbbceb1 1269Use \\[toggle-read-only] to permit editing."
14fd09e5
SM
1270 (interactive
1271 (find-file-read-args "Find file read-only other frame: "
75f6af19 1272 (if find-file-confirm-nonexistent-file 'confirm-only)))
a9d6a617
JL
1273 (unless (or (and wildcards find-file-wildcards
1274 (not (string-match "\\`/:" filename))
1275 (string-match "[[*?]" filename))
1276 (file-exists-p filename))
1277 (error "%s does not exist" filename))
1278 (let ((value (find-file-other-frame filename wildcards)))
1279 (mapc (lambda (b) (with-current-buffer b (toggle-read-only 1)))
1280 (if (listp value) value (list value)))
1281 value))
1282
1283(defun find-alternate-file-other-window (filename &optional wildcards)
60eaf370 1284 "Find file FILENAME as a replacement for the file in the next window.
a9d6a617
JL
1285This command does not select that window.
1286
4d4efd30
EZ
1287See \\[find-file] for the possible forms of the FILENAME argument.
1288
a9d6a617
JL
1289Interactively, or if WILDCARDS is non-nil in a call from Lisp,
1290expand wildcards (if any) and replace the file with multiple files."
60eaf370
RS
1291 (interactive
1292 (save-selected-window
1293 (other-window 1)
1294 (let ((file buffer-file-name)
1295 (file-name nil)
1296 (file-dir nil))
1297 (and file
1298 (setq file-name (file-name-nondirectory file)
1299 file-dir (file-name-directory file)))
1300 (list (read-file-name
a9d6a617
JL
1301 "Find alternate file: " file-dir nil nil file-name)
1302 t))))
60eaf370 1303 (if (one-window-p)
a9d6a617 1304 (find-file-other-window filename wildcards)
60eaf370
RS
1305 (save-selected-window
1306 (other-window 1)
a9d6a617 1307 (find-alternate-file filename wildcards))))
60eaf370 1308
a9d6a617 1309(defun find-alternate-file (filename &optional wildcards)
b4da00e9
RM
1310 "Find file FILENAME, select its buffer, kill previous buffer.
1311If the current buffer now contains an empty file that you just visited
a9d6a617
JL
1312\(presumably by mistake), use this command to visit the file you really want.
1313
4d4efd30
EZ
1314See \\[find-file] for the possible forms of the FILENAME argument.
1315
a9d6a617 1316Interactively, or if WILDCARDS is non-nil in a call from Lisp,
077f47e2
CY
1317expand wildcards (if any) and replace the file with multiple files.
1318
1319If the current buffer is an indirect buffer, or the base buffer
1320for one or more indirect buffers, the other buffer(s) are not
1321killed."
b4da00e9
RM
1322 (interactive
1323 (let ((file buffer-file-name)
1324 (file-name nil)
1325 (file-dir nil))
1326 (and file
1327 (setq file-name (file-name-nondirectory file)
1328 file-dir (file-name-directory file)))
a61f59b4 1329 (list (read-file-name
a9d6a617
JL
1330 "Find alternate file: " file-dir nil nil file-name)
1331 t)))
63fabbb4
RS
1332 (unless (run-hook-with-args-until-failure 'kill-buffer-query-functions)
1333 (error "Aborted"))
1334 (when (and (buffer-modified-p) (buffer-file-name))
38fde45d 1335 (if (yes-or-no-p (format "Buffer %s is modified; kill anyway? "
63fabbb4 1336 (buffer-name)))
38fde45d
CY
1337 (unless (yes-or-no-p "Kill and replace the buffer without saving it? ")
1338 (error "Aborted"))
1339 (save-buffer)))
b4da00e9
RM
1340 (let ((obuf (current-buffer))
1341 (ofile buffer-file-name)
8bb27285 1342 (onum buffer-file-number)
37c58ca6 1343 (odir dired-directory)
8bb27285 1344 (otrue buffer-file-truename)
b4da00e9 1345 (oname (buffer-name)))
baf9b8c4
RS
1346 (if (get-buffer " **lose**")
1347 (kill-buffer " **lose**"))
b4da00e9 1348 (rename-buffer " **lose**")
b4da00e9
RM
1349 (unwind-protect
1350 (progn
1351 (unlock-buffer)
7906c044
RS
1352 ;; This prevents us from finding the same buffer
1353 ;; if we specified the same file again.
a4ad4d96
RS
1354 (setq buffer-file-name nil)
1355 (setq buffer-file-number nil)
1356 (setq buffer-file-truename nil)
7906c044
RS
1357 ;; Likewise for dired buffers.
1358 (setq dired-directory nil)
a9d6a617 1359 (find-file filename wildcards))
63fabbb4
RS
1360 (when (eq obuf (current-buffer))
1361 ;; This executes if find-file gets an error
1362 ;; and does not really find anything.
1363 ;; We put things back as they were.
1364 ;; If find-file actually finds something, we kill obuf below.
1365 (setq buffer-file-name ofile)
1366 (setq buffer-file-number onum)
1367 (setq buffer-file-truename otrue)
7906c044 1368 (setq dired-directory odir)
63fabbb4
RS
1369 (lock-buffer)
1370 (rename-buffer oname)))
1371 (unless (eq (current-buffer) obuf)
d97a9ff3
RS
1372 (with-current-buffer obuf
1373 ;; We already asked; don't ask again.
1374 (let ((kill-buffer-query-functions))
1375 (kill-buffer obuf))))))
9b8ef27d 1376\f
b4da00e9
RM
1377(defun create-file-buffer (filename)
1378 "Create a suitably named buffer for visiting FILENAME, and return it.
1379FILENAME (sans directory) is used unchanged if that name is free;
661e8cd1
MC
1380otherwise a string <2> or <3> or ... is appended to get an unused name.
1381Spaces at the start of FILENAME (sans directory) are removed."
b4da00e9
RM
1382 (let ((lastname (file-name-nondirectory filename)))
1383 (if (string= lastname "")
1384 (setq lastname filename))
661e8cd1
MC
1385 (save-match-data
1386 (string-match "^ *\\(.*\\)" lastname)
1387 (generate-new-buffer (match-string 1 lastname)))))
b4da00e9 1388
5bbbceb1
JB
1389(defun generate-new-buffer (name)
1390 "Create and return a buffer with a name based on NAME.
29165787 1391Choose the buffer's name using `generate-new-buffer-name'."
5bbbceb1
JB
1392 (get-buffer-create (generate-new-buffer-name name)))
1393
ffc0e1ca
AS
1394(defcustom automount-dir-prefix "^/tmp_mnt/"
1395 "Regexp to match the automounter prefix in a directory name."
1396 :group 'files
1397 :type 'regexp)
e373f201 1398
ffb3a4db 1399(defvar abbreviated-home-dir nil
ffc0e1ca 1400 "The user's homedir abbreviated according to `directory-abbrev-alist'.")
ffb3a4db 1401
5bbbceb1 1402(defun abbreviate-file-name (filename)
29165787 1403 "Return a version of FILENAME shortened using `directory-abbrev-alist'.
fe4e58ec
EZ
1404This also substitutes \"~\" for the user's home directory (unless the
1405home directory is a root directory) and removes automounter prefixes
1406\(see the variable `automount-dir-prefix')."
e373f201 1407 ;; Get rid of the prefixes added by the automounter.
f663a1ce
RS
1408 (save-match-data
1409 (if (and automount-dir-prefix
1410 (string-match automount-dir-prefix filename)
1411 (file-exists-p (file-name-directory
1412 (substring filename (1- (match-end 0))))))
1413 (setq filename (substring filename (1- (match-end 0)))))
1414 (let ((tail directory-abbrev-alist))
1415 ;; If any elt of directory-abbrev-alist matches this name,
1416 ;; abbreviate accordingly.
1417 (while tail
1418 (if (string-match (car (car tail)) filename)
1419 (setq filename
1420 (concat (cdr (car tail)) (substring filename (match-end 0)))))
1421 (setq tail (cdr tail)))
1422 ;; Compute and save the abbreviated homedir name.
1423 ;; We defer computing this until the first time it's needed, to
1424 ;; give time for directory-abbrev-alist to be set properly.
1425 ;; We include a slash at the end, to avoid spurious matches
1426 ;; such as `/usr/foobar' when the home dir is `/usr/foo'.
1427 (or abbreviated-home-dir
1428 (setq abbreviated-home-dir
1429 (let ((abbreviated-home-dir "$foo"))
1430 (concat "^" (abbreviate-file-name (expand-file-name "~"))
e959542d 1431 "\\(/\\|\\'\\)"))))
f663a1ce
RS
1432
1433 ;; If FILENAME starts with the abbreviated homedir,
1434 ;; make it start with `~' instead.
1435 (if (and (string-match abbreviated-home-dir filename)
1436 ;; If the home dir is just /, don't change it.
1437 (not (and (= (match-end 0) 1)
1438 (= (aref filename 0) ?/)))
1439 ;; MS-DOS root directories can come with a drive letter;
1440 ;; Novell Netware allows drive letters beyond `Z:'.
1441 (not (and (or (eq system-type 'ms-dos)
1442 (eq system-type 'cygwin)
1443 (eq system-type 'windows-nt))
1444 (save-match-data
1445 (string-match "^[a-zA-`]:/$" filename)))))
5bbbceb1 1446 (setq filename
f663a1ce
RS
1447 (concat "~"
1448 (match-string 1 filename)
1449 (substring filename (match-end 0)))))
1450 filename)))
5bbbceb1 1451
21540597 1452(defcustom find-file-not-true-dirname-list nil
ba83982b 1453 "List of logical names for which visiting shouldn't save the true dirname.
1770543d
RS
1454On VMS, when you visit a file using a logical name that searches a path,
1455you may or may not want the visited file name to record the specific
1456directory where the file was found. If you *do not* want that, add the logical
21540597
RS
1457name to this list as a string."
1458 :type '(repeat (string :tag "Name"))
1459 :group 'find-file)
1770543d 1460
3a64a3cf 1461(defun find-buffer-visiting (filename &optional predicate)
138c44f6
KH
1462 "Return the buffer visiting file FILENAME (a string).
1463This is like `get-file-buffer', except that it checks for any buffer
1464visiting the same file, possibly under a different name.
a1b0c2a7
RS
1465If PREDICATE is non-nil, only buffers satisfying it are eligible,
1466and others are ignored.
138c44f6 1467If there is no such live buffer, return nil."
3a64a3cf
JB
1468 (let ((predicate (or predicate #'identity))
1469 (truename (abbreviate-file-name (file-truename filename))))
1470 (or (let ((buf (get-file-buffer filename)))
1471 (when (and buf (funcall predicate buf)) buf))
1472 (let ((list (buffer-list)) found)
1473 (while (and (not found) list)
1474 (save-excursion
1475 (set-buffer (car list))
1476 (if (and buffer-file-name
1477 (string= buffer-file-truename truename)
1478 (funcall predicate (current-buffer)))
1479 (setq found (car list))))
1480 (setq list (cdr list)))
1481 found)
1482 (let* ((attributes (file-attributes truename))
1483 (number (nthcdr 10 attributes))
1484 (list (buffer-list)) found)
1485 (and buffer-file-numbers-unique
02bb2aab 1486 (car-safe number) ;Make sure the inode is not just nil.
3a64a3cf
JB
1487 (while (and (not found) list)
1488 (with-current-buffer (car list)
1489 (if (and buffer-file-name
1490 (equal buffer-file-number number)
1491 ;; Verify this buffer's file number
1492 ;; still belongs to its file.
1493 (file-exists-p buffer-file-name)
1494 (equal (file-attributes buffer-file-truename)
1495 attributes)
1496 (funcall predicate (current-buffer)))
1497 (setq found (car list))))
1498 (setq list (cdr list))))
1499 found))))
9b8ef27d 1500\f
5de148a2 1501(defcustom find-file-wildcards t
ba83982b 1502 "Non-nil means file-visiting commands should handle wildcards.
5de148a2
RS
1503For example, if you specify `*.c', that would visit all the files
1504whose names match the pattern."
1505 :group 'files
3957c982 1506 :version "20.4"
5de148a2
RS
1507 :type 'boolean)
1508
ffc0e1ca 1509(defcustom find-file-suppress-same-file-warnings nil
ba83982b 1510 "Non-nil means suppress warning messages for symlinked files.
ffc0e1ca
AS
1511When nil, Emacs prints a warning when visiting a file that is already
1512visited, but with a different name. Setting this option to t
1513suppresses this warning."
1514 :group 'files
1515 :version "21.1"
1516 :type 'boolean)
1517
818286f4 1518(defcustom large-file-warning-threshold 10000000
5d648479
JPW
1519 "Maximum size of file above which a confirmation is requested.
1520When nil, never request confirmation."
1521 :group 'files
1522 :group 'find-file
bf247b6e 1523 :version "22.1"
5d648479 1524 :type '(choice integer (const :tag "Never request confirmation" nil)))
818286f4 1525
4954b81b 1526(defun abort-if-file-too-large (size op-type)
afe9998d 1527 "If file SIZE larger than `large-file-warning-threshold', allow user to abort.
4954b81b
AR
1528OP-TYPE specifies the file operation being performed (for message to user)."
1529 (when (and large-file-warning-threshold size
1530 (> size large-file-warning-threshold)
1531 (not (y-or-n-p
1532 (format "File %s is large (%dMB), really %s? "
1533 (file-name-nondirectory filename)
1534 (/ size 1048576) op-type))))
1535 (error "Aborted")))
1536
243ce842 1537(defun find-file-noselect (filename &optional nowarn rawfile wildcards)
b4da00e9
RM
1538 "Read file FILENAME into a buffer and return the buffer.
1539If a buffer exists visiting FILENAME, return that one, but
1540verify that the file has not changed since visited or saved.
82d0954a 1541The buffer is not selected, just returned to the caller.
26b9ecbc
JB
1542Optional second arg NOWARN non-nil means suppress any warning messages.
1543Optional third arg RAWFILE non-nil means the file is read literally.
1544Optional fourth arg WILDCARDS non-nil means do wildcard processing
5b8ed07b 1545and visit all the matching files. When wildcards are actually
a9d6a617
JL
1546used and expanded, return a list of buffers that are visiting
1547the various files."
e373f201
JB
1548 (setq filename
1549 (abbreviate-file-name
1550 (expand-file-name filename)))
b4da00e9 1551 (if (file-directory-p filename)
ffc0e1ca
AS
1552 (or (and find-file-run-dired
1553 (run-hook-with-args-until-success
1554 'find-directory-functions
1555 (if find-file-visit-truename
1556 (abbreviate-file-name (file-truename filename))
1557 filename)))
1558 (error "%s is a directory" filename))
243ce842
RS
1559 (if (and wildcards
1560 find-file-wildcards
f91fe604 1561 (not (string-match "\\`/:" filename))
5de148a2 1562 (string-match "[[*?]" filename))
ffc0e1ca
AS
1563 (let ((files (condition-case nil
1564 (file-expand-wildcards filename t)
1565 (error (list filename))))
5de148a2 1566 (find-file-wildcards nil))
f91fe604 1567 (if (null files)
ffc0e1ca 1568 (find-file-noselect filename)
648ec2ff 1569 (mapcar #'find-file-noselect files)))
5de148a2
RS
1570 (let* ((buf (get-file-buffer filename))
1571 (truename (abbreviate-file-name (file-truename filename)))
818286f4
SM
1572 (attributes (file-attributes truename))
1573 (number (nthcdr 10 attributes))
5de148a2
RS
1574 ;; Find any buffer for a file which has same truename.
1575 (other (and (not buf) (find-buffer-visiting filename))))
1576 ;; Let user know if there is a buffer with the same truename.
1577 (if other
1578 (progn
1579 (or nowarn
ffc0e1ca 1580 find-file-suppress-same-file-warnings
5de148a2
RS
1581 (string-equal filename (buffer-file-name other))
1582 (message "%s and %s are the same file"
1583 filename (buffer-file-name other)))
1584 ;; Optionally also find that buffer.
1585 (if (or find-file-existing-other-name find-file-visit-truename)
1586 (setq buf other))))
818286f4 1587 ;; Check to see if the file looks uncommonly large.
4954b81b
AR
1588 (when (not (or buf nowarn))
1589 (abort-if-file-too-large (nth 7 attributes) "open"))
5de148a2
RS
1590 (if buf
1591 ;; We are using an existing buffer.
2c5b1db7 1592 (let (nonexistent)
5de148a2
RS
1593 (or nowarn
1594 (verify-visited-file-modtime buf)
1595 (cond ((not (file-exists-p filename))
2c5b1db7
RS
1596 (setq nonexistent t)
1597 (message "File %s no longer exists!" filename))
5de148a2
RS
1598 ;; Certain files should be reverted automatically
1599 ;; if they have changed on disk and not in the buffer.
1600 ((and (not (buffer-modified-p buf))
1601 (let ((tail revert-without-query)
1602 (found nil))
1603 (while tail
1604 (if (string-match (car tail) filename)
1605 (setq found t))
1606 (setq tail (cdr tail)))
1607 found))
1608 (with-current-buffer buf
1609 (message "Reverting file %s..." filename)
1610 (revert-buffer t t)
1611 (message "Reverting file %s...done" filename)))
1612 ((yes-or-no-p
1613 (if (string= (file-name-nondirectory filename)
1614 (buffer-name buf))
1615 (format
1616 (if (buffer-modified-p buf)
1617 "File %s changed on disk. Discard your edits? "
1618 "File %s changed on disk. Reread from disk? ")
1619 (file-name-nondirectory filename))
ddd64da9
RS
1620 (format
1621 (if (buffer-modified-p buf)
5de148a2
RS
1622 "File %s changed on disk. Discard your edits in %s? "
1623 "File %s changed on disk. Reread from disk into %s? ")
1624 (file-name-nondirectory filename)
1625 (buffer-name buf))))
1626 (with-current-buffer buf
1627 (revert-buffer t t)))))
1628 (with-current-buffer buf
a8d002d2
GM
1629
1630 ;; Check if a formerly read-only file has become
e554eeb7
RS
1631 ;; writable and vice versa, but if the buffer agrees
1632 ;; with the new state of the file, that is ok too.
a8d002d2 1633 (let ((read-only (not (file-writable-p buffer-file-name))))
2c5b1db7
RS
1634 (unless (or nonexistent
1635 (eq read-only buffer-file-read-only)
e554eeb7 1636 (eq read-only buffer-read-only))
a8d002d2 1637 (when (or nowarn
36236b72 1638 (let ((question
a8d002d2
GM
1639 (format "File %s is %s on disk. Change buffer mode? "
1640 buffer-file-name
1641 (if read-only "read-only" "writable"))))
1642 (y-or-n-p question)))
e554eeb7
RS
1643 (setq buffer-read-only read-only)))
1644 (setq buffer-file-read-only read-only))
a8d002d2 1645
ef59dd3b
EZ
1646 (when (and (not (eq (not (null rawfile))
1647 (not (null find-file-literally))))
2c5b1db7 1648 (not nonexistent)
ef59dd3b
EZ
1649 ;; It is confusing to ask whether to visit
1650 ;; non-literally if they have the file in
1651 ;; hexl-mode.
1652 (not (eq major-mode 'hexl-mode)))
5de148a2 1653 (if (buffer-modified-p)
562ca538 1654 (if (y-or-n-p
674b7bae 1655 (format
562ca538
RS
1656 (if rawfile
1657 "The file %s is already visited normally,
1658and you have edited the buffer. Now you have asked to visit it literally,
1659meaning no coding system handling, format conversion, or local variables.
1660Emacs can only visit a file in one way at a time.
1661
1662Do you want to save the file, and visit it literally instead? "
1663 "The file %s is already visited literally,
1664meaning no coding system handling, format conversion, or local variables.
1665You have edited the buffer. Now you have asked to visit the file normally,
1666but Emacs can only visit a file in one way at a time.
1667
1668Do you want to save the file, and visit it normally instead? ")
1669 (file-name-nondirectory filename)))
5de148a2
RS
1670 (progn
1671 (save-buffer)
1672 (find-file-noselect-1 buf filename nowarn
1673 rawfile truename number))
562ca538 1674 (if (y-or-n-p
674b7bae 1675 (format
562ca538
RS
1676 (if rawfile
1677 "\
1678Do you want to discard your changes, and visit the file literally now? "
1679 "\
1680Do you want to discard your changes, and visit the file normally now? ")))
5de148a2
RS
1681 (find-file-noselect-1 buf filename nowarn
1682 rawfile truename number)
1683 (error (if rawfile "File already visited non-literally"
1684 "File already visited literally"))))
674b7bae
JB
1685 (if (y-or-n-p
1686 (format
562ca538
RS
1687 (if rawfile
1688 "The file %s is already visited normally.
1689You have asked to visit it literally,
1690meaning no coding system decoding, format conversion, or local variables.
1691But Emacs can only visit a file in one way at a time.
1692
1693Do you want to revisit the file literally now? "
1694 "The file %s is already visited literally,
1695meaning no coding system decoding, format conversion, or local variables.
1696You have asked to visit it normally,
1697but Emacs can only visit a file in one way at a time.
1698
1699Do you want to revisit the file normally now? ")
1700 (file-name-nondirectory filename)))
5de148a2
RS
1701 (find-file-noselect-1 buf filename nowarn
1702 rawfile truename number)
1703 (error (if rawfile "File already visited non-literally"
1704 "File already visited literally"))))))
1705 ;; Return the buffer we are using.
1706 buf)
1707 ;; Create a new buffer.
1708 (setq buf (create-file-buffer filename))
5de148a2
RS
1709 ;; find-file-noselect-1 may use a different buffer.
1710 (find-file-noselect-1 buf filename nowarn
1711 rawfile truename number))))))
ddd64da9
RS
1712
1713(defun find-file-noselect-1 (buf filename nowarn rawfile truename number)
4edcfd17 1714 (let (error)
ddd64da9
RS
1715 (with-current-buffer buf
1716 (kill-local-variable 'find-file-literally)
b296cbd4
RS
1717 ;; Needed in case we are re-visiting the file with a different
1718 ;; text representation.
e73ec04b 1719 (kill-local-variable 'buffer-file-coding-system)
4ad1689f 1720 (kill-local-variable 'cursor-type)
4edcfd17 1721 (let ((inhibit-read-only t))
0a11c70b
LT
1722 (erase-buffer))
1723 (and (default-value 'enable-multibyte-characters)
1724 (not rawfile)
1725 (set-buffer-multibyte t))
1726 (if rawfile
74dca654 1727 (condition-case ()
0a11c70b
LT
1728 (let ((inhibit-read-only t))
1729 (insert-file-contents-literally filename t))
74dca654
LT
1730 (file-error
1731 (when (and (file-exists-p filename)
1732 (not (file-readable-p filename)))
1733 (kill-buffer buf)
1734 (signal 'file-error (list "File is not readable"
1735 filename)))
0a11c70b
LT
1736 ;; Unconditionally set error
1737 (setq error t)))
1738 (condition-case ()
1739 (let ((inhibit-read-only t))
1740 (insert-file-contents filename t))
1741 (file-error
1742 (when (and (file-exists-p filename)
1743 (not (file-readable-p filename)))
1744 (kill-buffer buf)
1745 (signal 'file-error (list "File is not readable"
1746 filename)))
e0d8fc91 1747 ;; Run find-file-not-found-functions until one returns non-nil.
0a11c70b
LT
1748 (or (run-hook-with-args-until-success 'find-file-not-found-functions)
1749 ;; If they fail too, set error.
1750 (setq error t)))))
b120e713
KH
1751 ;; Record the file's truename, and maybe use that as visited name.
1752 (if (equal filename buffer-file-name)
1753 (setq buffer-file-truename truename)
9ab19105
DL
1754 (setq buffer-file-truename
1755 (abbreviate-file-name (file-truename buffer-file-name))))
ddd64da9
RS
1756 (setq buffer-file-number number)
1757 ;; On VMS, we may want to remember which directory in a search list
1758 ;; the file was found in.
1759 (and (eq system-type 'vax-vms)
1760 (let (logical)
1761 (if (string-match ":" (file-name-directory filename))
1762 (setq logical (substring (file-name-directory filename)
1763 0 (match-beginning 0))))
1764 (not (member logical find-file-not-true-dirname-list)))
1765 (setq buffer-file-name buffer-file-truename))
1766 (if find-file-visit-truename
e442c62b 1767 (setq buffer-file-name (expand-file-name buffer-file-truename)))
ddd64da9 1768 ;; Set buffer's default directory to that of the file.
b120e713 1769 (setq default-directory (file-name-directory buffer-file-name))
ddd64da9
RS
1770 ;; Turn off backup files for certain file names. Since
1771 ;; this is a permanent local, the major mode won't eliminate it.
b98a8e06
RS
1772 (and backup-enable-predicate
1773 (not (funcall backup-enable-predicate buffer-file-name))
ddd64da9
RS
1774 (progn
1775 (make-local-variable 'backup-inhibited)
1776 (setq backup-inhibited t)))
f402ba38
RS
1777 (if rawfile
1778 (progn
1779 (set-buffer-multibyte nil)
1780 (setq buffer-file-coding-system 'no-conversion)
e8f30180 1781 (set-buffer-major-mode buf)
f402ba38
RS
1782 (make-local-variable 'find-file-literally)
1783 (setq find-file-literally t))
1784 (after-find-file error (not nowarn)))
1785 (current-buffer))))
9b8ef27d
RS
1786\f
1787(defun insert-file-contents-literally (filename &optional visit beg end replace)
1788 "Like `insert-file-contents', but only reads in the file literally.
1789A buffer may be modified in several ways after reading into the buffer,
1790to Emacs features such as format decoding, character code
0370fe77 1791conversion, `find-file-hook', automatic uncompression, etc.
9b8ef27d
RS
1792
1793This function ensures that none of these modifications will take place."
1794 (let ((format-alist nil)
1795 (after-insert-file-functions nil)
1796 (coding-system-for-read 'no-conversion)
1797 (coding-system-for-write 'no-conversion)
9b8ef27d 1798 (find-buffer-file-type-function
cdec2ad7
JB
1799 (if (fboundp 'find-buffer-file-type)
1800 (symbol-function 'find-buffer-file-type)
1801 nil))
1802 (inhibit-file-name-handlers
bfeee9d1 1803 (append '(jka-compr-handler image-file-handler epa-file-handler)
cdec2ad7
JB
1804 inhibit-file-name-handlers))
1805 (inhibit-file-name-operation 'insert-file-contents))
9b8ef27d 1806 (unwind-protect
cdec2ad7
JB
1807 (progn
1808 (fset 'find-buffer-file-type (lambda (filename) t))
1809 (insert-file-contents filename visit beg end replace))
9b8ef27d
RS
1810 (if find-buffer-file-type-function
1811 (fset 'find-buffer-file-type find-buffer-file-type-function)
1812 (fmakunbound 'find-buffer-file-type)))))
1813
3a64a3cf
JB
1814(defun insert-file-1 (filename insert-func)
1815 (if (file-directory-p filename)
1816 (signal 'file-error (list "Opening input file" "file is a directory"
1817 filename)))
4954b81b
AR
1818 ;; Check whether the file is uncommonly large
1819 (abort-if-file-too-large (nth 7 (file-attributes filename)) "insert")
3a64a3cf
JB
1820 (let* ((buffer (find-buffer-visiting (abbreviate-file-name (file-truename filename))
1821 #'buffer-modified-p))
1822 (tem (funcall insert-func filename)))
1823 (push-mark (+ (point) (car (cdr tem))))
1824 (when buffer
1825 (message "File %s already visited and modified in buffer %s"
1826 filename (buffer-name buffer)))))
1827
9b8ef27d
RS
1828(defun insert-file-literally (filename)
1829 "Insert contents of file FILENAME into buffer after point with no conversion.
1830
1831This function is meant for the user to run interactively.
1832Don't call it from programs! Use `insert-file-contents-literally' instead.
1833\(Its calling sequence is different; see its documentation)."
1834 (interactive "*fInsert file literally: ")
3a64a3cf 1835 (insert-file-1 filename #'insert-file-contents-literally))
9b8ef27d
RS
1836
1837(defvar find-file-literally nil
1838 "Non-nil if this buffer was made by `find-file-literally' or equivalent.
1839This is a permanent local.")
1840(put 'find-file-literally 'permanent-local t)
5fc196af 1841
ffc0e1ca 1842(defun find-file-literally (filename)
5fc196af
RS
1843 "Visit file FILENAME with no conversion of any kind.
1844Format conversion and character code conversion are both disabled,
1845and multibyte characters are disabled in the resulting buffer.
e65db7b8
RS
1846The major mode used is Fundamental mode regardless of the file name,
1847and local variable specifications in the file are ignored.
407b4328
GM
1848Automatic uncompression and adding a newline at the end of the
1849file due to `require-final-newline' is also disabled.
9b8ef27d
RS
1850
1851You cannot absolutely rely on this function to result in
b9aa9537 1852visiting the file literally. If Emacs already has a buffer
9b8ef27d
RS
1853which is visiting the file, you get the existing buffer,
1854regardless of whether it was created literally or not.
1855
1856In a Lisp program, if you want to be sure of accessing a file's
1857contents literally, you should create a temporary buffer and then read
1858the file contents into it using `insert-file-contents-literally'."
5fc196af 1859 (interactive "FFind file literally: ")
9b8ef27d 1860 (switch-to-buffer (find-file-noselect filename nil t)))
b4da00e9 1861\f
f7d786d0
RS
1862(defvar after-find-file-from-revert-buffer nil)
1863
e0ab8879 1864(defun after-find-file (&optional error warn noauto
9a30563f
RS
1865 after-find-file-from-revert-buffer
1866 nomodes)
b4da00e9
RM
1867 "Called after finding a file and by the default revert function.
1868Sets buffer mode, parses local variables.
8cfb9d46 1869Optional args ERROR, WARN, and NOAUTO: ERROR non-nil means there was an
b4da00e9
RM
1870error in reading the file. WARN non-nil means warn if there
1871exists an auto-save file more recent than the visited file.
8cfb9d46 1872NOAUTO means don't mess with auto-save mode.
e0ab8879
RS
1873Fourth arg AFTER-FIND-FILE-FROM-REVERT-BUFFER non-nil
1874 means this call was from `revert-buffer'.
9a30563f 1875Fifth arg NOMODES non-nil means don't alter the file's modes.
0370fe77 1876Finishes by calling the functions in `find-file-hook'
9a30563f 1877unless NOMODES is non-nil."
b4da00e9
RM
1878 (setq buffer-read-only (not (file-writable-p buffer-file-name)))
1879 (if noninteractive
1880 nil
1881 (let* (not-serious
1882 (msg
fe50b6ab
GM
1883 (cond
1884 ((not warn) nil)
1885 ((and error (file-attributes buffer-file-name))
1886 (setq buffer-read-only t)
1887 "File exists, but cannot be read")
1888 ((not buffer-read-only)
1889 (if (and warn
1890 ;; No need to warn if buffer is auto-saved
1891 ;; under the name of the visited file.
1892 (not (and buffer-file-name
1893 auto-save-visited-file-name))
1894 (file-newer-than-file-p (or buffer-auto-save-file-name
1895 (make-auto-save-file-name))
1896 buffer-file-name))
64d18e8f 1897 (format "%s has auto save data; consider M-x recover-this-file"
fe50b6ab
GM
1898 (file-name-nondirectory buffer-file-name))
1899 (setq not-serious t)
1900 (if error "(New file)" nil)))
1901 ((not error)
1902 (setq not-serious t)
1903 "Note: file is write protected")
1904 ((file-attributes (directory-file-name default-directory))
1905 "File not found and directory write-protected")
1906 ((file-exists-p (file-name-directory buffer-file-name))
1907 (setq buffer-read-only nil))
1908 (t
1909 (setq buffer-read-only nil)
07703430 1910 "Use M-x make-directory RET RET to create the directory and its parents"))))
fe50b6ab 1911 (when msg
a74357d4 1912 (message "%s" msg)
e09f3bff 1913 (or not-serious (sit-for 1 t))))
fe50b6ab
GM
1914 (when (and auto-save-default (not noauto))
1915 (auto-save-mode t)))
ffc0e1ca
AS
1916 ;; Make people do a little extra work (C-x C-q)
1917 ;; before altering a backup file.
fe50b6ab
GM
1918 (when (backup-file-name-p buffer-file-name)
1919 (setq buffer-read-only t))
8fd9c174
RS
1920 ;; When a file is marked read-only,
1921 ;; make the buffer read-only even if root is looking at it.
879365c6
KS
1922 (when (and (file-modes (buffer-file-name))
1923 (zerop (logand (file-modes (buffer-file-name)) #o222)))
8fd9c174 1924 (setq buffer-read-only t))
fe50b6ab
GM
1925 (unless nomodes
1926 (when (and view-read-only view-mode)
1927 (view-mode-disable))
9a30563f 1928 (normal-mode t)
f4206092
RS
1929 ;; If requested, add a newline at the end of the file.
1930 (and (memq require-final-newline '(visit visit-save))
1931 (> (point-max) (point-min))
1932 (/= (char-after (1- (point-max))) ?\n)
1933 (not (and (eq selective-display t)
1934 (= (char-after (1- (point-max))) ?\r)))
1935 (save-excursion
1936 (goto-char (point-max))
1937 (insert "\n")))
fe50b6ab
GM
1938 (when (and buffer-read-only
1939 view-read-only
1940 (not (eq (get major-mode 'mode-class) 'special)))
1941 (view-mode-enter))
0370fe77 1942 (run-hooks 'find-file-hook)))
b4da00e9 1943
818286f4
SM
1944(defmacro report-errors (format &rest body)
1945 "Eval BODY and turn any error into a FORMAT message.
1946FORMAT can have a %s escape which will be replaced with the actual error.
1947If `debug-on-error' is set, errors are not caught, so that you can
1948debug them.
1949Avoid using a large BODY since it is duplicated."
1950 (declare (debug t) (indent 1))
1951 `(if debug-on-error
1952 (progn . ,body)
1953 (condition-case err
1954 (progn . ,body)
1955 (error (message ,format (prin1-to-string err))))))
1956
b4da00e9
RM
1957(defun normal-mode (&optional find-file)
1958 "Choose the major mode for this buffer automatically.
1959Also sets up any specified local variables of the file.
1960Uses the visited file name, the -*- line, and the local variables spec.
1961
1962This function is called automatically from `find-file'. In that case,
aa5fcebf 1963we may set up the file-specified mode and local variables,
a5ce12c3 1964depending on the value of `enable-local-variables'.
aa5fcebf
KH
1965In addition, if `local-enable-local-variables' is nil, we do
1966not set local variables (though we do notice a mode specified with -*-.)
1967
1968`enable-local-variables' is ignored if you run `normal-mode' interactively,
1969or from Lisp without specifying the optional argument FIND-FILE;
1970in that case, this function acts as if `enable-local-variables' were t."
b4da00e9 1971 (interactive)
e8f30180 1972 (funcall (or default-major-mode 'fundamental-mode))
0fc205c6
LT
1973 (let ((enable-local-variables (or (not find-file) enable-local-variables)))
1974 (report-errors "File mode specification error: %s"
1975 (set-auto-mode))
1976 (report-errors "File local-variables error: %s"
818286f4 1977 (hack-local-variables)))
6e86be0b
RS
1978 ;; Turn font lock off and on, to make sure it takes account of
1979 ;; whatever file local variables are relevant to it.
344f1111
SM
1980 (when (and font-lock-mode
1981 ;; Font-lock-mode (now in font-core.el) can be ON when
1982 ;; font-lock.el still hasn't been loaded.
1983 (boundp 'font-lock-keywords)
1984 (eq (car font-lock-keywords) t))
6e86be0b
RS
1985 (setq font-lock-keywords (cadr font-lock-keywords))
1986 (font-lock-mode 1))
1987
24c9eeeb
DL
1988 (if (fboundp 'ucs-set-table-for-input) ; don't lose when building
1989 (ucs-set-table-for-input)))
b4da00e9 1990
94495713
KS
1991(defcustom auto-mode-case-fold nil
1992 "Non-nil means to try second pass through `auto-mode-alist'.
1993This means that if the first case-sensitive search through the alist fails
1994to find a matching major mode, a second case-insensitive search is made.
1995On systems with case-insensitive file names, this variable is ignored,
bb178aaa 1996since only a single case-insensitive search through the alist is made."
94495713
KS
1997 :group 'files
1998 :version "22.1"
1999 :type 'boolean)
2000
f76e0cd0 2001(defvar auto-mode-alist
f209c999
MS
2002 ;; Note: The entries for the modes defined in cc-mode.el (c-mode,
2003 ;; c++-mode, java-mode and more) are added through autoload
2004 ;; directives in that file. That way is discouraged since it
2005 ;; spreads out the definition of the initial value.
4aaffda1 2006 (mapcar
ffc0e1ca
AS
2007 (lambda (elt)
2008 (cons (purecopy (car elt)) (cdr elt)))
813731b3 2009 `(;; do this first, so that .html.pl is Polish html, not Perl
9e6f5419
DP
2010 ("\\.s?html?\\(\\.[a-zA-Z_]+\\)?\\'" . html-mode)
2011 ("\\.te?xt\\'" . text-mode)
bbc67516 2012 ("\\.[tT]e[xX]\\'" . tex-mode)
4e163715 2013 ("\\.ins\\'" . tex-mode) ;Installation files for TeX packages.
ffc0e1ca 2014 ("\\.ltx\\'" . latex-mode)
4e163715 2015 ("\\.dtx\\'" . doctex-mode)
18d8cb81 2016 ("\\.org\\'" . org-mode)
ffc0e1ca 2017 ("\\.el\\'" . emacs-lisp-mode)
21575d92 2018 ("\\.\\(scm\\|stk\\|ss\\|sch\\)\\'" . scheme-mode)
ffc0e1ca 2019 ("\\.l\\'" . lisp-mode)
bbc67516
DP
2020 ("\\.li?sp\\'" . lisp-mode)
2021 ("\\.[fF]\\'" . fortran-mode)
ffc0e1ca
AS
2022 ("\\.for\\'" . fortran-mode)
2023 ("\\.p\\'" . pascal-mode)
2024 ("\\.pas\\'" . pascal-mode)
2025 ("\\.ad[abs]\\'" . ada-mode)
7defe888 2026 ("\\.ad[bs].dg\\'" . ada-mode)
bbc67516 2027 ("\\.\\([pP]\\([Llm]\\|erl\\|od\\)\\|al\\)\\'" . perl-mode)
3968c89f 2028 ("Imakefile\\'" . makefile-imake-mode)
8088bb2c
DP
2029 ("Makeppfile\\(?:\\.mk\\)?\\'" . makefile-makepp-mode) ; Put this before .mk
2030 ("\\.makepp\\'" . makefile-makepp-mode)
813731b3
DP
2031 ,@(if (memq system-type '(berkeley-unix next-mach darwin))
2032 '(("\\.mk\\'" . makefile-bsdmake-mode)
47d4e709 2033 ("GNUmakefile\\'" . makefile-gmake-mode)
813731b3
DP
2034 ("[Mm]akefile\\'" . makefile-bsdmake-mode))
2035 '(("\\.mk\\'" . makefile-gmake-mode) ; Might be any make, give Gnu the host advantage
47d4e709 2036 ("[Mm]akefile\\'" . makefile-gmake-mode)))
27a7c83f 2037 ("\\.am\\'" . makefile-automake-mode)
5c6d31a4
SM
2038 ;; Less common extensions come here
2039 ;; so more common ones above are found faster.
ffc0e1ca
AS
2040 ("\\.texinfo\\'" . texinfo-mode)
2041 ("\\.te?xi\\'" . texinfo-mode)
bbc67516 2042 ("\\.[sS]\\'" . asm-mode)
ffc0e1ca 2043 ("\\.asm\\'" . asm-mode)
bbc67516 2044 ("[cC]hange\\.?[lL]og?\\'" . change-log-mode)
40656849 2045 ("[cC]hange[lL]og[-.][0-9]+\\'" . change-log-mode)
ffc0e1ca
AS
2046 ("\\$CHANGE_LOG\\$\\.TXT" . change-log-mode)
2047 ("\\.scm\\.[0-9]*\\'" . scheme-mode)
2048 ("\\.[ck]?sh\\'\\|\\.shar\\'\\|/\\.z?profile\\'" . sh-mode)
b921b596 2049 ("\\.bash\\'" . sh-mode)
ffc0e1ca
AS
2050 ("\\(/\\|\\`\\)\\.\\(bash_profile\\|z?login\\|bash_login\\|z?logout\\)\\'" . sh-mode)
2051 ("\\(/\\|\\`\\)\\.\\(bash_logout\\|shrc\\|[kz]shrc\\|bashrc\\|t?cshrc\\|esrc\\)\\'" . sh-mode)
2052 ("\\(/\\|\\`\\)\\.\\([kz]shenv\\|xinitrc\\|startxrc\\|xsession\\)\\'" . sh-mode)
d5798fa7 2053 ("\\.m?spec\\'" . sh-mode)
bbc67516 2054 ("\\.m[mes]\\'" . nroff-mode)
ffc0e1ca 2055 ("\\.man\\'" . nroff-mode)
ffc0e1ca 2056 ("\\.sty\\'" . latex-mode)
bbc67516 2057 ("\\.cl[so]\\'" . latex-mode) ;LaTeX 2e class option
ffc0e1ca
AS
2058 ("\\.bbl\\'" . latex-mode)
2059 ("\\.bib\\'" . bibtex-mode)
2060 ("\\.sql\\'" . sql-mode)
bbc67516 2061 ("\\.m[4c]\\'" . m4-mode)
ffc0e1ca
AS
2062 ("\\.mf\\'" . metafont-mode)
2063 ("\\.mp\\'" . metapost-mode)
2064 ("\\.vhdl?\\'" . vhdl-mode)
2065 ("\\.article\\'" . text-mode)
2066 ("\\.letter\\'" . text-mode)
bbc67516 2067 ("\\.i?tcl\\'" . tcl-mode)
ffc0e1ca 2068 ("\\.exp\\'" . tcl-mode)
ffc0e1ca
AS
2069 ("\\.itk\\'" . tcl-mode)
2070 ("\\.icn\\'" . icon-mode)
2071 ("\\.sim\\'" . simula-mode)
2072 ("\\.mss\\'" . scribe-mode)
bbc67516 2073 ("\\.f9[05]\\'" . f90-mode)
8f9495e7 2074 ("\\.indent\\.pro\\'" . fundamental-mode) ; to avoid idlwave-mode
ffc0e1ca 2075 ("\\.pro\\'" . idlwave-mode)
ffc0e1ca
AS
2076 ("\\.prolog\\'" . prolog-mode)
2077 ("\\.tar\\'" . tar-mode)
0ee6e7b7
JL
2078 ;; The list of archive file extensions should be in sync with
2079 ;; `auto-coding-alist' with `no-conversion' coding system.
e7988f09
SM
2080 ("\\.\\(\
2081arc\\|zip\\|lzh\\|lha\\|zoo\\|[jew]ar\\|xpi\\|rar\\|\
2082ARC\\|ZIP\\|LZH\\|LHA\\|ZOO\\|[JEW]AR\\|XPI\\|RAR\\)\\'" . archive-mode)
d5040404 2083 ("\\.\\(sx[dmicw]\\|odt\\)\\'" . archive-mode) ; OpenOffice.org
ece21937 2084 ("\\.\\(deb\\)\\'" . archive-mode) ; Debian packages.
ffc0e1ca
AS
2085 ;; Mailer puts message to be edited in
2086 ;; /tmp/Re.... or Message
2087 ("\\`/tmp/Re" . text-mode)
2088 ("/Message[0-9]*\\'" . text-mode)
ffc0e1ca
AS
2089 ("\\.zone\\'" . zone-mode)
2090 ;; some news reader is reported to use this
2091 ("\\`/tmp/fol/" . text-mode)
ffc0e1ca
AS
2092 ("\\.oak\\'" . scheme-mode)
2093 ("\\.sgml?\\'" . sgml-mode)
bbc67516 2094 ("\\.x[ms]l\\'" . xml-mode)
ffc0e1ca
AS
2095 ("\\.dtd\\'" . sgml-mode)
2096 ("\\.ds\\(ss\\)?l\\'" . dsssl-mode)
bbc67516 2097 ("\\.js\\'" . java-mode) ; javascript-mode would be better
62a7c35d 2098 ("\\.d?v\\'" . verilog-mode)
709d45e1
KG
2099 ;; .emacs or .gnus or .viper following a directory delimiter in
2100 ;; Unix, MSDOG or VMS syntax.
2101 ("[]>:/\\]\\..*\\(emacs\\|gnus\\|viper\\)\\'" . emacs-lisp-mode)
ffc0e1ca
AS
2102 ("\\`\\..*emacs\\'" . emacs-lisp-mode)
2103 ;; _emacs following a directory delimiter
2104 ;; in MsDos syntax
2105 ("[:/]_emacs\\'" . emacs-lisp-mode)
2106 ("/crontab\\.X*[0-9]+\\'" . shell-script-mode)
2107 ("\\.ml\\'" . lisp-mode)
ebbcece3
GM
2108 ;; Common Lisp ASDF package system.
2109 ("\\.asd\\'" . lisp-mode)
d5798fa7
SM
2110 ("\\.\\(asn\\|mib\\|smi\\)\\'" . snmp-mode)
2111 ("\\.\\(as\\|mi\\|sm\\)2\\'" . snmpv2-mode)
ffc0e1ca 2112 ("\\.\\(diffs?\\|patch\\|rej\\)\\'" . diff-mode)
e854cc22 2113 ("\\.\\(dif\\|pat\\)\\'" . diff-mode) ; for MSDOG
9a905782 2114 ("\\.[eE]?[pP][sS]\\'" . ps-mode)
88a54804 2115 ("\\.\\(?:PDF\\|DVI\\|pdf\\|dvi\\)\\'" . doc-view-mode)
e55c4863 2116 ("configure\\.\\(ac\\|in\\)\\'" . autoconf-mode)
ffc0e1ca
AS
2117 ("BROWSE\\'" . ebrowse-tree-mode)
2118 ("\\.ebrowse\\'" . ebrowse-tree-mode)
9ee45b2c 2119 ("#\\*mail\\*" . mail-mode)
80174d35
DP
2120 ("\\.g\\'" . antlr-mode)
2121 ("\\.ses\\'" . ses-mode)
2122 ("\\.\\(soa\\|zone\\)\\'" . dns-mode)
2123 ("\\.docbook\\'" . sgml-mode)
00daa381 2124 ("\\.com\\'" . dcl-mode)
80174d35
DP
2125 ("/config\\.\\(?:bat\\|log\\)\\'" . fundamental-mode)
2126 ;; Windows candidates may be opened case sensitively on Unix
2127 ("\\.\\(?:[iI][nN][iI]\\|[lL][sS][tT]\\|[rR][eE][gG]\\|[sS][yY][sS]\\)\\'" . conf-mode)
2128 ("\\.\\(?:desktop\\|la\\)\\'" . conf-unix-mode)
08adf84e 2129 ("\\.ppd\\'" . conf-ppd-mode)
80174d35
DP
2130 ("java.+\\.conf\\'" . conf-javaprop-mode)
2131 ("\\.properties\\(?:\\.[a-zA-Z0-9._-]+\\)?\\'" . conf-javaprop-mode)
2132 ;; *.cf, *.cfg, *.conf, *.config[.local|.de_DE.UTF8|...], */config
73936494 2133 ("[/.]c\\(?:on\\)?f\\(?:i?g\\)?\\(?:\\.[a-zA-Z0-9._-]+\\)?\\'" . conf-mode-maybe)
a35d9075
AS
2134 ("\\`/etc/\\(?:DIR_COLORS\\|ethers\\|.?fstab\\|.*hosts\\|lesskey\\|login\\.?de\\(?:fs\\|vperm\\)\\|magic\\|mtab\\|pam\\.d/.*\\|permissions\\(?:\\.d/.+\\)?\\|protocols\\|rpc\\|services\\)\\'" . conf-space-mode)
2135 ("\\`/etc/\\(?:acpid?/.+\\|aliases\\(?:\\.d/.+\\)?\\|default/.+\\|group-?\\|hosts\\..+\\|inittab\\|ksysguarddrc\\|opera6rc\\|passwd-?\\|shadow-?\\|sysconfig/.+\\)\\'" . conf-mode)
40656849
CY
2136 ;; ChangeLog.old etc. Other change-log-mode entries are above;
2137 ;; this has lower priority to avoid matching changelog.sgml etc.
2138 ("[cC]hange[lL]og[-.][-0-9a-z]+\\'" . change-log-mode)
80174d35
DP
2139 ;; either user's dot-files or under /etc or some such
2140 ("/\\.?\\(?:gnokiirc\\|kde.*rc\\|mime\\.types\\|wgetrc\\)\\'" . conf-mode)
2141 ;; alas not all ~/.*rc files are like this
b14f1885 2142 ("/\\.\\(?:enigma\\|gltron\\|gtk\\|hxplayer\\|net\\|neverball\\|qt/.+\\|realplayer\\|scummvm\\|sversion\\|sylpheed/.+\\|xmp\\)rc\\'" . conf-mode)
80174d35
DP
2143 ("/\\.\\(?:gdbtkinit\\|grip\\|orbital/.+txt\\|rhosts\\|tuxracer/options\\)\\'" . conf-mode)
2144 ("/\\.?X\\(?:default\\|resource\\|re\\)s\\>" . conf-xdefaults-mode)
2145 ("/X11.+app-defaults/" . conf-xdefaults-mode)
2146 ("/X11.+locale/.+/Compose\\'" . conf-colon-mode)
2147 ;; this contains everything twice, with space and with colon :-(
2148 ("/X11.+locale/compose\\.dir\\'" . conf-javaprop-mode)
9ee45b2c
SM
2149 ;; Get rid of any trailing .n.m and try again.
2150 ;; This is for files saved by cvs-merge that look like .#<file>.<rev>
5c6d31a4
SM
2151 ;; or .#<file>.<rev>-<rev> or VC's <file>.~<rev>~.
2152 ;; Using mode nil rather than `ignore' would let the search continue
2153 ;; through this list (with the shortened name) rather than start over.
bbc67516 2154 ("\\.~?[0-9]+\\.[0-9][-.0-9]*~?\\'" nil t)
5c6d31a4
SM
2155 ;; The following should come after the ChangeLog pattern
2156 ;; for the sake of ChangeLog.1, etc.
2157 ;; and after the .scm.[0-9] and CVS' <file>.<rev> patterns too.
e043664a 2158 ("\\.[1-9]\\'" . nroff-mode)
80174d35 2159 ("\\.\\(?:orig\\|in\\|[bB][aA][kK]\\)\\'" nil t)))
ffc0e1ca 2160 "Alist of filename patterns vs corresponding major mode functions.
116987ba
RS
2161Each element looks like (REGEXP . FUNCTION) or (REGEXP FUNCTION NON-NIL).
2162\(NON-NIL stands for anything that is not nil; the value does not matter.)
2163Visiting a file whose name matches REGEXP specifies FUNCTION as the
2164mode function to use. FUNCTION will be called, unless it is nil.
2165
2166If the element has the form (REGEXP FUNCTION NON-NIL), then after
2167calling FUNCTION (if it's not nil), we delete the suffix that matched
969be033 2168REGEXP and search the list again for another match.
7b3f3dc2 2169
969be033
RS
2170If the file name matches `inhibit-first-line-modes-regexps',
2171then `auto-mode-alist' is not processed.
2172
d5040404
EZ
2173The extensions whose FUNCTION is `archive-mode' should also
2174appear in `auto-coding-alist' with `no-conversion' coding system.
2175
969be033
RS
2176See also `interpreter-mode-alist', which detects executable script modes
2177based on the interpreters they specify to run,
2178and `magic-mode-alist', which determines modes based on file contents.")
e13322a0 2179
73936494
RS
2180(defun conf-mode-maybe ()
2181 "Select Conf mode or XML mode according to start of file."
2182 (if (save-excursion
2183 (save-restriction
2184 (widen)
2185 (goto-char (point-min))
2186 (looking-at "<\\?xml \\|<!-- \\|<!DOCTYPE ")))
2187 (xml-mode)
2188 (conf-mode)))
2189
d7fa5aa2 2190(defvar interpreter-mode-alist
f209c999
MS
2191 ;; Note: The entries for the modes defined in cc-mode.el (awk-mode
2192 ;; and pike-mode) are added through autoload directives in that
2193 ;; file. That way is discouraged since it spreads out the
2194 ;; definition of the initial value.
ffc0e1ca
AS
2195 (mapc
2196 (lambda (l)
2197 (cons (purecopy (car l)) (cdr l)))
2198 '(("perl" . perl-mode)
2199 ("perl5" . perl-mode)
2200 ("miniperl" . perl-mode)
2201 ("wish" . tcl-mode)
2202 ("wishx" . tcl-mode)
2203 ("tcl" . tcl-mode)
2204 ("tclsh" . tcl-mode)
ffc0e1ca
AS
2205 ("scm" . scheme-mode)
2206 ("ash" . sh-mode)
2207 ("bash" . sh-mode)
2208 ("bash2" . sh-mode)
2209 ("csh" . sh-mode)
2210 ("dtksh" . sh-mode)
2211 ("es" . sh-mode)
2212 ("itcsh" . sh-mode)
2213 ("jsh" . sh-mode)
2214 ("ksh" . sh-mode)
2215 ("oash" . sh-mode)
2216 ("pdksh" . sh-mode)
2217 ("rc" . sh-mode)
2218 ("rpm" . sh-mode)
2219 ("sh" . sh-mode)
2220 ("sh5" . sh-mode)
2221 ("tcsh" . sh-mode)
2222 ("wksh" . sh-mode)
2223 ("wsh" . sh-mode)
2224 ("zsh" . sh-mode)
2225 ("tail" . text-mode)
2226 ("more" . text-mode)
2227 ("less" . text-mode)
2228 ("pg" . text-mode)
27a7c83f 2229 ("make" . makefile-gmake-mode) ; Debian uses this
ffc0e1ca
AS
2230 ("guile" . scheme-mode)
2231 ("clisp" . lisp-mode)))
c907d156 2232 "Alist mapping interpreter names to major modes.
969be033 2233This is used for files whose first lines match `auto-mode-interpreter-regexp'.
c907d156 2234Each element looks like (INTERPRETER . MODE).
9f01a773
RS
2235If INTERPRETER matches the name of the interpreter specified in the first line
2236of a script, mode MODE is enabled.
969be033
RS
2237
2238See also `auto-mode-alist'.")
c907d156 2239
d7fa5aa2 2240(defvar inhibit-first-line-modes-regexps '("\\.tar\\'" "\\.tgz\\'")
45fb3bb8 2241 "List of regexps; if one matches a file name, don't look for `-*-'.")
a0c9f21b 2242
d7fa5aa2 2243(defvar inhibit-first-line-modes-suffixes nil
b20ff6d0
RS
2244 "List of regexps for what to ignore, for `inhibit-first-line-modes-regexps'.
2245When checking `inhibit-first-line-modes-regexps', we first discard
2246from the end of the file name anything that matches one of these regexps.")
2247
ffc0e1ca
AS
2248(defvar auto-mode-interpreter-regexp
2249 "#![ \t]?\\([^ \t\n]*\
2250/bin/env[ \t]\\)?\\([^ \t\n]+\\)"
54005870 2251 "Regexp matching interpreters, for file mode determination.
ffc0e1ca 2252This regular expression is matched against the first line of a file
54005870
LT
2253to determine the file's mode in `set-auto-mode'. If it matches, the file
2254is assumed to be interpreted by the interpreter matched by the second group
2255of the regular expression. The mode is then determined as the mode
2256associated with that interpreter in `interpreter-mode-alist'.")
0720b68b 2257
1a5bfb0e 2258(defvar magic-mode-alist nil
c11781de
SM
2259 "Alist of buffer beginnings vs. corresponding major mode functions.
2260Each element looks like (REGEXP . FUNCTION) or (MATCH-FUNCTION . FUNCTION).
2261After visiting a file, if REGEXP matches the text at the beginning of the
2262buffer, or calling MATCH-FUNCTION returns non-nil, `normal-mode' will
2263call FUNCTION rather than allowing `auto-mode-alist' to decide the buffer's
2264major mode.
2265
2266If FUNCTION is nil, then it is not called. (That is a way of saying
2267\"allow `auto-mode-alist' to decide for these files.\")")
2268(put 'magic-mode-alist 'risky-local-variable t)
2269
2270(defvar magic-fallback-mode-alist
1a5bfb0e
CY
2271 `((image-type-auto-detected-p . image-mode)
2272 ;; The < comes before the groups (but the first) to reduce backtracking.
4ac1d37a 2273 ;; TODO: UTF-16 <?xml may be preceded by a BOM 0xff 0xfe or 0xfe 0xff.
efaa82ff 2274 ;; We use [ \t\r\n] instead of `\\s ' to make regex overflow less likely.
32a0479a 2275 (,(let* ((incomment-re "\\(?:[^-]\\|-[^-]\\)")
efaa82ff
GM
2276 (comment-re (concat "\\(?:!--" incomment-re "*-->[ \t\r\n]*<\\)")))
2277 (concat "\\(?:<\\?xml[ \t\r\n]+[^>]*>\\)?[ \t\r\n]*<"
32a0479a 2278 comment-re "*"
efaa82ff 2279 "\\(?:!DOCTYPE[ \t\r\n]+[^>]*>[ \t\r\n]*<[ \t\r\n]*" comment-re "*\\)?"
969be033
RS
2280 "[Hh][Tt][Mm][Ll]"))
2281 . html-mode)
815fde34 2282 ("<!DOCTYPE[ \t\r\n]+[Hh][Tt][Mm][Ll]" . html-mode)
4ac1d37a
DP
2283 ;; These two must come after html, because they are more general:
2284 ("<\\?xml " . xml-mode)
811cab86 2285 (,(let* ((incomment-re "\\(?:[^-]\\|-[^-]\\)")
e7d313a0
GM
2286 (comment-re (concat "\\(?:!--" incomment-re "*-->[ \t\r\n]*<\\)")))
2287 (concat "[ \t\r\n]*<" comment-re "*!DOCTYPE "))
969be033 2288 . sgml-mode)
12333e2b 2289 ("%!PS" . ps-mode)
80174d35 2290 ("# xmcd " . conf-unix-mode))
14774875
RS
2291 "Like `magic-mode-alist' but has lower priority than `auto-mode-alist'.
2292Each element looks like (REGEXP . FUNCTION) or (MATCH-FUNCTION . FUNCTION).
2293After visiting a file, if REGEXP matches the text at the beginning of the
2294buffer, or calling MATCH-FUNCTION returns non-nil, `normal-mode' will
2295call FUNCTION, provided that `magic-mode-alist' and `auto-mode-alist'
2296have not specified a mode for this file.
2297
2298If FUNCTION is nil, then it is not called.")
92228a10 2299(put 'magic-fallback-mode-alist 'risky-local-variable t)
14774875 2300
5cce080e 2301(defvar magic-mode-regexp-match-limit 4000
14774875 2302 "Upper limit on `magic-mode-alist' regexp matches.
92228a10 2303Also applies to `magic-fallback-mode-alist'.")
5cce080e 2304
9e6f5419 2305(defun set-auto-mode (&optional keep-mode-if-same)
b4da00e9 2306 "Select major mode appropriate for current buffer.
4ac1d37a 2307
c022c4c4
RS
2308To find the right major mode, this function checks for a -*- mode tag,
2309checks if it uses an interpreter listed in `interpreter-mode-alist',
2310matches the buffer beginning against `magic-mode-alist',
2311compares the filename against the entries in `auto-mode-alist',
2312then matches the buffer beginning against `magic-fallback-mode-alist'.
e3998da1
RS
2313
2314It does not check for the `mode:' local variable in the
2315Local Variables section of the file; for that, use `hack-local-variables'.
7b3f3dc2 2316
f3e23606 2317If `enable-local-variables' is nil, this function does not check for a
9de9b6a2
RS
2318-*- mode tag.
2319
521cf174 2320If the optional argument KEEP-MODE-IF-SAME is non-nil, then we
c022c4c4
RS
2321set the major mode only if that would change it. In other words
2322we don't actually set it to the same mode the buffer already has."
b4da00e9 2323 ;; Look for -*-MODENAME-*- or -*- ... mode: MODENAME; ... -*-
811cab86 2324 (let (end done mode modes)
9e6f5419 2325 ;; Find a -*- mode tag
b4da00e9
RM
2326 (save-excursion
2327 (goto-char (point-min))
2328 (skip-chars-forward " \t\n")
9fa7bfe5 2329 (and enable-local-variables
e3f9b9c0 2330 (setq end (set-auto-mode-1))
2d2ab9da
RS
2331 (if (save-excursion (search-forward ":" end t))
2332 ;; Find all specifications for the `mode:' variable
2333 ;; and execute them left to right.
2334 (while (let ((case-fold-search t))
2335 (or (and (looking-at "mode:")
2336 (goto-char (match-end 0)))
2337 (re-search-forward "[ \t;]mode:" end t)))
2338 (skip-chars-forward " \t")
2339 (let ((beg (point)))
9fa7bfe5
RS
2340 (if (search-forward ";" end t)
2341 (forward-char -1)
2342 (goto-char end))
2343 (skip-chars-backward " \t")
9ee45b2c 2344 (push (intern (concat (downcase (buffer-substring beg (point))) "-mode"))
2d2ab9da
RS
2345 modes)))
2346 ;; Simple -*-MODE-*- case.
2347 (push (intern (concat (downcase (buffer-substring (point) end))
2348 "-mode"))
2349 modes))))
9e6f5419
DP
2350 ;; If we found modes to use, invoke them now, outside the save-excursion.
2351 (if modes
521cf174
DP
2352 (catch 'nop
2353 (dolist (mode (nreverse modes))
2354 (if (not (functionp mode))
2355 (message "Ignoring unknown mode `%s'" mode)
2356 (setq done t)
3467488e 2357 (or (set-auto-mode-0 mode keep-mode-if-same)
df4d0613 2358 ;; continuing would call minor modes again, toggling them off
ec6328a2 2359 (throw 'nop nil))))))
14774875
RS
2360 ;; If we didn't, look for an interpreter specified in the first line.
2361 ;; As a special case, allow for things like "#!/bin/env perl", which
2362 ;; finds the interpreter anywhere in $PATH.
ec6328a2 2363 (unless done
9e6f5419
DP
2364 (setq mode (save-excursion
2365 (goto-char (point-min))
2366 (if (looking-at auto-mode-interpreter-regexp)
2367 (match-string 2)
2368 ""))
2369 ;; Map interpreter name to a mode, signalling we're done at the
2370 ;; same time.
2371 done (assoc (file-name-nondirectory mode)
2372 interpreter-mode-alist))
811cab86 2373 ;; If we found an interpreter mode to use, invoke it now.
df4d0613
DP
2374 (if done
2375 (set-auto-mode-0 (cdr done) keep-mode-if-same)))
14774875 2376 ;; Next try matching the buffer beginning against magic-mode-alist.
df4d0613 2377 (unless done
4ac1d37a
DP
2378 (if (setq done (save-excursion
2379 (goto-char (point-min))
5cce080e
KS
2380 (save-restriction
2381 (narrow-to-region (point-min)
2382 (min (point-max)
2383 (+ (point-min) magic-mode-regexp-match-limit)))
2384 (assoc-default nil magic-mode-alist
2385 (lambda (re dummy)
10ffa2a1
KS
2386 (if (functionp re)
2387 (funcall re)
2388 (looking-at re)))))))
14774875
RS
2389 (set-auto-mode-0 done keep-mode-if-same)))
2390 ;; Next compare the filename against the entries in auto-mode-alist.
2391 (unless done
2392 (if buffer-file-name
f1fa5062
MA
2393 (let ((name buffer-file-name)
2394 (remote-id (file-remote-p buffer-file-name)))
2395 ;; Remove remote file name identification.
2396 (when (and (stringp remote-id)
32650100 2397 (string-match (regexp-quote remote-id) name))
f1fa5062 2398 (setq name (substring name (match-end 0))))
14774875
RS
2399 ;; Remove backup-suffixes from file name.
2400 (setq name (file-name-sans-versions name))
2401 (while name
2402 ;; Find first matching alist entry.
2403 (setq mode
2404 (if (memq system-type '(vax-vms windows-nt cygwin))
2405 ;; System is case-insensitive.
2406 (let ((case-fold-search t))
2407 (assoc-default name auto-mode-alist
2408 'string-match))
2409 ;; System is case-sensitive.
2410 (or
2411 ;; First match case-sensitively.
2412 (let ((case-fold-search nil))
2413 (assoc-default name auto-mode-alist
2414 'string-match))
2415 ;; Fallback to case-insensitive match.
2416 (and auto-mode-case-fold
2417 (let ((case-fold-search t))
2418 (assoc-default name auto-mode-alist
2419 'string-match))))))
2420 (if (and mode
2421 (consp mode)
2422 (cadr mode))
2423 (setq mode (car mode)
2424 name (substring name 0 (match-beginning 0)))
2425 (setq name))
2426 (when mode
2427 (set-auto-mode-0 mode keep-mode-if-same)
2428 (setq done t))))))
92228a10 2429 ;; Next try matching the buffer beginning against magic-fallback-mode-alist.
14774875
RS
2430 (unless done
2431 (if (setq done (save-excursion
2432 (goto-char (point-min))
2433 (save-restriction
2434 (narrow-to-region (point-min)
2435 (min (point-max)
2436 (+ (point-min) magic-mode-regexp-match-limit)))
92228a10 2437 (assoc-default nil magic-fallback-mode-alist
14774875
RS
2438 (lambda (re dummy)
2439 (if (functionp re)
2440 (funcall re)
2441 (looking-at re)))))))
2442 (set-auto-mode-0 done keep-mode-if-same)))))
521cf174 2443
521cf174
DP
2444;; When `keep-mode-if-same' is set, we are working on behalf of
2445;; set-visited-file-name. In that case, if the major mode specified is the
2446;; same one we already have, don't actually reset it. We don't want to lose
2447;; minor modes such as Font Lock.
3467488e 2448(defun set-auto-mode-0 (mode &optional keep-mode-if-same)
521cf174 2449 "Apply MODE and return it.
3467488e
KS
2450If optional arg KEEP-MODE-IF-SAME is non-nil, MODE is chased of
2451any aliases and compared to current major mode. If they are the
2452same, do nothing and return nil."
0c7c413c
CY
2453 (unless (and keep-mode-if-same
2454 (eq (indirect-function mode)
2455 (indirect-function major-mode)))
2456 (when mode
2457 (funcall mode)
2458 mode)))
b4da00e9 2459
e3f9b9c0
RS
2460(defun set-auto-mode-1 ()
2461 "Find the -*- spec in the buffer.
2462Call with point at the place to start searching from.
2463If one is found, set point to the beginning
2464and return the position of the end.
2465Otherwise, return nil; point may be changed."
2466 (let (beg end)
2467 (and
2468 ;; Don't look for -*- if this file name matches any
2469 ;; of the regexps in inhibit-first-line-modes-regexps.
2470 (let ((temp inhibit-first-line-modes-regexps)
2471 (name (if buffer-file-name
2472 (file-name-sans-versions buffer-file-name)
2473 (buffer-name))))
2474 (while (let ((sufs inhibit-first-line-modes-suffixes))
2475 (while (and sufs (not (string-match (car sufs) name)))
2476 (setq sufs (cdr sufs)))
2477 sufs)
2478 (setq name (substring name 0 (match-beginning 0))))
2479 (while (and temp
2480 (not (string-match (car temp) name)))
2481 (setq temp (cdr temp)))
2482 (not temp))
2483
f587e30b
SM
2484 (search-forward "-*-" (line-end-position
2485 ;; If the file begins with "#!"
2486 ;; (exec interpreter magic), look
2487 ;; for mode frobs in the first two
2488 ;; lines. You cannot necessarily
2489 ;; put them in the first line of
2490 ;; such a file without screwing up
2491 ;; the interpreter invocation.
dddb4597
WL
2492 ;; The same holds for
2493 ;; '\"
2494 ;; in man pages (preprocessor
2495 ;; magic for the `man' program).
2496 (and (looking-at "^\\(#!\\|'\\\\\"\\)") 2)) t)
e3f9b9c0
RS
2497 (progn
2498 (skip-chars-forward " \t")
2499 (setq beg (point))
f587e30b 2500 (search-forward "-*-" (line-end-position) t))
e3f9b9c0
RS
2501 (progn
2502 (forward-char -3)
2503 (skip-chars-backward " \t")
2504 (setq end (point))
2505 (goto-char beg)
2506 end))))
b9e1451a
CY
2507\f
2508;;; Handling file local variables
2509
2510(defvar ignored-local-variables
2511 '(ignored-local-variables safe-local-variable-values)
2512 "Variables to be ignored in a file's local variable spec.")
2513
2514(defvar hack-local-variables-hook nil
2515 "Normal hook run after processing a file's local variables specs.
2516Major modes can use this to examine user-specified local variables
2517in order to initialize other data structure based on them.")
2518
2519(defcustom safe-local-variable-values nil
2520 "List variable-value pairs that are considered safe.
2521Each element is a cons cell (VAR . VAL), where VAR is a variable
2522symbol and VAL is a value that is considered safe."
2523 :group 'find-file
2524 :type 'alist)
2525
146b3daf 2526(defcustom safe-local-eval-forms '((add-hook 'write-file-hooks 'time-stamp))
ba83982b 2527 "Expressions that are considered safe in an `eval:' local variable.
b9e1451a
CY
2528Add expressions to this list if you want Emacs to evaluate them, when
2529they appear in an `eval' local variable specification, without first
2530asking you for confirmation."
2531 :group 'find-file
146b3daf 2532 :version "22.2"
b9e1451a
CY
2533 :type '(repeat sexp))
2534
2535;; Risky local variables:
2536(mapc (lambda (var) (put var 'risky-local-variable t))
2537 '(after-load-alist
2538 auto-mode-alist
2539 buffer-auto-save-file-name
2540 buffer-file-name
2541 buffer-file-truename
2542 buffer-undo-list
2543 dabbrev-case-fold-search
2544 dabbrev-case-replace
2545 debugger
2546 default-text-properties
2547 display-time-string
2548 enable-local-eval
e58cec15 2549 enable-local-variables
b9e1451a
CY
2550 eval
2551 exec-directory
2552 exec-path
2553 file-name-handler-alist
2554 font-lock-defaults
2555 format-alist
2556 frame-title-format
2557 global-mode-string
2558 header-line-format
2559 icon-title-format
2560 ignored-local-variables
2561 imenu--index-alist
2562 imenu-generic-expression
2563 inhibit-quit
2564 input-method-alist
2565 load-path
2566 max-lisp-eval-depth
2567 max-specpdl-size
2568 minor-mode-alist
2569 minor-mode-map-alist
2570 minor-mode-overriding-map-alist
2571 mode-line-buffer-identification
2572 mode-line-format
f2aa3ae4 2573 mode-line-client
b9e1451a
CY
2574 mode-line-modes
2575 mode-line-modified
2576 mode-line-mule-info
2577 mode-line-position
2578 mode-line-process
3650f60e 2579 mode-line-remote
b9e1451a
CY
2580 mode-name
2581 outline-level
2582 overriding-local-map
2583 overriding-terminal-local-map
2584 parse-time-rules
2585 process-environment
2586 rmail-output-file-alist
e58cec15
RS
2587 safe-local-variable-values
2588 safe-local-eval-forms
b9e1451a
CY
2589 save-some-buffers-action-alist
2590 special-display-buffer-names
2591 standard-input
2592 standard-output
2593 unread-command-events
2594 vc-mode))
2595
2596;; Safe local variables:
2597;;
3e457225
RS
2598;; For variables defined by major modes, the safety declarations can go into
2599;; the major mode's file, since that will be loaded before file variables are
2600;; processed.
2601;;
2602;; For variables defined by minor modes, put the safety declarations in the
2603;; file defining the minor mode after the defcustom/defvar using an autoload
2604;; cookie, e.g.:
2605;;
2606;; ;;;###autoload(put 'variable 'safe-local-variable 'stringp)
2607;;
2608;; Otherwise, when Emacs visits a file specifying that local variable, the
2609;; minor mode file may not be loaded yet.
2610;;
2611;; For variables defined in the C source code the declaration should go here:
b9e1451a 2612
0a51c121
JL
2613(mapc (lambda (pair)
2614 (put (car pair) 'safe-local-variable (cdr pair)))
4b025f47
CY
2615 '((buffer-read-only . booleanp) ;; C source code
2616 (default-directory . stringp) ;; C source code
2617 (fill-column . integerp) ;; C source code
2618 (indent-tabs-mode . booleanp) ;; C source code
2619 (left-margin . integerp) ;; C source code
2620 (no-update-autoloads . booleanp)
2621 (tab-width . integerp) ;; C source code
2622 (truncate-lines . booleanp))) ;; C source code
b9e1451a
CY
2623
2624(put 'c-set-style 'safe-local-eval-function t)
e3f9b9c0 2625
70b49e57
RS
2626(defun hack-local-variables-confirm (all-vars unsafe-vars risky-vars)
2627 "Get confirmation before setting up local variable values.
2628ALL-VARS is the list of all variables to be set up.
2629UNSAFE-VARS is the list of those that aren't marked as safe or risky.
2630RISKY-VARS is the list of those that are marked as risky."
5a6c1d87
CY
2631 (if noninteractive
2632 nil
2633 (let ((name (if buffer-file-name
2634 (file-name-nondirectory buffer-file-name)
2635 (concat "buffer " (buffer-name))))
af467e28 2636 (offer-save (and (eq enable-local-variables t) unsafe-vars))
0a158521 2637 prompt char)
5a6c1d87 2638 (save-window-excursion
0a158521 2639 (let ((buf (get-buffer-create "*Local Variables*")))
42078bb2
CY
2640 (pop-to-buffer buf)
2641 (set (make-local-variable 'cursor-type) nil)
2642 (erase-buffer)
5a6c1d87 2643 (if unsafe-vars
42078bb2
CY
2644 (insert "The local variables list in " name
2645 "\ncontains values that may not be safe (*)"
2646 (if risky-vars
2647 ", and variables that are risky (**)."
2648 "."))
5a6c1d87 2649 (if risky-vars
42078bb2
CY
2650 (insert "The local variables list in " name
2651 "\ncontains variables that are risky (**).")
2652 (insert "A local variables list is specified in " name ".")))
2653 (insert "\n\nDo you want to apply it? You can type
5a6c1d87 2654y -- to apply the local variables list.
af467e28
CY
2655n -- to ignore the local variables list.")
2656 (if offer-save
2657 (insert "
dbcd3ce0
EZ
2658! -- to apply the local variables list, and permanently mark these
2659 values (*) as safe (in the future, they will be set automatically.)\n\n")
af467e28 2660 (insert "\n\n"))
70b49e57 2661 (dolist (elt all-vars)
5a6c1d87 2662 (cond ((member elt unsafe-vars)
42078bb2 2663 (insert " * "))
5a6c1d87 2664 ((member elt risky-vars)
42078bb2 2665 (insert " ** "))
5a6c1d87 2666 (t
42078bb2
CY
2667 (insert " ")))
2668 (princ (car elt) buf)
2669 (insert " : ")
e442c62b
SM
2670 ;; Make strings with embedded whitespace easier to read.
2671 (let ((print-escape-newlines t))
2672 (prin1 (cdr elt) buf))
42078bb2 2673 (insert "\n"))
af467e28
CY
2674 (setq prompt
2675 (format "Please type %s%s: "
2676 (if offer-save "y, n, or !" "y or n")
2677 (if (< (line-number-at-pos) (window-body-height))
2678 ""
2679 ", or C-v to scroll")))
2680 (goto-char (point-min))
a5ce12c3 2681 (let ((cursor-in-echo-area t)
5340648d 2682 (executing-kbd-macro executing-kbd-macro)
af467e28
CY
2683 (exit-chars
2684 (if offer-save '(?! ?y ?n ?\s ?\C-g) '(?y ?n ?\s ?\C-g)))
42078bb2
CY
2685 done)
2686 (while (not done)
f6e7ec02 2687 (message "%s" prompt)
42078bb2
CY
2688 (setq char (read-event))
2689 (if (numberp char)
5340648d
CY
2690 (cond ((eq char ?\C-v)
2691 (condition-case nil
2692 (scroll-up)
2693 (error (goto-char (point-min)))))
2694 ;; read-event returns -1 if we are in a kbd
2695 ;; macro and there are no more events in the
2696 ;; macro. In that case, attempt to get an
2697 ;; event interactively.
2698 ((and executing-kbd-macro (= char -1))
2699 (setq executing-kbd-macro nil))
2700 (t (setq done (memq (downcase char) exit-chars)))))))
42078bb2 2701 (setq char (downcase char))
af467e28 2702 (when (and offer-save (= char ?!) unsafe-vars)
42078bb2
CY
2703 (dolist (elt unsafe-vars)
2704 (add-to-list 'safe-local-variable-values elt))
4299d849
CY
2705 ;; When this is called from desktop-restore-file-buffer,
2706 ;; coding-system-for-read may be non-nil. Reset it before
2707 ;; writing to .emacs.
af467e28
CY
2708 (if (or custom-file user-init-file)
2709 (let ((coding-system-for-read nil))
2710 (customize-save-variable
2711 'safe-local-variable-values
2712 safe-local-variable-values))))
0a158521 2713 (kill-buffer buf)
42078bb2
CY
2714 (or (= char ?!)
2715 (= char ?\s)
2716 (= char ?y)))))))
cc45837e 2717
a0e74e72 2718(defun hack-local-variables-prop-line (&optional mode-only)
5a6c1d87 2719 "Return local variables specified in the -*- line.
ffc0e1ca
AS
2720Ignore any specification for `mode:' and `coding:';
2721`set-auto-mode' should already have handled `mode:',
a0e74e72 2722`set-auto-coding' should already have handled `coding:'.
5a6c1d87
CY
2723
2724If MODE-ONLY is non-nil, all we do is check whether the major
2725mode is specified, returning t if it is specified. Otherwise,
2726return an alist of elements (VAR . VAL), where VAR is a variable
2727and VAL is the specified value."
f3e23606
RS
2728 (save-excursion
2729 (goto-char (point-min))
5a6c1d87
CY
2730 (let ((end (set-auto-mode-1))
2731 result mode-specified)
a0e74e72
RS
2732 ;; Parse the -*- line into the RESULT alist.
2733 ;; Also set MODE-SPECIFIED if we see a spec or `mode'.
e3f9b9c0 2734 (cond ((not end)
f3e23606
RS
2735 nil)
2736 ((looking-at "[ \t]*\\([^ \t\n\r:;]+\\)\\([ \t]*-\\*-\\)")
13a66180 2737 ;; Simple form: "-*- MODENAME -*-". Already handled.
a0e74e72 2738 (setq mode-specified t)
13a66180 2739 nil)
f3e23606
RS
2740 (t
2741 ;; Hairy form: '-*-' [ <variable> ':' <value> ';' ]* '-*-'
2742 ;; (last ";" is optional).
f3e23606
RS
2743 (while (< (point) end)
2744 (or (looking-at "[ \t]*\\([^ \t\n:]+\\)[ \t]*:[ \t]*")
ffc0e1ca 2745 (error "Malformed -*- line"))
f3e23606 2746 (goto-char (match-end 0))
1c26a6f3
KH
2747 ;; There used to be a downcase here,
2748 ;; but the manual didn't say so,
2749 ;; and people want to set var names that aren't all lc.
e442c62b 2750 (let ((key (intern (match-string 1)))
f3e23606
RS
2751 (val (save-restriction
2752 (narrow-to-region (point) end)
2753 (read (current-buffer)))))
93a2702d
RS
2754 ;; It is traditional to ignore
2755 ;; case when checking for `mode' in set-auto-mode,
2756 ;; so we must do that here as well.
2757 ;; That is inconsistent, but we're stuck with it.
3fa0a9aa 2758 ;; The same can be said for `coding' in set-auto-coding.
5a6c1d87
CY
2759 (or (and (equal (downcase (symbol-name key)) "mode")
2760 (setq mode-specified t))
3fa0a9aa 2761 (equal (downcase (symbol-name key)) "coding")
5a6c1d87
CY
2762 (condition-case nil
2763 (push (cons (if (eq key 'eval)
2764 'eval
2765 (indirect-variable key))
2766 val) result)
2767 (error nil)))
2768 (skip-chars-forward " \t;")))))
2769
2770 (if mode-only
2771 mode-specified
2772 result))))
f3e23606 2773
9de9b6a2
RS
2774(defun hack-local-variables (&optional mode-only)
2775 "Parse and put into effect this buffer's local variables spec.
2776If MODE-ONLY is non-nil, all we do is check whether the major mode
2777is specified, returning t if it is specified."
5a6c1d87
CY
2778 (let ((enable-local-variables
2779 (and local-enable-local-variables enable-local-variables))
2780 result)
2781 (when (or mode-only enable-local-variables)
2782 (setq result (hack-local-variables-prop-line mode-only))
2783 ;; Look for "Local variables:" line in last page.
2784 (save-excursion
2785 (goto-char (point-max))
2786 (search-backward "\n\^L" (max (- (point-max) 3000) (point-min))
2787 'move)
2788 (when (let ((case-fold-search t))
2789 (search-forward "Local Variables:" nil t))
2790 (skip-chars-forward " \t")
2791 ;; suffix is what comes after "local variables:" in its line.
2792 ;; prefix is what comes before "local variables:" in its line.
2793 (let ((suffix
2794 (concat
2795 (regexp-quote (buffer-substring (point)
2796 (line-end-position)))
2797 "$"))
2798 (prefix
2799 (concat "^" (regexp-quote
2800 (buffer-substring (line-beginning-position)
2801 (match-beginning 0)))))
2802 beg)
2803
2804 (forward-line 1)
2805 (let ((startpos (point))
2806 endpos
2807 (thisbuf (current-buffer)))
2808 (save-excursion
2809 (unless (let ((case-fold-search t))
2810 (re-search-forward
2811 (concat prefix "[ \t]*End:[ \t]*" suffix)
2812 nil t))
2813 (error "Local variables list is not properly terminated"))
2814 (beginning-of-line)
2815 (setq endpos (point)))
2816
2817 (with-temp-buffer
2818 (insert-buffer-substring thisbuf startpos endpos)
2819 (goto-char (point-min))
2820 (subst-char-in-region (point) (point-max) ?\^m ?\n)
2821 (while (not (eobp))
2822 ;; Discard the prefix.
2823 (if (looking-at prefix)
2824 (delete-region (point) (match-end 0))
2825 (error "Local variables entry is missing the prefix"))
2826 (end-of-line)
2827 ;; Discard the suffix.
2828 (if (looking-back suffix)
2829 (delete-region (match-beginning 0) (point))
2830 (error "Local variables entry is missing the suffix"))
2831 (forward-line 1))
2832 (goto-char (point-min))
2833
2834 (while (not (eobp))
2835 ;; Find the variable name; strip whitespace.
2836 (skip-chars-forward " \t")
2837 (setq beg (point))
2838 (skip-chars-forward "^:\n")
2839 (if (eolp) (error "Missing colon in local variables entry"))
2840 (skip-chars-backward " \t")
2841 (let* ((str (buffer-substring beg (point)))
2842 (var (read str))
2843 val)
2844 ;; Read the variable value.
2845 (skip-chars-forward "^:")
2846 (forward-char 1)
2847 (setq val (read (current-buffer)))
2848 (if mode-only
2849 (if (eq var 'mode)
2850 (setq result t))
2851 (unless (eq var 'coding)
2852 (condition-case nil
2853 (push (cons (if (eq var 'eval)
2854 'eval
2855 (indirect-variable var))
2856 val) result)
2857 (error nil)))))
2858 (forward-line 1)))))))
2859
2860 ;; We've read all the local variables. Now, return whether the
2861 ;; mode is specified (if MODE-ONLY is non-nil), or set the
2862 ;; variables (if MODE-ONLY is nil.)
2863 (if mode-only
2864 result
d450f2a2
CY
2865 (dolist (ignored ignored-local-variables)
2866 (setq result (assq-delete-all ignored result)))
2867 (if (null enable-local-eval)
2868 (setq result (assq-delete-all 'eval result)))
dd60bebe
CY
2869 (when result
2870 (setq result (nreverse result))
dd60bebe
CY
2871 ;; Find those variables that we may want to save to
2872 ;; `safe-local-variable-values'.
2873 (let (risky-vars unsafe-vars)
2874 (dolist (elt result)
2875 (let ((var (car elt))
2876 (val (cdr elt)))
66381027
RS
2877 ;; Don't query about the fake variables.
2878 (or (memq var '(mode unibyte coding))
dd60bebe
CY
2879 (and (eq var 'eval)
2880 (or (eq enable-local-eval t)
2881 (hack-one-local-variable-eval-safep
2882 (eval (quote val)))))
2883 (safe-local-variable-p var val)
2884 (and (risky-local-variable-p var val)
2885 (push elt risky-vars))
2886 (push elt unsafe-vars))))
a5ce12c3
RS
2887 (if (eq enable-local-variables :safe)
2888 ;; If caller wants only the safe variables,
2889 ;; install only them.
dd60bebe 2890 (dolist (elt result)
3020ee92
RF
2891 (unless (or (member elt unsafe-vars)
2892 (member elt risky-vars))
a5ce12c3
RS
2893 (hack-one-local-variable (car elt) (cdr elt))))
2894 ;; Query, except in the case where all are known safe
2895 ;; if the user wants no quuery in that case.
2896 (if (or (and (eq enable-local-variables t)
2897 (null unsafe-vars)
2898 (null risky-vars))
e58cec15 2899 (eq enable-local-variables :all)
a5ce12c3
RS
2900 (hack-local-variables-confirm
2901 result unsafe-vars risky-vars))
2902 (dolist (elt result)
a548f3d7
CY
2903 (hack-one-local-variable (car elt) (cdr elt)))))))
2904 (run-hooks 'hack-local-variables-hook)))))
5a6c1d87 2905
5a6c1d87
CY
2906(defun safe-local-variable-p (sym val)
2907 "Non-nil if SYM is safe as a file-local variable with value VAL.
2908It is safe if any of these conditions are met:
2909
2910 * There is a matching entry (SYM . VAL) in the
2911 `safe-local-variable-values' user option.
2912
5a6c1d87
CY
2913 * The `safe-local-variable' property of SYM is a function that
2914 evaluates to a non-nil value with VAL as an argument."
2915 (or (member (cons sym val) safe-local-variable-values)
2916 (let ((safep (get sym 'safe-local-variable)))
80aa4695 2917 (and (functionp safep) (funcall safep val)))))
5a6c1d87
CY
2918
2919(defun risky-local-variable-p (sym &optional ignored)
2920 "Non-nil if SYM could be dangerous as a file-local variable.
2921It is dangerous if either of these conditions are met:
2922
2923 * Its `risky-local-variable' property is non-nil.
2924
2925 * Its name ends with \"hook(s)\", \"function(s)\", \"form(s)\", \"map\",
2926 \"program\", \"command(s)\", \"predicate(s)\", \"frame-alist\",
cc5a104d
RS
2927 \"mode-alist\", \"font-lock-(syntactic-)keyword*\",
2928 \"map-alist\", or \"bindat-spec\"."
f36d46ca
RS
2929 ;; If this is an alias, check the base name.
2930 (condition-case nil
2931 (setq sym (indirect-variable sym))
2932 (error nil))
5a6c1d87
CY
2933 (or (get sym 'risky-local-variable)
2934 (string-match "-hooks?$\\|-functions?$\\|-forms?$\\|-program$\\|\
2935-commands?$\\|-predicates?$\\|font-lock-keywords$\\|font-lock-keywords\
2936-[0-9]+$\\|font-lock-syntactic-keywords$\\|-frame-alist$\\|-mode-alist$\\|\
cc5a104d 2937-map$\\|-map-alist$\\|-bindat-spec$" (symbol-name sym))))
7ed9159a 2938
d0bd3513
RS
2939(defun hack-one-local-variable-quotep (exp)
2940 (and (consp exp) (eq (car exp) 'quote) (consp (cdr exp))))
2941
ff7affeb
RS
2942(defun hack-one-local-variable-constantp (exp)
2943 (or (and (not (symbolp exp)) (not (consp exp)))
2944 (memq exp '(t nil))
2945 (keywordp exp)
2946 (hack-one-local-variable-quotep exp)))
2947
2948(defun hack-one-local-variable-eval-safep (exp)
2949 "Return t if it is safe to eval EXP when it is found in a file."
8fd9c174
RS
2950 (or (not (consp exp))
2951 ;; Detect certain `put' expressions.
2952 (and (eq (car exp) 'put)
2953 (hack-one-local-variable-quotep (nth 1 exp))
2954 (hack-one-local-variable-quotep (nth 2 exp))
bc5d1dfb
EZ
2955 (let ((prop (nth 1 (nth 2 exp))) (val (nth 3 exp)))
2956 (cond ((eq prop 'lisp-indent-hook)
2957 ;; Only allow safe values of lisp-indent-hook;
2958 ;; not functions.
2959 (or (numberp val) (equal val ''defun)))
2960 ((eq prop 'edebug-form-spec)
2961 ;; Only allow indirect form specs.
b486a098
SM
2962 ;; During bootstrapping, edebug-basic-spec might not be
2963 ;; defined yet.
2964 (and (fboundp 'edebug-basic-spec)
f215a02f
AS
2965 (hack-one-local-variable-quotep val)
2966 (edebug-basic-spec (nth 1 val)))))))
8fd9c174
RS
2967 ;; Allow expressions that the user requested.
2968 (member exp safe-local-eval-forms)
2969 ;; Certain functions can be allowed with safe arguments
2970 ;; or can specify verification functions to try.
2971 (and (symbolp (car exp))
2972 (let ((prop (get (car exp) 'safe-local-eval-function)))
2973 (cond ((eq prop t)
2974 (let ((ok t))
2975 (dolist (arg (cdr exp))
2976 (unless (hack-one-local-variable-constantp arg)
2977 (setq ok nil)))
2978 ok))
2979 ((functionp prop)
2980 (funcall prop exp))
2981 ((listp prop)
2982 (let ((ok nil))
2983 (dolist (function prop)
2984 (if (funcall function exp)
2985 (setq ok t)))
2986 ok)))))))
ff7affeb 2987
f3e23606 2988(defun hack-one-local-variable (var val)
0c7c413c
CY
2989 "Set local variable VAR with value VAL.
2990If VAR is `mode', call `VAL-mode' as a function unless it's
2991already the major mode."
f3e23606 2992 (cond ((eq var 'mode)
0c7c413c
CY
2993 (let ((mode (intern (concat (downcase (symbol-name val))
2994 "-mode"))))
2995 (unless (eq (indirect-function mode)
2996 (indirect-function major-mode))
2997 (funcall mode))))
5a6c1d87
CY
2998 ((eq var 'eval)
2999 (save-excursion (eval val)))
e442c62b
SM
3000 (t
3001 ;; Make sure the string has no text properties.
3002 ;; Some text properties can get evaluated in various ways,
3003 ;; so it is risky to put them on with a local variable list.
3004 (if (stringp val)
3005 (set-text-properties 0 (length val) nil val))
3006 (set (make-local-variable var) val))))
f3e23606 3007
b4da00e9 3008\f
21540597 3009(defcustom change-major-mode-with-file-name t
ba83982b 3010 "Non-nil means \\[write-file] should set the major mode from the file name.
9de9b6a2
RS
3011However, the mode will not be changed if
3012\(1) a local variables list or the `-*-' line specifies a major mode, or
3013\(2) the current major mode is a \"special\" mode,
96e777e1 3014\ not suitable for ordinary files, or
21540597
RS
3015\(3) the new file name does not particularly specify any mode."
3016 :type 'boolean
3017 :group 'editing-basics)
9de9b6a2 3018
f36012a6 3019(defun set-visited-file-name (filename &optional no-query along-with-file)
b4da00e9 3020 "Change name of file visited in current buffer to FILENAME.
1af57101 3021This also renames the buffer to correspond to the new file.
b4da00e9 3022The next time the buffer is saved it will go in the newly specified file.
1af57101 3023FILENAME nil or an empty string means mark buffer as not visiting any file.
b4da00e9 3024Remember to delete the initial contents of the minibuffer
6a6b62f8
RS
3025if you wish to pass an empty string as the argument.
3026
3027The optional second argument NO-QUERY, if non-nil, inhibits asking for
f36012a6
RS
3028confirmation in the case where another buffer is already visiting FILENAME.
3029
3030The optional third argument ALONG-WITH-FILE, if non-nil, means that
3031the old visited file has been renamed to the new name FILENAME."
b4da00e9 3032 (interactive "FSet visited file name: ")
c11a94fe
RS
3033 (if (buffer-base-buffer)
3034 (error "An indirect buffer cannot visit a file"))
a522e5bf
RS
3035 (let (truename)
3036 (if filename
3037 (setq filename
3038 (if (string-equal filename "")
3039 nil
3040 (expand-file-name filename))))
3041 (if filename
3042 (progn
3043 (setq truename (file-truename filename))
3044 (if find-file-visit-truename
a522e5bf 3045 (setq filename truename))))
cbca0a4b 3046 (if filename
e6d0b67a 3047 (let ((new-name (file-name-nondirectory filename)))
cbca0a4b
RS
3048 (if (string= new-name "")
3049 (error "Empty file name"))))
11e314fa 3050 (let ((buffer (and filename (find-buffer-visiting filename))))
7b89d38e 3051 (and buffer (not (eq buffer (current-buffer)))
6a6b62f8 3052 (not no-query)
674b7bae
JB
3053 (not (y-or-n-p (format "A buffer is visiting %s; proceed? "
3054 filename)))
7b89d38e 3055 (error "Aborted")))
a522e5bf
RS
3056 (or (equal filename buffer-file-name)
3057 (progn
3058 (and filename (lock-buffer filename))
3059 (unlock-buffer)))
3060 (setq buffer-file-name filename)
3061 (if filename ; make buffer name reflect filename.
3062 (let ((new-name (file-name-nondirectory buffer-file-name)))
a522e5bf
RS
3063 (if (eq system-type 'vax-vms)
3064 (setq new-name (downcase new-name)))
3065 (setq default-directory (file-name-directory buffer-file-name))
67b6fd1c
SM
3066 ;; If new-name == old-name, renaming would add a spurious <2>
3067 ;; and it's considered as a feature in rename-buffer.
a522e5bf
RS
3068 (or (string= new-name (buffer-name))
3069 (rename-buffer new-name t))))
3070 (setq buffer-backed-up nil)
f36012a6
RS
3071 (or along-with-file
3072 (clear-visited-file-modtime))
8ccdc29e 3073 ;; Abbreviate the file names of the buffer.
4826e97f 3074 (if truename
8ccdc29e
RS
3075 (progn
3076 (setq buffer-file-truename (abbreviate-file-name truename))
3077 (if find-file-visit-truename
b1f1ceb8 3078 (setq buffer-file-name truename))))
a522e5bf
RS
3079 (setq buffer-file-number
3080 (if filename
2a47b4f5 3081 (nthcdr 10 (file-attributes buffer-file-name))
a522e5bf 3082 nil)))
0370fe77 3083 ;; write-file-functions is normally used for things like ftp-find-file
b4da00e9
RM
3084 ;; that visit things that are not local files as if they were files.
3085 ;; Changing to visit an ordinary local file instead should flush the hook.
0370fe77 3086 (kill-local-variable 'write-file-functions)
c9dca4e0 3087 (kill-local-variable 'local-write-file-hooks)
b4da00e9
RM
3088 (kill-local-variable 'revert-buffer-function)
3089 (kill-local-variable 'backup-inhibited)
ee81c959
RS
3090 ;; If buffer was read-only because of version control,
3091 ;; that reason is gone now, so make it writable.
3092 (if vc-mode
3093 (setq buffer-read-only nil))
3094 (kill-local-variable 'vc-mode)
b4da00e9
RM
3095 ;; Turn off backup files for certain file names.
3096 ;; Since this is a permanent local, the major mode won't eliminate it.
4d49551a 3097 (and buffer-file-name
b98a8e06 3098 backup-enable-predicate
4d49551a 3099 (not (funcall backup-enable-predicate buffer-file-name))
b4da00e9
RM
3100 (progn
3101 (make-local-variable 'backup-inhibited)
3102 (setq backup-inhibited t)))
c77a81cf
RS
3103 (let ((oauto buffer-auto-save-file-name))
3104 ;; If auto-save was not already on, turn it on if appropriate.
3105 (if (not buffer-auto-save-file-name)
3106 (and buffer-file-name auto-save-default
3107 (auto-save-mode t))
3108 ;; If auto save is on, start using a new name.
3109 ;; We deliberately don't rename or delete the old auto save
3110 ;; for the old visited file name. This is because perhaps
3111 ;; the user wants to save the new state and then compare with the
3112 ;; previous state from the auto save file.
3113 (setq buffer-auto-save-file-name
3114 (make-auto-save-file-name)))
3115 ;; Rename the old auto save file if any.
3116 (and oauto buffer-auto-save-file-name
e6f0e76c 3117 (file-exists-p oauto)
c77a81cf 3118 (rename-file oauto buffer-auto-save-file-name t)))
f36012a6
RS
3119 (and buffer-file-name
3120 (not along-with-file)
9de9b6a2
RS
3121 (set-buffer-modified-p t))
3122 ;; Update the major mode, if the file name determines it.
3123 (condition-case nil
3124 ;; Don't change the mode if it is special.
3125 (or (not change-major-mode-with-file-name)
3126 (get major-mode 'mode-class)
3127 ;; Don't change the mode if the local variable list specifies it.
3128 (hack-local-variables t)
3129 (set-auto-mode t))
3130 (error nil)))
b4da00e9 3131
912192d1 3132(defun write-file (filename &optional confirm)
b4da00e9 3133 "Write current buffer into file FILENAME.
7f99999a 3134This makes the buffer visit that file, and marks it as not modified.
7458cc35 3135
7f99999a
KH
3136If you specify just a directory name as FILENAME, that means to use
3137the default file name but in that directory. You can also yank
074eb6ac 3138the default file name into the minibuffer to edit it, using \\<minibuffer-local-map>\\[next-history-element].
7f99999a
KH
3139
3140If the buffer is not already visiting a file, the default file name
3141for the output file is the buffer name.
3142
3143If optional second arg CONFIRM is non-nil, this function
3144asks for confirmation before overwriting an existing file.
912192d1 3145Interactively, confirmation is required unless you supply a prefix argument."
b4da00e9
RM
3146;; (interactive "FWrite file: ")
3147 (interactive
3148 (list (if buffer-file-name
3149 (read-file-name "Write file: "
f3684505 3150 nil nil nil nil)
7f99999a
KH
3151 (read-file-name "Write file: " default-directory
3152 (expand-file-name
3153 (file-name-nondirectory (buffer-name))
3154 default-directory)
3155 nil nil))
912192d1 3156 (not current-prefix-arg)))
b4da00e9 3157 (or (null filename) (string-equal filename "")
41f48cb1
RS
3158 (progn
3159 ;; If arg is just a directory,
7f99999a
KH
3160 ;; use the default file name, but in that directory.
3161 (if (file-directory-p filename)
41f48cb1 3162 (setq filename (concat (file-name-as-directory filename)
7f99999a
KH
3163 (file-name-nondirectory
3164 (or buffer-file-name (buffer-name))))))
c2fb8488
RS
3165 (and confirm
3166 (file-exists-p filename)
3167 (or (y-or-n-p (format "File `%s' exists; overwrite? " filename))
3168 (error "Canceled")))
5f65549e 3169 (set-visited-file-name filename (not confirm))))
b4da00e9 3170 (set-buffer-modified-p t)
6492b55d
KH
3171 ;; Make buffer writable if file is writable.
3172 (and buffer-file-name
3173 (file-writable-p buffer-file-name)
3174 (setq buffer-read-only nil))
8e5c7b90
SM
3175 (save-buffer)
3176 ;; It's likely that the VC status at the new location is different from
3177 ;; the one at the old location.
3178 (vc-find-file-hook))
b4da00e9
RM
3179\f
3180(defun backup-buffer ()
3181 "Make a backup of the disk file visited by the current buffer, if appropriate.
3182This is normally done before saving the buffer the first time.
27ab6944
KH
3183
3184A backup may be done by renaming or by copying; see documentation of
3185variable `make-backup-files'. If it's done by renaming, then the file is
f3f9e207
RS
3186no longer accessible under its old name.
3187
3188The value is non-nil after a backup was made by renaming.
3189It has the form (MODES . BACKUPNAME).
3190MODES is the result of `file-modes' on the original
3191file; this means that the caller, after saving the buffer, should change
3192the modes of the new file to agree with the old modes.
3193BACKUPNAME is the backup file name, which is the old file renamed."
b4da00e9
RM
3194 (if (and make-backup-files (not backup-inhibited)
3195 (not buffer-backed-up)
3196 (file-exists-p buffer-file-name)
3197 (memq (aref (elt (file-attributes buffer-file-name) 8) 0)
3198 '(?- ?l)))
3199 (let ((real-file-name buffer-file-name)
3200 backup-info backupname targets setmodes)
3201 ;; If specified name is a symbolic link, chase it to the target.
3202 ;; Thus we make the backups in the directory where the real file is.
5dadeb29 3203 (setq real-file-name (file-chase-links real-file-name))
b4da00e9
RM
3204 (setq backup-info (find-backup-file-name real-file-name)
3205 backupname (car backup-info)
3206 targets (cdr backup-info))
5c6d31a4
SM
3207 ;; (if (file-directory-p buffer-file-name)
3208 ;; (error "Cannot save buffer in directory %s" buffer-file-name))
eb650569
RS
3209 (if backup-info
3210 (condition-case ()
3211 (let ((delete-old-versions
3212 ;; If have old versions to maybe delete,
3213 ;; ask the user to confirm now, before doing anything.
3214 ;; But don't actually delete til later.
3215 (and targets
3216 (or (eq delete-old-versions t) (eq delete-old-versions nil))
3217 (or delete-old-versions
3218 (y-or-n-p (format "Delete excess backup versions of %s? "
446c63b0
RS
3219 real-file-name)))))
3220 (modes (file-modes buffer-file-name)))
eb650569
RS
3221 ;; Actually write the back up file.
3222 (condition-case ()
3223 (if (or file-precious-flag
ffc0e1ca 3224 ; (file-symlink-p buffer-file-name)
eb650569 3225 backup-by-copying
446c63b0 3226 ;; Don't rename a suid or sgid file.
7da6bf00 3227 (and modes (< 0 (logand modes #o6000)))
79d2d279 3228 (not (file-writable-p (file-name-directory real-file-name)))
eb650569
RS
3229 (and backup-by-copying-when-linked
3230 (> (file-nlinks real-file-name) 1))
ffc0e1ca
AS
3231 (and (or backup-by-copying-when-mismatch
3232 (integerp backup-by-copying-when-privileged-mismatch))
eb650569 3233 (let ((attr (file-attributes real-file-name)))
ffc0e1ca
AS
3234 (and (or backup-by-copying-when-mismatch
3235 (and (integerp (nth 2 attr))
3236 (integerp backup-by-copying-when-privileged-mismatch)
3237 (<= (nth 2 attr) backup-by-copying-when-privileged-mismatch)))
3238 (or (nth 9 attr)
3239 (not (file-ownership-preserved-p real-file-name)))))))
446c63b0 3240 (backup-buffer-copy real-file-name backupname modes)
eb650569
RS
3241 ;; rename-file should delete old backup.
3242 (rename-file real-file-name backupname t)
446c63b0 3243 (setq setmodes (cons modes backupname)))
eb650569
RS
3244 (file-error
3245 ;; If trouble writing the backup, write it in ~.
567c1ca9
RS
3246 (setq backupname (expand-file-name
3247 (convert-standard-filename
3248 "~/%backup%~")))
3249 (message "Cannot write backup file; backing up in %s"
6ba7756e 3250 backupname)
eb650569 3251 (sleep-for 1)
446c63b0 3252 (backup-buffer-copy real-file-name backupname modes)))
eb650569
RS
3253 (setq buffer-backed-up t)
3254 ;; Now delete the old versions, if desired.
3255 (if delete-old-versions
3256 (while targets
3257 (condition-case ()
3258 (delete-file (car targets))
3259 (file-error nil))
3260 (setq targets (cdr targets))))
3261 setmodes)
3262 (file-error nil))))))
b4da00e9 3263
446c63b0 3264(defun backup-buffer-copy (from-name to-name modes)
44dce0fb
RS
3265 (let ((umask (default-file-modes)))
3266 (unwind-protect
3267 (progn
3268 ;; Create temp files with strict access rights. It's easy to
3269 ;; loosen them later, whereas it's impossible to close the
3270 ;; time-window of loose permissions otherwise.
3271 (set-default-file-modes ?\700)
0f39d2c9
MR
3272 (when (condition-case nil
3273 ;; Try to overwrite old backup first.
5b2e628f 3274 (copy-file from-name to-name t t t)
0f39d2c9
MR
3275 (error t))
3276 (while (condition-case nil
3277 (progn
3278 (when (file-exists-p to-name)
3279 (delete-file to-name))
5b2e628f 3280 (copy-file from-name to-name nil t t)
0f39d2c9
MR
3281 nil)
3282 (file-already-exists t))
3283 ;; The file was somehow created by someone else between
3284 ;; `delete-file' and `copy-file', so let's try again.
3285 ;; rms says "I think there is also a possible race
3286 ;; condition for making backup files" (emacs-devel 20070821).
3287 nil)))
44dce0fb
RS
3288 ;; Reset the umask.
3289 (set-default-file-modes umask)))
147fbf70
RS
3290 (and modes
3291 (set-file-modes to-name (logand modes #o1777))))
446c63b0 3292
c3554e95 3293(defun file-name-sans-versions (name &optional keep-backup-version)
ffc0e1ca 3294 "Return file NAME sans backup versions or strings.
b4da00e9 3295This is a separate procedure so your site-init or startup file can
c3554e95
RS
3296redefine it.
3297If the optional argument KEEP-BACKUP-VERSION is non-nil,
3298we do not remove backup version numbers, only true file version numbers."
6eaebaa2 3299 (let ((handler (find-file-name-handler name 'file-name-sans-versions)))
c3554e95
RS
3300 (if handler
3301 (funcall handler 'file-name-sans-versions name keep-backup-version)
3302 (substring name 0
3303 (if (eq system-type 'vax-vms)
3304 ;; VMS version number is (a) semicolon, optional
3305 ;; sign, zero or more digits or (b) period, option
3306 ;; sign, zero or more digits, provided this is the
3307 ;; second period encountered outside of the
3308 ;; device/directory part of the file name.
26add1bf
KH
3309 (or (string-match ";[-+]?[0-9]*\\'" name)
3310 (if (string-match "\\.[^]>:]*\\(\\.[-+]?[0-9]*\\)\\'"
c3554e95
RS
3311 name)
3312 (match-beginning 1))
3313 (length name))
3314 (if keep-backup-version
3315 (length name)
9a3d2737 3316 (or (string-match "\\.~[-[:alnum:]:#@^._]+~\\'" name)
c3554e95
RS
3317 (string-match "~\\'" name)
3318 (length name))))))))
b4da00e9 3319
cb0cd911 3320(defun file-ownership-preserved-p (file)
ffc0e1ca 3321 "Return t if deleting FILE and rewriting it would preserve the owner."
cb0cd911
RS
3322 (let ((handler (find-file-name-handler file 'file-ownership-preserved-p)))
3323 (if handler
3324 (funcall handler 'file-ownership-preserved-p file)
ec5533be 3325 (let ((attributes (file-attributes file)))
306faa42
RS
3326 ;; Return t if the file doesn't exist, since it's true that no
3327 ;; information would be lost by an (attempted) delete and create.
3328 (or (null attributes)
3329 (= (nth 2 attributes) (user-uid)))))))
cb0cd911 3330
20b5d24c
RS
3331(defun file-name-sans-extension (filename)
3332 "Return FILENAME sans final \"extension\".
2531b0c3
EZ
3333The extension, in a file name, is the part that follows the last `.',
3334except that a leading `.', if any, doesn't count."
20b5d24c
RS
3335 (save-match-data
3336 (let ((file (file-name-sans-versions (file-name-nondirectory filename)))
3337 directory)
2531b0c3
EZ
3338 (if (and (string-match "\\.[^.]*\\'" file)
3339 (not (eq 0 (match-beginning 0))))
20b5d24c 3340 (if (setq directory (file-name-directory filename))
6ee24f1e
RS
3341 ;; Don't use expand-file-name here; if DIRECTORY is relative,
3342 ;; we don't want to expand it.
3343 (concat directory (substring file 0 (match-beginning 0)))
20b5d24c
RS
3344 (substring file 0 (match-beginning 0)))
3345 filename))))
3346
93a2702d
RS
3347(defun file-name-extension (filename &optional period)
3348 "Return FILENAME's final \"extension\".
2531b0c3 3349The extension, in a file name, is the part that follows the last `.',
32483280 3350excluding version numbers and backup suffixes,
2531b0c3 3351except that a leading `.', if any, doesn't count.
93a2702d
RS
3352Return nil for extensionless file names such as `foo'.
3353Return the empty string for file names such as `foo.'.
3354
3355If PERIOD is non-nil, then the returned value includes the period
3356that delimits the extension, and if FILENAME has no extension,
3357the value is \"\"."
3358 (save-match-data
3359 (let ((file (file-name-sans-versions (file-name-nondirectory filename))))
2531b0c3
EZ
3360 (if (and (string-match "\\.[^.]*\\'" file)
3361 (not (eq 0 (match-beginning 0))))
93a2702d
RS
3362 (substring file (+ (match-beginning 0) (if period 0 1)))
3363 (if period
3364 "")))))
3365
ffc0e1ca
AS
3366(defcustom make-backup-file-name-function nil
3367 "A function to use instead of the default `make-backup-file-name'.
643c985d 3368A value of nil gives the default `make-backup-file-name' behavior.
ffc0e1ca 3369
d5798fa7 3370This could be buffer-local to do something special for specific
ffc0e1ca
AS
3371files. If you define it, you may need to change `backup-file-name-p'
3372and `file-name-sans-versions' too.
3373
3374See also `backup-directory-alist'."
3375 :group 'backup
3376 :type '(choice (const :tag "Default" nil)
3377 (function :tag "Your function")))
3378
3379(defcustom backup-directory-alist nil
3380 "Alist of filename patterns and backup directory names.
3381Each element looks like (REGEXP . DIRECTORY). Backups of files with
3382names matching REGEXP will be made in DIRECTORY. DIRECTORY may be
3383relative or absolute. If it is absolute, so that all matching files
3384are backed up into the same directory, the file names in this
3385directory will be the full name of the file backed up with all
3386directory separators changed to `!' to prevent clashes. This will not
3387work correctly if your filesystem truncates the resulting name.
3388
3389For the common case of all backups going into one directory, the alist
3390should contain a single element pairing \".\" with the appropriate
3391directory name.
3392
3393If this variable is nil, or it fails to match a filename, the backup
3394is made in the original file's directory.
3395
3396On MS-DOS filesystems without long names this variable is always
3397ignored."
3398 :group 'backup
dca5e71d 3399 :type '(repeat (cons (regexp :tag "Regexp matching filename")
ffc0e1ca
AS
3400 (directory :tag "Backup directory name"))))
3401
388d6ab5
RS
3402(defun normal-backup-enable-predicate (name)
3403 "Default `backup-enable-predicate' function.
0c2f6dda
RS
3404Checks for files in `temporary-file-directory',
3405`small-temporary-file-directory', and /tmp."
388d6ab5
RS
3406 (not (or (let ((comp (compare-strings temporary-file-directory 0 nil
3407 name 0 nil)))
3408 ;; Directory is under temporary-file-directory.
3409 (and (not (eq comp t))
3410 (< comp (- (length temporary-file-directory)))))
0c2f6dda
RS
3411 (let ((comp (compare-strings "/tmp" 0 nil
3412 name 0 nil)))
3413 ;; Directory is under /tmp.
3414 (and (not (eq comp t))
3415 (< comp (- (length "/tmp")))))
388d6ab5
RS
3416 (if small-temporary-file-directory
3417 (let ((comp (compare-strings small-temporary-file-directory
3418 0 nil
3419 name 0 nil)))
3420 ;; Directory is under small-temporary-file-directory.
3421 (and (not (eq comp t))
3422 (< comp (- (length small-temporary-file-directory)))))))))
3423
b4da00e9
RM
3424(defun make-backup-file-name (file)
3425 "Create the non-numeric backup file name for FILE.
ffc0e1ca
AS
3426Normally this will just be the file's name with `~' appended.
3427Customization hooks are provided as follows.
3428
3429If the variable `make-backup-file-name-function' is non-nil, its value
3430should be a function which will be called with FILE as its argument;
3431the resulting name is used.
3432
3433Otherwise a match for FILE is sought in `backup-directory-alist'; see
3434the documentation of that variable. If the directory for the backup
3435doesn't exist, it is created."
3436 (if make-backup-file-name-function
3437 (funcall make-backup-file-name-function file)
3438 (if (and (eq system-type 'ms-dos)
3439 (not (msdos-long-file-names)))
3440 (let ((fn (file-name-nondirectory file)))
3441 (concat (file-name-directory file)
3442 (or (and (string-match "\\`[^.]+\\'" fn)
3443 (concat (match-string 0 fn) ".~"))
3444 (and (string-match "\\`[^.]+\\.\\(..?\\)?" fn)
3445 (concat (match-string 0 fn) "~")))))
3446 (concat (make-backup-file-name-1 file) "~"))))
3447
3448(defun make-backup-file-name-1 (file)
3449 "Subroutine of `make-backup-file-name' and `find-backup-file-name'."
3450 (let ((alist backup-directory-alist)
6ba7756e 3451 elt backup-directory abs-backup-directory)
ffc0e1ca
AS
3452 (while alist
3453 (setq elt (pop alist))
3454 (if (string-match (car elt) file)
3455 (setq backup-directory (cdr elt)
3456 alist nil)))
eb0455ab
RS
3457 ;; If backup-directory is relative, it should be relative to the
3458 ;; file's directory. By expanding explicitly here, we avoid
3459 ;; depending on default-directory.
3460 (if backup-directory
6ba7756e
RS
3461 (setq abs-backup-directory
3462 (expand-file-name backup-directory
3463 (file-name-directory file))))
3464 (if (and abs-backup-directory (not (file-exists-p abs-backup-directory)))
ffc0e1ca 3465 (condition-case nil
6ba7756e
RS
3466 (make-directory abs-backup-directory 'parents)
3467 (file-error (setq backup-directory nil
3468 abs-backup-directory nil))))
ee291b46
RS
3469 (if (null backup-directory)
3470 file
ffc0e1ca
AS
3471 (if (file-name-absolute-p backup-directory)
3472 (progn
c60ee5e7 3473 (when (memq system-type '(windows-nt ms-dos cygwin))
d7b6ca4a
RS
3474 ;; Normalize DOSish file names: downcase the drive
3475 ;; letter, if any, and replace the leading "x:" with
3476 ;; "/drive_x".
ffc0e1ca
AS
3477 (or (file-name-absolute-p file)
3478 (setq file (expand-file-name file))) ; make defaults explicit
3479 ;; Replace any invalid file-name characters (for the
3480 ;; case of backing up remote files).
446c097e 3481 (setq file (expand-file-name (convert-standard-filename file)))
ffc0e1ca 3482 (if (eq (aref file 1) ?:)
d7b6ca4a 3483 (setq file (concat "/"
ffc0e1ca
AS
3484 "drive_"
3485 (char-to-string (downcase (aref file 0)))
d7b6ca4a 3486 (if (eq (aref file 2) ?/)
ffc0e1ca 3487 ""
d7b6ca4a 3488 "/")
ffc0e1ca
AS
3489 (substring file 2)))))
3490 ;; Make the name unique by substituting directory
3491 ;; separators. It may not really be worth bothering about
3492 ;; doubling `!'s in the original name...
3493 (expand-file-name
3494 (subst-char-in-string
d7b6ca4a 3495 ?/ ?!
ffc0e1ca
AS
3496 (replace-regexp-in-string "!" "!!" file))
3497 backup-directory))
3498 (expand-file-name (file-name-nondirectory file)
6ba7756e 3499 (file-name-as-directory abs-backup-directory))))))
b4da00e9
RM
3500
3501(defun backup-file-name-p (file)
3502 "Return non-nil if FILE is a backup file name (numeric or not).
3503This is a separate function so you can redefine it for customization.
3504You may need to redefine `file-name-sans-versions' as well."
066327ae 3505 (string-match "~\\'" file))
b4da00e9 3506
e2b30772
RS
3507(defvar backup-extract-version-start)
3508
2d051399 3509;; This is used in various files.
a7aa942a
KH
3510;; The usage of backup-extract-version-start is not very clean,
3511;; but I can't see a good alternative, so as of now I am leaving it alone.
2d051399 3512(defun backup-extract-version (fn)
ffc0e1ca 3513 "Given the name of a numeric backup file, FN, return the backup number.
e2b30772 3514Uses the free variable `backup-extract-version-start', whose value should be
2d051399 3515the index in the name where the version number begins."
e2b30772
RS
3516 (if (and (string-match "[0-9]+~$" fn backup-extract-version-start)
3517 (= (match-beginning 0) backup-extract-version-start))
027a4b6b 3518 (string-to-number (substring fn backup-extract-version-start -1))
2d051399
RS
3519 0))
3520
b4da00e9
RM
3521;; I believe there is no need to alter this behavior for VMS;
3522;; since backup files are not made on VMS, it should not get called.
3523(defun find-backup-file-name (fn)
ffc0e1ca 3524 "Find a file name for a backup file FN, and suggestions for deletions.
b4da00e9 3525Value is a list whose car is the name for the backup file
ffc0e1ca
AS
3526and whose cdr is a list of old versions to consider deleting now.
3527If the value is nil, don't make a backup.
3528Uses `backup-directory-alist' in the same way as does
3529`make-backup-file-name'."
eb650569
RS
3530 (let ((handler (find-file-name-handler fn 'find-backup-file-name)))
3531 ;; Run a handler for this function so that ange-ftp can refuse to do it.
3532 (if handler
3533 (funcall handler 'find-backup-file-name fn)
f26d858e
EZ
3534 (if (or (eq version-control 'never)
3535 ;; We don't support numbered backups on plain MS-DOS
3536 ;; when long file names are unavailable.
3537 (and (eq system-type 'ms-dos)
3538 (not (msdos-long-file-names))))
b4da00e9 3539 (list (make-backup-file-name fn))
ffc0e1ca
AS
3540 (let* ((basic-name (make-backup-file-name-1 fn))
3541 (base-versions (concat (file-name-nondirectory basic-name)
3542 ".~"))
e2b30772 3543 (backup-extract-version-start (length base-versions))
eb650569 3544 (high-water-mark 0)
ffc0e1ca
AS
3545 (number-to-delete 0)
3546 possibilities deserve-versions-p versions)
eb650569
RS
3547 (condition-case ()
3548 (setq possibilities (file-name-all-completions
3549 base-versions
ffc0e1ca
AS
3550 (file-name-directory basic-name))
3551 versions (sort (mapcar #'backup-extract-version
3552 possibilities)
3553 #'<)
eb650569
RS
3554 high-water-mark (apply 'max 0 versions)
3555 deserve-versions-p (or version-control
3556 (> high-water-mark 0))
3557 number-to-delete (- (length versions)
ffc0e1ca
AS
3558 kept-old-versions
3559 kept-new-versions
3560 -1))
3561 (file-error (setq possibilities nil)))
eb650569 3562 (if (not deserve-versions-p)
8767d866 3563 (list (make-backup-file-name fn))
ffc0e1ca 3564 (cons (format "%s.~%d~" basic-name (1+ high-water-mark))
eb650569
RS
3565 (if (and (> number-to-delete 0)
3566 ;; Delete nothing if there is overflow
3567 ;; in the number of versions to keep.
3568 (>= (+ kept-new-versions kept-old-versions -1) 0))
ffc0e1ca
AS
3569 (mapcar (lambda (n)
3570 (format "%s.~%d~" basic-name n))
eb650569
RS
3571 (let ((v (nthcdr kept-old-versions versions)))
3572 (rplacd (nthcdr (1- number-to-delete) v) ())
3573 v))))))))))
b4da00e9 3574
b4da00e9
RM
3575(defun file-nlinks (filename)
3576 "Return number of names file FILENAME has."
3577 (car (cdr (file-attributes filename))))
6c636af9 3578
753ad988
KG
3579;; (defun file-relative-name (filename &optional directory)
3580;; "Convert FILENAME to be relative to DIRECTORY (default: `default-directory').
3581;; This function returns a relative file name which is equivalent to FILENAME
3582;; when used with that default directory as the default.
3583;; If this is impossible (which can happen on MSDOS and Windows
3584;; when the file name and directory use different drive names)
3585;; then it returns FILENAME."
3586;; (save-match-data
3587;; (let ((fname (expand-file-name filename)))
3588;; (setq directory (file-name-as-directory
3589;; (expand-file-name (or directory default-directory))))
3590;; ;; On Microsoft OSes, if FILENAME and DIRECTORY have different
3591;; ;; drive names, they can't be relative, so return the absolute name.
3592;; (if (and (or (eq system-type 'ms-dos)
3593;; (eq system-type 'cygwin)
3594;; (eq system-type 'windows-nt))
3595;; (not (string-equal (substring fname 0 2)
3596;; (substring directory 0 2))))
3597;; filename
3598;; (let ((ancestor ".")
3599;; (fname-dir (file-name-as-directory fname)))
3600;; (while (and (not (string-match (concat "^" (regexp-quote directory)) fname-dir))
3601;; (not (string-match (concat "^" (regexp-quote directory)) fname)))
3602;; (setq directory (file-name-directory (substring directory 0 -1))
3603;; ancestor (if (equal ancestor ".")
3604;; ".."
3605;; (concat "../" ancestor))))
3606;; ;; Now ancestor is empty, or .., or ../.., etc.
3607;; (if (string-match (concat "^" (regexp-quote directory)) fname)
3608;; ;; We matched within FNAME's directory part.
3609;; ;; Add the rest of FNAME onto ANCESTOR.
3610;; (let ((rest (substring fname (match-end 0))))
3611;; (if (and (equal ancestor ".")
3612;; (not (equal rest "")))
3613;; ;; But don't bother with ANCESTOR if it would give us `./'.
3614;; rest
3615;; (concat (file-name-as-directory ancestor) rest)))
3616;; ;; We matched FNAME's directory equivalent.
3617;; ancestor))))))
3618
6c636af9 3619(defun file-relative-name (filename &optional directory)
ffc0e1ca 3620 "Convert FILENAME to be relative to DIRECTORY (default: `default-directory').
2d6562a5
RS
3621This function returns a relative file name which is equivalent to FILENAME
3622when used with that default directory as the default.
753ad988 3623If FILENAME and DIRECTORY lie on different machines or on different drives
1be0210d 3624on a DOS/Windows machine, it returns FILENAME in expanded form."
96c188b0 3625 (save-match-data
753ad988
KG
3626 (setq directory
3627 (file-name-as-directory (expand-file-name (or directory
3628 default-directory))))
3629 (setq filename (expand-file-name filename))
3f788773
KG
3630 (let ((fremote (file-remote-p filename))
3631 (dremote (file-remote-p directory)))
493c98af
KG
3632 (if ;; Conditions for separate trees
3633 (or
3634 ;; Test for different drives on DOS/Windows
3635 (and
7c64272b 3636 ;; Should `cygwin' really be included here? --stef
493c98af 3637 (memq system-type '(ms-dos cygwin windows-nt))
7c64272b 3638 (not (eq t (compare-strings filename 0 2 directory 0 2))))
493c98af 3639 ;; Test for different remote file system identification
3f788773 3640 (not (equal fremote dremote)))
e2b30772 3641 filename
753ad988
KG
3642 (let ((ancestor ".")
3643 (filename-dir (file-name-as-directory filename)))
7c64272b
SM
3644 (while (not
3645 (or
3646 (eq t (compare-strings filename-dir nil (length directory)
3647 directory nil nil case-fold-search))
3648 (eq t (compare-strings filename nil (length directory)
3649 directory nil nil case-fold-search))))
753ad988 3650 (setq directory (file-name-directory (substring directory 0 -1))
9695aac6
RS
3651 ancestor (if (equal ancestor ".")
3652 ".."
3653 (concat "../" ancestor))))
753ad988 3654 ;; Now ancestor is empty, or .., or ../.., etc.
7c64272b
SM
3655 (if (eq t (compare-strings filename nil (length directory)
3656 directory nil nil case-fold-search))
753ad988
KG
3657 ;; We matched within FILENAME's directory part.
3658 ;; Add the rest of FILENAME onto ANCESTOR.
3f7d6528 3659 (let ((rest (substring filename (length directory))))
753ad988 3660 (if (and (equal ancestor ".") (not (equal rest "")))
9695aac6
RS
3661 ;; But don't bother with ANCESTOR if it would give us `./'.
3662 rest
3663 (concat (file-name-as-directory ancestor) rest)))
753ad988
KG
3664 ;; We matched FILENAME's directory equivalent.
3665 ancestor))))))
b4da00e9
RM
3666\f
3667(defun save-buffer (&optional args)
e8f4db18
RS
3668 "Save current buffer in visited file if modified.
3669Variations are described below.
3670
b4da00e9
RM
3671By default, makes the previous version into a backup file
3672 if previously requested or if this is the first save.
dc2ab26e 3673Prefixed with one \\[universal-argument], marks this version
b4da00e9 3674 to become a backup when the next save is done.
dc2ab26e 3675Prefixed with two \\[universal-argument]'s,
b4da00e9 3676 unconditionally makes the previous version into a backup file.
dc2ab26e 3677Prefixed with three \\[universal-argument]'s, marks this version
ac9650be
RS
3678 to become a backup when the next save is done,
3679 and unconditionally makes the previous version into a backup file.
3680
dc2ab26e
EZ
3681With a numeric argument of 0, never make the previous version
3682into a backup file.
b4da00e9
RM
3683
3684If a file's name is FOO, the names of its numbered backup versions are
3685 FOO.~i~ for various integers i. A non-numbered backup file is called FOO~.
3686Numeric backups (rather than FOO~) will be made if value of
3687 `version-control' is not the atom `never' and either there are already
3688 numeric versions of the file being backed up, or `version-control' is
3689 non-nil.
3690We don't want excessive versions piling up, so there are variables
3691 `kept-old-versions', which tells Emacs how many oldest versions to keep,
3692 and `kept-new-versions', which tells how many newest versions to keep.
3693 Defaults are 2 old versions and 2 new.
3694`dired-kept-versions' controls dired's clean-directory (.) command.
de7d5e1b 3695If `delete-old-versions' is nil, system will query user
e73ec04b
RS
3696 before trimming versions. Otherwise it does it silently.
3697
749d2ee6
RS
3698If `vc-make-backup-files' is nil, which is the default,
3699 no backup files are made for files managed by version control.
3700 (This is because the version control system itself records previous versions.)
3701
e73ec04b 3702See the subroutine `basic-save-buffer' for more information."
b4da00e9
RM
3703 (interactive "p")
3704 (let ((modp (buffer-modified-p))
3705 (large (> (buffer-size) 50000))
b5a8e0fc
RS
3706 (make-backup-files (or (and make-backup-files (not (eq args 0)))
3707 (memq args '(16 64)))))
b4da00e9 3708 (and modp (memq args '(16 64)) (setq buffer-backed-up nil))
b4990dde
GM
3709 (if (and modp large (buffer-file-name))
3710 (message "Saving file %s..." (buffer-file-name)))
b4da00e9
RM
3711 (basic-save-buffer)
3712 (and modp (memq args '(4 64)) (setq buffer-backed-up nil))))
3713
3714(defun delete-auto-save-file-if-necessary (&optional force)
3715 "Delete auto-save file for current buffer if `delete-auto-save-files' is t.
3716Normally delete only if the file was written by this Emacs since
3717the last real save, but optional arg FORCE non-nil means delete anyway."
3718 (and buffer-auto-save-file-name delete-auto-save-files
3719 (not (string= buffer-file-name buffer-auto-save-file-name))
3720 (or force (recent-auto-save-p))
3721 (progn
3722 (condition-case ()
3723 (delete-file buffer-auto-save-file-name)
3724 (file-error nil))
3725 (set-buffer-auto-saved))))
3726
481f215b
KH
3727(defvar auto-save-hook nil
3728 "Normal hook run just before auto-saving.")
3729
3c3b81d1
SJ
3730(defcustom before-save-hook nil
3731 "Normal hook that is run before a buffer is saved to its file."
25f6295e 3732 :options '(copyright-update time-stamp)
3c3b81d1
SJ
3733 :type 'hook
3734 :group 'files)
3735
ffc0e1ca
AS
3736(defcustom after-save-hook nil
3737 "Normal hook that is run after a buffer is saved to its file."
3738 :options '(executable-make-buffer-file-executable-if-script-p)
3739 :type 'hook
3740 :group 'files)
1cc852cc 3741
0516edee
RS
3742(defvar save-buffer-coding-system nil
3743 "If non-nil, use this coding system for saving the buffer.
3744More precisely, use this coding system in place of the
3745value of `buffer-file-coding-system', when saving the buffer.
3746Calling `write-region' for any purpose other than saving the buffer
3747will still use `buffer-file-coding-system'; this variable has no effect
3748in such cases.")
3749
d5fe94cc
RS
3750(make-variable-buffer-local 'save-buffer-coding-system)
3751(put 'save-buffer-coding-system 'permanent-local t)
3752
b4da00e9 3753(defun basic-save-buffer ()
1cc852cc 3754 "Save the current buffer in its visited file, if it has been modified.
0370fe77
SM
3755The hooks `write-contents-functions' and `write-file-functions' get a chance
3756to do the job of saving; if they do not, then the buffer is saved in
222cf381 3757the visited file in the usual way.
3c3b81d1
SJ
3758Before and after saving the buffer, this function runs
3759`before-save-hook' and `after-save-hook', respectively."
b4da00e9 3760 (interactive)
19618231 3761 (save-current-buffer
c11a94fe
RS
3762 ;; In an indirect buffer, save its base buffer instead.
3763 (if (buffer-base-buffer)
3764 (set-buffer (buffer-base-buffer)))
3765 (if (buffer-modified-p)
3766 (let ((recent-save (recent-auto-save-p))
818286f4 3767 setmodes)
c11a94fe
RS
3768 ;; On VMS, rename file and buffer to get rid of version number.
3769 (if (and (eq system-type 'vax-vms)
3770 (not (string= buffer-file-name
3771 (file-name-sans-versions buffer-file-name))))
3772 (let (buffer-new-name)
3773 ;; Strip VMS version number before save.
3774 (setq buffer-file-name
3775 (file-name-sans-versions buffer-file-name))
3776 ;; Construct a (unique) buffer name to correspond.
3777 (let ((buf (create-file-buffer (downcase buffer-file-name))))
3778 (setq buffer-new-name (buffer-name buf))
3779 (kill-buffer buf))
3780 (rename-buffer buffer-new-name)))
3781 ;; If buffer has no file name, ask user for one.
3782 (or buffer-file-name
182891ef
RS
3783 (let ((filename
3784 (expand-file-name
3785 (read-file-name "File to save in: ") nil)))
8400146f
MR
3786 (if (file-exists-p filename)
3787 (if (file-directory-p filename)
3788 ;; Signal an error if the user specified the name of an
3789 ;; existing directory.
3790 (error "%s is a directory" filename)
3791 (unless (y-or-n-p (format "File `%s' exists; overwrite? "
3792 filename))
3793 (error "Canceled")))
3794 ;; Signal an error if the specified name refers to a
3795 ;; non-existing directory.
3796 (let ((dir (file-name-directory filename)))
3797 (unless (file-directory-p dir)
3798 (if (file-exists-p dir)
3799 (error "%s is not a directory" dir)
3800 (error "%s: no such directory" dir)))))
182891ef 3801 (set-visited-file-name filename)))
c11a94fe
RS
3802 (or (verify-visited-file-modtime (current-buffer))
3803 (not (file-exists-p buffer-file-name))
3804 (yes-or-no-p
3805 (format "%s has changed since visited or saved. Save anyway? "
3806 (file-name-nondirectory buffer-file-name)))
3807 (error "Save not confirmed"))
3808 (save-restriction
3809 (widen)
19618231 3810 (save-excursion
0370fe77 3811 (and (> (point-max) (point-min))
407b4328 3812 (not find-file-literally)
19618231
RS
3813 (/= (char-after (1- (point-max))) ?\n)
3814 (not (and (eq selective-display t)
3815 (= (char-after (1- (point-max))) ?\r)))
3816 (or (eq require-final-newline t)
f4206092 3817 (eq require-final-newline 'visit-save)
19618231
RS
3818 (and require-final-newline
3819 (y-or-n-p
3820 (format "Buffer %s does not end in newline. Add one? "
3821 (buffer-name)))))
3822 (save-excursion
3823 (goto-char (point-max))
3824 (insert ?\n))))
fa5867f6
AS
3825 ;; Support VC version backups.
3826 (vc-before-save)
3c3b81d1 3827 (run-hooks 'before-save-hook)
0370fe77 3828 (or (run-hook-with-args-until-success 'write-contents-functions)
c11a94fe 3829 (run-hook-with-args-until-success 'local-write-file-hooks)
0370fe77 3830 (run-hook-with-args-until-success 'write-file-functions)
0ba5894b
RS
3831 ;; If a hook returned t, file is already "written".
3832 ;; Otherwise, write it the usual way now.
3833 (setq setmodes (basic-save-buffer-1)))
d6e8ea6f
KH
3834 ;; Now we have saved the current buffer. Let's make sure
3835 ;; that buffer-file-coding-system is fixed to what
3836 ;; actually used for saving by binding it locally.
0516edee
RS
3837 (if save-buffer-coding-system
3838 (setq save-buffer-coding-system last-coding-system-used)
3839 (setq buffer-file-coding-system last-coding-system-used))
2a47b4f5
RS
3840 (setq buffer-file-number
3841 (nthcdr 10 (file-attributes buffer-file-name)))
c11a94fe
RS
3842 (if setmodes
3843 (condition-case ()
f3f9e207 3844 (set-file-modes buffer-file-name (car setmodes))
c11a94fe
RS
3845 (error nil))))
3846 ;; If the auto-save file was recent before this command,
3847 ;; delete it now.
3848 (delete-auto-save-file-if-necessary recent-save)
49530862
RS
3849 ;; Support VC `implicit' locking.
3850 (vc-after-save)
c11a94fe
RS
3851 (run-hooks 'after-save-hook))
3852 (message "(No changes need to be saved)"))))
b4da00e9 3853
87d26afc
RS
3854;; This does the "real job" of writing a buffer into its visited file
3855;; and making a backup file. This is what is normally done
0370fe77 3856;; but inhibited if one of write-file-functions returns non-nil.
f3f9e207 3857;; It returns a value (MODES . BACKUPNAME), like backup-buffer.
87d26afc 3858(defun basic-save-buffer-1 ()
969be033
RS
3859 (prog1
3860 (if save-buffer-coding-system
3861 (let ((coding-system-for-write save-buffer-coding-system))
3862 (basic-save-buffer-2))
d5fe94cc 3863 (basic-save-buffer-2))
969be033 3864 (setq buffer-file-coding-system-explicit last-coding-system-used)))
d5fe94cc 3865
f3f9e207 3866;; This returns a value (MODES . BACKUPNAME), like backup-buffer.
d5fe94cc
RS
3867(defun basic-save-buffer-2 ()
3868 (let (tempsetmodes setmodes)
87d26afc
RS
3869 (if (not (file-writable-p buffer-file-name))
3870 (let ((dir (file-name-directory buffer-file-name)))
3871 (if (not (file-directory-p dir))
83c6f446
RS
3872 (if (file-exists-p dir)
3873 (error "%s is not a directory" dir)
87c60260 3874 (error "%s: no such directory" dir))
87d26afc
RS
3875 (if (not (file-exists-p buffer-file-name))
3876 (error "Directory %s write-protected" dir)
3877 (if (yes-or-no-p
3878 (format "File %s is write-protected; try to save anyway? "
3879 (file-name-nondirectory
3880 buffer-file-name)))
3881 (setq tempsetmodes t)
3882 (error "Attempt to save to a file which you aren't allowed to write"))))))
3883 (or buffer-backed-up
3884 (setq setmodes (backup-buffer)))
76d5492b 3885 (let ((dir (file-name-directory buffer-file-name)))
f4a0f59b
RS
3886 (if (and file-precious-flag
3887 (file-writable-p dir))
3888 ;; If file is precious, write temp name, then rename it.
3889 ;; This requires write access to the containing dir,
3890 ;; which is why we don't try it if we don't have that access.
3891 (let ((realname buffer-file-name)
44dce0fb
RS
3892 tempname succeed
3893 (umask (default-file-modes))
6782610c 3894 (old-modtime (visited-file-modtime)))
44dce0fb
RS
3895 ;; Create temp files with strict access rights. It's easy to
3896 ;; loosen them later, whereas it's impossible to close the
3897 ;; time-window of loose permissions otherwise.
f4a0f59b 3898 (unwind-protect
44dce0fb
RS
3899 (progn
3900 (clear-visited-file-modtime)
3901 (set-default-file-modes ?\700)
3902 ;; Try various temporary names.
3903 ;; This code follows the example of make-temp-file,
3904 ;; but it calls write-region in the appropriate way
3905 ;; for saving the buffer.
3906 (while (condition-case ()
3907 (progn
3908 (setq tempname
3909 (make-temp-name
3910 (expand-file-name "tmp" dir)))
3911 (write-region (point-min) (point-max)
3912 tempname nil realname
3913 buffer-file-truename 'excl)
3914 nil)
3915 (file-already-exists t))
3916 ;; The file was somehow created by someone else between
3917 ;; `make-temp-name' and `write-region', let's try again.
3918 nil)
3919 (setq succeed t))
3920 ;; Reset the umask.
3921 (set-default-file-modes umask)
3922 ;; If we failed, restore the buffer's modtime.
3923 (unless succeed
3924 (set-visited-file-modtime old-modtime)))
3925 ;; Since we have created an entirely new file,
3926 ;; make sure it gets the right permission bits set.
730df8db 3927 (setq setmodes (or setmodes
562ca538
RS
3928 (cons (or (file-modes buffer-file-name)
3929 (logand ?\666 umask))
730df8db 3930 buffer-file-name)))
f4a0f59b
RS
3931 ;; We succeeded in writing the temp file,
3932 ;; so rename it.
3933 (rename-file tempname buffer-file-name t))
3934 ;; If file not writable, see if we can make it writable
3935 ;; temporarily while we write it.
3936 ;; But no need to do so if we have just backed it up
3937 ;; (setmodes is set) because that says we're superseding.
3938 (cond ((and tempsetmodes (not setmodes))
3939 ;; Change the mode back, after writing.
f3f9e207
RS
3940 (setq setmodes (cons (file-modes buffer-file-name) buffer-file-name))
3941 (set-file-modes buffer-file-name (logior (car setmodes) 128))))
3942 (let (success)
3943 (unwind-protect
3944 (progn
3945 (write-region (point-min) (point-max)
3946 buffer-file-name nil t buffer-file-truename)
3947 (setq success t))
3948 ;; If we get an error writing the new file, and we made
3949 ;; the backup by renaming, undo the backing-up.
3950 (and setmodes (not success)
0133dab9
EZ
3951 (progn
3952 (rename-file (cdr setmodes) buffer-file-name t)
3953 (setq buffer-backed-up nil)))))))
87d26afc
RS
3954 setmodes))
3955
1eeae2a1
RS
3956(defun diff-buffer-with-file (&optional buffer)
3957 "View the differences between BUFFER and its associated file.
0b9e4749 3958This requires the external program `diff' to be in your `exec-path'."
1eeae2a1 3959 (interactive "bBuffer: ")
0b9e4749 3960 (with-current-buffer (get-buffer (or buffer (current-buffer)))
4e4e9519
MR
3961 (if (and buffer-file-name
3962 (file-exists-p buffer-file-name))
3963 (let ((tempfile (make-temp-file "buffer-content-")))
3964 (unwind-protect
3965 (save-restriction
3966 (widen)
3967 (write-region (point-min) (point-max) tempfile nil 'nomessage)
3968 (diff buffer-file-name tempfile nil t)
3969 (sit-for 0))
3970 (when (file-exists-p tempfile)
3971 (delete-file tempfile))))
3972 (message "Buffer %s has no associated file on disc" (buffer-name))
3973 ;; Display that message for 1 second so that user can read it
3974 ;; in the minibuffer.
3975 (sit-for 1)))
3976 ;; return always nil, so that save-buffers-kill-emacs will not move
3977 ;; over to the next unsaved buffer when calling `d'.
3978 nil)
1eeae2a1
RS
3979
3980(defvar save-some-buffers-action-alist
3981 '((?\C-r
3982 (lambda (buf)
3983 (view-buffer buf
3984 (lambda (ignore)
3985 (exit-recursive-edit)))
3986 (recursive-edit)
3987 ;; Return nil to ask about BUF again.
3988 nil)
5c471b12 3989 "view this buffer")
16abdbe6
CY
3990 (?d (lambda (buf)
3991 (save-window-excursion
3992 (diff-buffer-with-file buf))
3993 (view-buffer (get-buffer-create "*Diff*")
3994 (lambda (ignore) (exit-recursive-edit)))
3995 (recursive-edit)
3996 nil)
5c471b12 3997 "view changes in this buffer"))
1eeae2a1 3998 "ACTION-ALIST argument used in call to `map-y-or-n-p'.")
1eeae2a1 3999
a1b0c2a7
RS
4000(defvar buffer-save-without-query nil
4001 "Non-nil means `save-some-buffers' should save this buffer without asking.")
4002(make-variable-buffer-local 'buffer-save-without-query)
4003
ffc0e1ca 4004(defun save-some-buffers (&optional arg pred)
b4da00e9 4005 "Save some modified file-visiting buffers. Asks user about each one.
1eeae2a1
RS
4006You can answer `y' to save, `n' not to save, `C-r' to look at the
4007buffer in question with `view-buffer' before deciding or `d' to
126c9dda 4008view the differences using `diff-buffer-with-file'.
8fd9c174 4009
5bbbceb1 4010Optional argument (the prefix) non-nil means save all with no questions.
ffc0e1ca
AS
4011Optional second argument PRED determines which buffers are considered:
4012If PRED is nil, all the file-visiting buffers are considered.
4013If PRED is t, then certain non-file buffers will also be considered.
4014If PRED is a zero-argument function, it indicates for each buffer whether
1eeae2a1
RS
4015to consider it or not when called with that buffer current.
4016
4017See `save-some-buffers-action-alist' if you want to
4018change the additional actions you can take on files."
b4da00e9 4019 (interactive "P")
907482b9 4020 (save-window-excursion
a1b0c2a7
RS
4021 (let* (queried some-automatic
4022 files-done abbrevs-done)
4023 (dolist (buffer (buffer-list))
4024 ;; First save any buffers that we're supposed to save unconditionally.
4025 ;; That way the following code won't ask about them.
4026 (with-current-buffer buffer
4027 (when (and buffer-save-without-query (buffer-modified-p))
4028 (setq some-automatic t)
4029 (save-buffer))))
4030 ;; Ask about those buffers that merit it,
4031 ;; and record the number thus saved.
4032 (setq files-done
76d5492b
RM
4033 (map-y-or-n-p
4034 (function
4035 (lambda (buffer)
4036 (and (buffer-modified-p buffer)
4037 (not (buffer-base-buffer buffer))
4038 (or
4039 (buffer-file-name buffer)
ffc0e1ca 4040 (and pred
76d5492b
RM
4041 (progn
4042 (set-buffer buffer)
4043 (and buffer-offer-save (> (buffer-size) 0)))))
ffc0e1ca
AS
4044 (or (not (functionp pred))
4045 (with-current-buffer buffer (funcall pred)))
76d5492b
RM
4046 (if arg
4047 t
4048 (setq queried t)
4049 (if (buffer-file-name buffer)
4050 (format "Save file %s? "
4051 (buffer-file-name buffer))
4052 (format "Save buffer %s? "
4053 (buffer-name buffer)))))))
4054 (function
4055 (lambda (buffer)
4056 (set-buffer buffer)
4057 (save-buffer)))
4058 (buffer-list)
4059 '("buffer" "buffers" "save")
1eeae2a1 4060 save-some-buffers-action-alist))
bf247b6e 4061 ;; Maybe to save abbrevs, and record whether
a1b0c2a7
RS
4062 ;; we either saved them or asked to.
4063 (and save-abbrevs abbrevs-changed
4064 (progn
4065 (if (or arg
4066 (eq save-abbrevs 'silently)
4067 (y-or-n-p (format "Save abbrevs in %s? "
4068 abbrev-file-name)))
4069 (write-abbrev-file nil))
4070 ;; Don't keep bothering user if he says no.
4071 (setq abbrevs-changed nil)
4072 (setq abbrevs-done t)))
76d5492b 4073 (or queried (> files-done 0) abbrevs-done
a1b0c2a7
RS
4074 (message (if some-automatic
4075 "(Some special files were saved without asking)"
4076 "(No files need saving)"))))))
b4da00e9
RM
4077\f
4078(defun not-modified (&optional arg)
4079 "Mark current buffer as unmodified, not needing to be saved.
a641f9a1
RM
4080With prefix arg, mark buffer as modified, so \\[save-buffer] will save.
4081
4082It is not a good idea to use this function in Lisp programs, because it
4083prints a message in the minibuffer. Instead, use `set-buffer-modified-p'."
b4da00e9
RM
4084 (interactive "P")
4085 (message (if arg "Modification-flag set"
4086 "Modification-flag cleared"))
4087 (set-buffer-modified-p arg))
4088
4089(defun toggle-read-only (&optional arg)
4090 "Change whether this buffer is visiting its file read-only.
4837b516
GM
4091With prefix argument ARG, make the buffer read-only if ARG is
4092positive, otherwise make it writable. If visiting file read-only
4093and `view-read-only' is non-nil, enter view mode."
b4da00e9 4094 (interactive "P")
c60ee5e7 4095 (if (and arg
d758359d
AS
4096 (if (> (prefix-numeric-value arg) 0) buffer-read-only
4097 (not buffer-read-only))) ; If buffer-read-only is set correctly,
4098 nil ; do nothing.
4099 ;; Toggle.
4100 (cond
4101 ((and buffer-read-only view-mode)
4102 (View-exit-and-edit)
4103 (make-local-variable 'view-read-only)
4104 (setq view-read-only t)) ; Must leave view mode.
4105 ((and (not buffer-read-only) view-read-only
818286f4
SM
4106 ;; If view-mode is already active, `view-mode-enter' is a nop.
4107 (not view-mode)
d758359d
AS
4108 (not (eq (get major-mode 'mode-class) 'special)))
4109 (view-mode-enter))
4110 (t (setq buffer-read-only (not buffer-read-only))
4111 (force-mode-line-update)))
4112 (if (vc-backend buffer-file-name)
8a26c165 4113 (message "%s" (substitute-command-keys
a5dd5f60
RS
4114 (concat "File is under version-control; "
4115 "use \\[vc-next-action] to check in/out"))))))
b4da00e9 4116
912192d1 4117(defun insert-file (filename)
b4da00e9
RM
4118 "Insert contents of file FILENAME into buffer after point.
4119Set mark after the inserted text.
4120
4121This function is meant for the user to run interactively.
4122Don't call it from programs! Use `insert-file-contents' instead.
4123\(Its calling sequence is different; see its documentation)."
912192d1 4124 (interactive "*fInsert file: ")
3a64a3cf 4125 (insert-file-1 filename #'insert-file-contents))
b4da00e9 4126
912192d1 4127(defun append-to-file (start end filename)
b4da00e9
RM
4128 "Append the contents of the region to the end of file FILENAME.
4129When called from a function, expects three arguments,
4130START, END and FILENAME. START and END are buffer positions
da30bf98 4131saying what text to write."
912192d1
KH
4132 (interactive "r\nFAppend to file: ")
4133 (write-region start end filename t))
b4da00e9
RM
4134
4135(defun file-newest-backup (filename)
4136 "Return most recent backup file for FILENAME or nil if no backups exist."
ffc0e1ca
AS
4137 ;; `make-backup-file-name' will get us the right directory for
4138 ;; ordinary or numeric backups. It might create a directory for
4139 ;; backups as a side-effect, according to `backup-directory-alist'.
e31cfca5 4140 (let* ((filename (file-name-sans-versions
783bf210 4141 (make-backup-file-name (expand-file-name filename))))
b4da00e9
RM
4142 (file (file-name-nondirectory filename))
4143 (dir (file-name-directory filename))
4144 (comp (file-name-all-completions file dir))
cf7e94a0
RS
4145 (newest nil)
4146 tem)
b4da00e9 4147 (while comp
ffc0e1ca 4148 (setq tem (pop comp))
cf7e94a0
RS
4149 (cond ((and (backup-file-name-p tem)
4150 (string= (file-name-sans-versions tem) file))
4151 (setq tem (concat dir tem))
4152 (if (or (null newest)
4153 (file-newer-than-file-p tem newest))
4154 (setq newest tem)))))
b4da00e9
RM
4155 newest))
4156
4157(defun rename-uniquely ()
4158 "Rename current buffer to a similar name not already taken.
4159This function is useful for creating multiple shell process buffers
4160or multiple mail buffers, etc."
4161 (interactive)
40eb8038 4162 (save-match-data
e0df3aef
KH
4163 (let ((base-name (buffer-name)))
4164 (and (string-match "<[0-9]+>\\'" base-name)
4165 (not (and buffer-file-name
4166 (string= base-name
4167 (file-name-nondirectory buffer-file-name))))
4168 ;; If the existing buffer name has a <NNN>,
4169 ;; which isn't part of the file name (if any),
4170 ;; then get rid of that.
4171 (setq base-name (substring base-name 0 (match-beginning 0))))
4172 (rename-buffer (generate-new-buffer-name base-name))
3941fe2c 4173 (force-mode-line-update))))
5bbbceb1 4174
4e43240a 4175(defun make-directory (dir &optional parents)
5ce8bb89 4176 "Create the directory DIR and any nonexistent parent dirs.
ae0ece90 4177If DIR already exists as a directory, signal an error, unless PARENTS is set.
789cb0f9 4178
5ce8bb89
RS
4179Interactively, the default choice of directory to create
4180is the current default directory for file names.
0225ae5e 4181That is useful when you have visited a file in a nonexistent directory.
5ce8bb89
RS
4182
4183Noninteractively, the second (optional) argument PARENTS says whether
07703430
RS
4184to create parent directories if they don't exist. Interactively,
4185this happens by default."
5ce8bb89
RS
4186 (interactive
4187 (list (read-file-name "Make directory: " default-directory default-directory
4188 nil nil)
4189 t))
ee291b46
RS
4190 ;; If default-directory is a remote directory,
4191 ;; make sure we find its make-directory handler.
4192 (setq dir (expand-file-name dir))
6eaebaa2 4193 (let ((handler (find-file-name-handler dir 'make-directory)))
4e43240a
RS
4194 (if handler
4195 (funcall handler 'make-directory dir parents)
4196 (if (not parents)
4197 (make-directory-internal dir)
4198 (let ((dir (directory-file-name (expand-file-name dir)))
4199 create-list)
4200 (while (not (file-exists-p dir))
76d5492b 4201 (setq create-list (cons dir create-list)
4e43240a
RS
4202 dir (directory-file-name (file-name-directory dir))))
4203 (while create-list
4204 (make-directory-internal (car create-list))
4205 (setq create-list (cdr create-list))))))))
b4da00e9
RM
4206\f
4207(put 'revert-buffer-function 'permanent-local t)
4208(defvar revert-buffer-function nil
0973d78b
RS
4209 "Function to use to revert this buffer, or nil to do the default.
4210The function receives two arguments IGNORE-AUTO and NOCONFIRM,
4211which are the arguments that `revert-buffer' received.")
b4da00e9
RM
4212
4213(put 'revert-buffer-insert-file-contents-function 'permanent-local t)
4214(defvar revert-buffer-insert-file-contents-function nil
4215 "Function to use to insert contents when reverting this buffer.
4216Gets two args, first the nominal file name to use,
2df32500
RS
4217and second, t if reading the auto-save file.
4218
4219The function you specify is responsible for updating (or preserving) point.")
b4da00e9 4220
b0dc9757
LT
4221(defvar buffer-stale-function nil
4222 "Function to check whether a non-file buffer needs reverting.
4223This should be a function with one optional argument NOCONFIRM.
44dce0fb 4224Auto Revert Mode passes t for NOCONFIRM. The function should return
8b0b6932
LT
4225non-nil if the buffer should be reverted. A return value of
4226`fast' means that the need for reverting was not checked, but
4227that reverting the buffer is fast. The buffer is current when
4228this function is called.
b0dc9757 4229
4f8453ae
LT
4230The idea behind the NOCONFIRM argument is that it should be
4231non-nil if the buffer is going to be reverted without asking the
4232user. In such situations, one has to be careful with potentially
c90dcdd5
LT
4233time consuming operations.
4234
4235For more information on how this variable is used by Auto Revert mode,
b3a59350 4236see Info node `(emacs)Supporting additional buffers'.")
b0dc9757 4237
5f76e7d4
KH
4238(defvar before-revert-hook nil
4239 "Normal hook for `revert-buffer' to run before reverting.
4240If `revert-buffer-function' is used to override the normal revert
4241mechanism, this hook is not used.")
4242
4243(defvar after-revert-hook nil
4244 "Normal hook for `revert-buffer' to run after reverting.
4245Note that the hook value that it runs is the value that was in effect
4246before reverting; that makes a difference if you have buffer-local
4247hook functions.
4248
4249If `revert-buffer-function' is used to override the normal revert
4250mechanism, this hook is not used.")
4251
1554c03b
RS
4252(defvar revert-buffer-internal-hook)
4253
9a30563f 4254(defun revert-buffer (&optional ignore-auto noconfirm preserve-modes)
7e7c9c4e 4255 "Replace current buffer text with the text of the visited file on disk.
b4da00e9 4256This undoes all changes since the file was visited or saved.
8c0e7b73
JB
4257With a prefix argument, offer to revert from latest auto-save file, if
4258that is more recent than the visited file.
1ab31687 4259
0dff8975
VJL
4260This command also implements an interface for special buffers
4261that contain text which doesn't come from a file, but reflects
4262some other data instead (e.g. Dired buffers, `buffer-list'
c84b3004
VJL
4263buffers). This is done via the variable
4264`revert-buffer-function'. In these cases, it should reconstruct
0dff8975 4265the buffer contents from the appropriate data.
7e7c9c4e 4266
65ee6096 4267When called from Lisp, the first argument is IGNORE-AUTO; only offer
1ab31687
JB
4268to revert from the auto-save file when this is nil. Note that the
4269sense of this argument is the reverse of the prefix argument, for the
4270sake of backward compatibility. IGNORE-AUTO is optional, defaulting
4271to nil.
4272
4273Optional second argument NOCONFIRM means don't ask for confirmation at
518dc5be
EZ
4274all. \(The variable `revert-without-query' offers another way to
4275revert buffers without querying for confirmation.)
b4da00e9 4276
5b2b26d5
RS
4277Optional third argument PRESERVE-MODES non-nil means don't alter
4278the files modes. Normally we reinitialize them using `normal-mode'.
4279
8c0e7b73 4280If the value of `revert-buffer-function' is non-nil, it is called to
7e7c9c4e
RS
4281do all the work for this command. Otherwise, the hooks
4282`before-revert-hook' and `after-revert-hook' are run at the beginning
4283and the end, and if `revert-buffer-insert-file-contents-function' is
4284non-nil, it is called instead of rereading visited file contents."
fb6208a6 4285
1ab31687
JB
4286 ;; I admit it's odd to reverse the sense of the prefix argument, but
4287 ;; there is a lot of code out there which assumes that the first
4288 ;; argument should be t to avoid consulting the auto-save file, and
4289 ;; there's no straightforward way to encourage authors to notice a
4290 ;; reversal of the argument sense. So I'm just changing the user
4291 ;; interface, but leaving the programmatic interface the same.
e0867e99 4292 (interactive (list (not current-prefix-arg)))
b4da00e9 4293 (if revert-buffer-function
1ab31687 4294 (funcall revert-buffer-function ignore-auto noconfirm)
44dce0fb
RS
4295 (with-current-buffer (or (buffer-base-buffer (current-buffer))
4296 (current-buffer))
4297 (let* ((auto-save-p (and (not ignore-auto)
4298 (recent-auto-save-p)
4299 buffer-auto-save-file-name
4300 (file-readable-p buffer-auto-save-file-name)
4301 (y-or-n-p
4302 "Buffer has been auto-saved recently. Revert from auto-save file? ")))
4303 (file-name (if auto-save-p
4304 buffer-auto-save-file-name
4305 buffer-file-name)))
4306 (cond ((null file-name)
4307 (error "Buffer does not seem to be associated with any file"))
4308 ((or noconfirm
4309 (and (not (buffer-modified-p))
518dc5be
EZ
4310 (catch 'found
4311 (dolist (regexp revert-without-query)
4312 (when (string-match regexp file-name)
4313 (throw 'found t)))))
44dce0fb
RS
4314 (yes-or-no-p (format "Revert buffer from file %s? "
4315 file-name)))
4316 (run-hooks 'before-revert-hook)
4317 ;; If file was backed up but has changed since,
4318 ;; we shd make another backup.
4319 (and (not auto-save-p)
4320 (not (verify-visited-file-modtime (current-buffer)))
4321 (setq buffer-backed-up nil))
44dce0fb
RS
4322 ;; Effectively copy the after-revert-hook status,
4323 ;; since after-find-file will clobber it.
4324 (let ((global-hook (default-value 'after-revert-hook))
518dc5be
EZ
4325 (local-hook (when (local-variable-p 'after-revert-hook)
4326 after-revert-hook))
4327 (inhibit-read-only t))
4328 (cond
4329 (revert-buffer-insert-file-contents-function
4330 (unless (eq buffer-undo-list t)
4331 ;; Get rid of all undo records for this buffer.
4332 (setq buffer-undo-list nil))
4333 ;; Don't make undo records for the reversion.
4334 (let ((buffer-undo-list t))
4335 (funcall revert-buffer-insert-file-contents-function
4336 file-name auto-save-p)))
4337 ((not (file-exists-p file-name))
4338 (error (if buffer-file-number
4339 "File %s no longer exists!"
4340 "Cannot revert nonexistent file %s")
4341 file-name))
b2d239c1
RS
4342 ((not (file-readable-p file-name))
4343 (error (if buffer-file-number
4344 "File %s no longer readable!"
4345 "Cannot revert unreadable file %s")
4346 file-name))
518dc5be
EZ
4347 (t
4348 ;; Bind buffer-file-name to nil
4349 ;; so that we don't try to lock the file.
4350 (let ((buffer-file-name nil))
4351 (or auto-save-p
4352 (unlock-buffer)))
4353 (widen)
4354 (let ((coding-system-for-read
4355 ;; Auto-saved file should be read by Emacs'
4356 ;; internal coding.
4357 (if auto-save-p 'auto-save-coding
4358 (or coding-system-for-read
4359 buffer-file-coding-system-explicit))))
e1ee3b54 4360 (if (and (not enable-multibyte-characters)
52f9b751 4361 coding-system-for-read
e1ee3b54
KH
4362 (not (memq (coding-system-base
4363 coding-system-for-read)
4364 '(no-conversion raw-text))))
4365 ;; As a coding system suitable for multibyte
4366 ;; buffer is specified, make the current
4367 ;; buffer multibyte.
4368 (set-buffer-multibyte t))
4369
518dc5be
EZ
4370 ;; This force after-insert-file-set-coding
4371 ;; (called from insert-file-contents) to set
4372 ;; buffer-file-coding-system to a proper value.
4373 (kill-local-variable 'buffer-file-coding-system)
4374
4375 ;; Note that this preserves point in an intelligent way.
4376 (if preserve-modes
4377 (let ((buffer-file-format buffer-file-format))
4378 (insert-file-contents file-name (not auto-save-p)
4379 nil nil t))
4380 (insert-file-contents file-name (not auto-save-p)
2a29c409 4381 nil nil t)))))
44dce0fb
RS
4382 ;; Recompute the truename in case changes in symlinks
4383 ;; have changed the truename.
4384 (setq buffer-file-truename
4385 (abbreviate-file-name (file-truename buffer-file-name)))
4386 (after-find-file nil nil t t preserve-modes)
4387 ;; Run after-revert-hook as it was before we reverted.
4388 (setq-default revert-buffer-internal-hook global-hook)
518dc5be 4389 (if local-hook
44dce0fb
RS
4390 (set (make-local-variable 'revert-buffer-internal-hook)
4391 local-hook)
4392 (kill-local-variable 'revert-buffer-internal-hook))
4393 (run-hooks 'revert-buffer-internal-hook))
4394 t))))))
b4da00e9 4395
64d18e8f
RS
4396(defun recover-this-file ()
4397 "Recover the visited file--get contents from its last auto-save file."
4398 (interactive)
4399 (recover-file buffer-file-name))
4400
b4da00e9
RM
4401(defun recover-file (file)
4402 "Visit file FILE, but get contents from its last auto-save file."
10f7c7fc
RS
4403 ;; Actually putting the file name in the minibuffer should be used
4404 ;; only rarely.
4405 ;; Not just because users often use the default.
e1dadc17 4406 (interactive "FRecover file: ")
b4da00e9 4407 (setq file (expand-file-name file))
f7da6740 4408 (if (auto-save-file-name-p (file-name-nondirectory file))
4e163715 4409 (error "%s is an auto-save file" (abbreviate-file-name file)))
b4da00e9
RM
4410 (let ((file-name (let ((buffer-file-name file))
4411 (make-auto-save-file-name))))
945e1965
RS
4412 (cond ((if (file-exists-p file)
4413 (not (file-newer-than-file-p file-name file))
4414 (not (file-exists-p file-name)))
4e163715
SM
4415 (error "Auto-save file %s not current"
4416 (abbreviate-file-name file-name)))
b4da00e9 4417 ((save-window-excursion
ffc0e1ca
AS
4418 (with-output-to-temp-buffer "*Directory*"
4419 (buffer-disable-undo standard-output)
4420 (save-excursion
4421 (let ((switches dired-listing-switches))
4422 (if (file-symlink-p file)
4423 (setq switches (concat switches "L")))
4424 (set-buffer standard-output)
bc22fd18
EZ
4425 ;; Use insert-directory-safely, not insert-directory,
4426 ;; because these files might not exist. In particular,
4427 ;; FILE might not exist if the auto-save file was for
4428 ;; a buffer that didn't visit a file, such as "*mail*".
4429 ;; The code in v20.x called `ls' directly, so we need
4430 ;; to emulate what `ls' did in that case.
4431 (insert-directory-safely file switches)
4432 (insert-directory-safely file-name switches))))
b4da00e9
RM
4433 (yes-or-no-p (format "Recover auto save file %s? " file-name)))
4434 (switch-to-buffer (find-file-noselect file t))
518dc5be 4435 (let ((inhibit-read-only t)
1e87edf5
KH
4436 ;; Keep the current buffer-file-coding-system.
4437 (coding-system buffer-file-coding-system)
1d0ec0d1 4438 ;; Auto-saved file should be read with special coding.
77619f8e 4439 (coding-system-for-read 'auto-save-coding))
b4da00e9 4440 (erase-buffer)
1e87edf5
KH
4441 (insert-file-contents file-name nil)
4442 (set-buffer-file-coding-system coding-system))
8cfb9d46 4443 (after-find-file nil nil t))
ffa7ab70 4444 (t (error "Recover-file cancelled")))))
b4da00e9 4445
6598027d 4446(defun recover-session ()
9aee5392
RS
4447 "Recover auto save files from a previous Emacs session.
4448This command first displays a Dired buffer showing you the
4449previous sessions that you could recover from.
4450To choose one, move point to the proper line and then type C-c C-c.
4451Then you'll be asked about a number of files to recover."
4452 (interactive)
363a5030
RS
4453 (if (null auto-save-list-file-prefix)
4454 (error "You set `auto-save-list-file-prefix' to disable making session files"))
ffc0e1ca
AS
4455 (let ((dir (file-name-directory auto-save-list-file-prefix)))
4456 (unless (file-directory-p dir)
194600a8
JPW
4457 (make-directory dir t))
4458 (unless (directory-files dir nil
4459 (concat "\\`" (regexp-quote
4460 (file-name-nondirectory
4461 auto-save-list-file-prefix)))
4462 t)
4463 (error "No previous sessions to recover")))
6f4983e6 4464 (let ((ls-lisp-support-shell-wildcards t))
7b3478a5
RS
4465 (dired (concat auto-save-list-file-prefix "*")
4466 (concat dired-listing-switches "t")))
05e076c7
AS
4467 (save-excursion
4468 (goto-char (point-min))
4469 (or (looking-at " Move to the session you want to recover,")
4470 (let ((inhibit-read-only t))
4471 ;; Each line starts with a space
4472 ;; so that Font Lock mode won't highlight the first character.
4473 (insert " Move to the session you want to recover,\n"
4474 " then type C-c C-c to select it.\n\n"
4475 " You can also delete some of these files;\n"
4476 " type d on a line to mark that file for deletion.\n\n"))))
9aee5392 4477 (use-local-map (nconc (make-sparse-keymap) (current-local-map)))
80280bb7 4478 (define-key (current-local-map) "\C-c\C-c" 'recover-session-finish))
9aee5392 4479
80280bb7 4480(defun recover-session-finish ()
9aee5392
RS
4481 "Choose one saved session to recover auto-save files from.
4482This command is used in the special Dired buffer created by
80280bb7 4483\\[recover-session]."
9aee5392
RS
4484 (interactive)
4485 ;; Get the name of the session file to recover from.
4486 (let ((file (dired-get-filename))
953a03b2 4487 files
9aee5392 4488 (buffer (get-buffer-create " *recover*")))
c11032b9 4489 (dired-unmark 1)
033ef863 4490 (dired-do-flagged-delete t)
9aee5392
RS
4491 (unwind-protect
4492 (save-excursion
4493 ;; Read in the auto-save-list file.
4494 (set-buffer buffer)
4495 (erase-buffer)
4496 (insert-file-contents file)
953a03b2
RS
4497 ;; Loop thru the text of that file
4498 ;; and get out the names of the files to recover.
4499 (while (not (eobp))
4500 (let (thisfile autofile)
4501 (if (eolp)
4502 ;; This is a pair of lines for a non-file-visiting buffer.
4503 ;; Get the auto-save file name and manufacture
4504 ;; a "visited file name" from that.
4505 (progn
4506 (forward-line 1)
259be4e6
JB
4507 ;; If there is no auto-save file name, the
4508 ;; auto-save-list file is probably corrupted.
4509 (unless (eolp)
4510 (setq autofile
4511 (buffer-substring-no-properties
4512 (point)
e442c62b 4513 (line-end-position)))
259be4e6
JB
4514 (setq thisfile
4515 (expand-file-name
4516 (substring
4517 (file-name-nondirectory autofile)
4518 1 -1)
4519 (file-name-directory autofile))))
953a03b2
RS
4520 (forward-line 1))
4521 ;; This pair of lines is a file-visiting
4522 ;; buffer. Use the visited file name.
4523 (progn
4524 (setq thisfile
4525 (buffer-substring-no-properties
4526 (point) (progn (end-of-line) (point))))
4527 (forward-line 1)
4528 (setq autofile
4529 (buffer-substring-no-properties
4530 (point) (progn (end-of-line) (point))))
4531 (forward-line 1)))
4532 ;; Ignore a file if its auto-save file does not exist now.
259be4e6 4533 (if (and autofile (file-exists-p autofile))
953a03b2
RS
4534 (setq files (cons thisfile files)))))
4535 (setq files (nreverse files))
945e1965
RS
4536 ;; The file contains a pair of line for each auto-saved buffer.
4537 ;; The first line of the pair contains the visited file name
4538 ;; or is empty if the buffer was not visiting a file.
4539 ;; The second line is the auto-save file name.
953a03b2
RS
4540 (if files
4541 (map-y-or-n-p "Recover %s? "
4542 (lambda (file)
4543 (condition-case nil
4544 (save-excursion (recover-file file))
76d5492b 4545 (error
953a03b2
RS
4546 "Failed to recover `%s'" file)))
4547 files
4548 '("file" "files" "recover"))
4549 (message "No files can be recovered from this session now")))
9aee5392
RS
4550 (kill-buffer buffer))))
4551
a151f82c
SS
4552(defun kill-buffer-ask (buffer)
4553 "Kill buffer if confirmed."
4554 (when (yes-or-no-p
4555 (format "Buffer %s %s. Kill? " (buffer-name buffer)
4556 (if (buffer-modified-p buffer)
4557 "HAS BEEN EDITED" "is unmodified")))
4558 (kill-buffer buffer)))
4559
73ba610a 4560(defun kill-some-buffers (&optional list)
243a3ae0 4561 "Kill some buffers. Asks the user whether to kill each one of them.
bb8eaf67 4562Non-interactively, if optional argument LIST is non-nil, it
243a3ae0 4563specifies the list of buffers to kill, asking for approval for each one."
b4da00e9 4564 (interactive)
73ba610a
RS
4565 (if (null list)
4566 (setq list (buffer-list)))
4567 (while list
4568 (let* ((buffer (car list))
4569 (name (buffer-name buffer)))
cbca0a4b
RS
4570 (and name ; Can be nil for an indirect buffer
4571 ; if we killed the base buffer.
4572 (not (string-equal name ""))
26b9ecbc 4573 (/= (aref name 0) ?\s)
a151f82c 4574 (kill-buffer-ask buffer)))
73ba610a 4575 (setq list (cdr list))))
a151f82c
SS
4576
4577(defun kill-matching-buffers (regexp &optional internal-too)
4578 "Kill buffers whose name matches the specified regexp.
4579The optional second argument indicates whether to kill internal buffers too."
4580 (interactive "sKill buffers matching this regular expression: \nP")
4581 (dolist (buffer (buffer-list))
4582 (let ((name (buffer-name buffer)))
4583 (when (and name (not (string-equal name ""))
4584 (or internal-too (/= (aref name 0) ?\s))
4585 (string-match regexp name))
4586 (kill-buffer-ask buffer)))))
4587
b4da00e9
RM
4588\f
4589(defun auto-save-mode (arg)
4590 "Toggle auto-saving of contents of current buffer.
f3e23606 4591With prefix argument ARG, turn auto-saving on if positive, else off."
b4da00e9
RM
4592 (interactive "P")
4593 (setq buffer-auto-save-file-name
4594 (and (if (null arg)
74b9c2af 4595 (or (not buffer-auto-save-file-name)
4e0c8650 4596 ;; If auto-save is off because buffer has shrunk,
74b9c2af
RS
4597 ;; then toggling should turn it on.
4598 (< buffer-saved-size 0))
b4da00e9
RM
4599 (or (eq arg t) (listp arg) (and (integerp arg) (> arg 0))))
4600 (if (and buffer-file-name auto-save-visited-file-name
4601 (not buffer-read-only))
4602 buffer-file-name
4603 (make-auto-save-file-name))))
0b7f1ef2
RS
4604 ;; If -1 was stored here, to temporarily turn off saving,
4605 ;; turn it back on.
4606 (and (< buffer-saved-size 0)
4607 (setq buffer-saved-size 0))
b4da00e9
RM
4608 (if (interactive-p)
4609 (message "Auto-save %s (in this buffer)"
4610 (if buffer-auto-save-file-name "on" "off")))
4611 buffer-auto-save-file-name)
4612
4613(defun rename-auto-save-file ()
4614 "Adjust current buffer's auto save file name for current conditions.
4615Also rename any existing auto save file, if it was made in this session."
4616 (let ((osave buffer-auto-save-file-name))
4617 (setq buffer-auto-save-file-name
4618 (make-auto-save-file-name))
4619 (if (and osave buffer-auto-save-file-name
4620 (not (string= buffer-auto-save-file-name buffer-file-name))
4621 (not (string= buffer-auto-save-file-name osave))
4622 (file-exists-p osave)
4623 (recent-auto-save-p))
4624 (rename-file osave buffer-auto-save-file-name t))))
4625
4626(defun make-auto-save-file-name ()
4627 "Return file name to use for auto-saves of current buffer.
4628Does not consider `auto-save-visited-file-name' as that variable is checked
4629before calling this function. You can redefine this for customization.
4630See also `auto-save-file-name-p'."
4631 (if buffer-file-name
c1105d05
MA
4632 (let ((handler (find-file-name-handler buffer-file-name
4633 'make-auto-save-file-name)))
4634 (if handler
4635 (funcall handler 'make-auto-save-file-name)
4636 (let ((list auto-save-file-name-transforms)
4637 (filename buffer-file-name)
4638 result uniq)
4639 ;; Apply user-specified translations
4640 ;; to the file name.
4641 (while (and list (not result))
4642 (if (string-match (car (car list)) filename)
4643 (setq result (replace-match (cadr (car list)) t nil
4644 filename)
4645 uniq (car (cddr (car list)))))
4646 (setq list (cdr list)))
4647 (if result
4648 (if uniq
4649 (setq filename (concat
4650 (file-name-directory result)
4651 (subst-char-in-string
4652 ?/ ?!
4653 (replace-regexp-in-string "!" "!!"
4654 filename))))
4655 (setq filename result)))
4656 (setq result
4657 (if (and (eq system-type 'ms-dos)
4658 (not (msdos-long-file-names)))
4659 ;; We truncate the file name to DOS 8+3 limits
4660 ;; before doing anything else, because the regexp
4661 ;; passed to string-match below cannot handle
4662 ;; extensions longer than 3 characters, multiple
4663 ;; dots, and other atrocities.
4664 (let ((fn (dos-8+3-filename
4665 (file-name-nondirectory buffer-file-name))))
4666 (string-match
4667 "\\`\\([^.]+\\)\\(\\.\\(..?\\)?.?\\|\\)\\'"
4668 fn)
4669 (concat (file-name-directory buffer-file-name)
4670 "#" (match-string 1 fn)
4671 "." (match-string 3 fn) "#"))
4672 (concat (file-name-directory filename)
4673 "#"
4674 (file-name-nondirectory filename)
4675 "#")))
4676 ;; Make sure auto-save file names don't contain characters
4677 ;; invalid for the underlying filesystem.
18b28ef1 4678 (if (and (memq system-type '(ms-dos windows-nt cygwin))
c1105d05
MA
4679 ;; Don't modify remote (ange-ftp) filenames
4680 (not (string-match "^/\\w+@[-A-Za-z0-9._]+:" result)))
4681 (convert-standard-filename result)
4682 result))))
0a1763b4
RS
4683
4684 ;; Deal with buffers that don't have any associated files. (Mail
4685 ;; mode tends to create a good number of these.)
4686
7d483e8c 4687 (let ((buffer-name (buffer-name))
ff5c7181 4688 (limit 0)
77d18896 4689 file-name)
ad80c679
JR
4690 ;; Restrict the characters used in the file name to those which
4691 ;; are known to be safe on all filesystems, url-encoding the
4692 ;; rest.
4693 ;; We do this on all platforms, because even if we are not
4694 ;; running on DOS/Windows, the current directory may be on a
4695 ;; mounted VFAT filesystem, such as a USB memory stick.
4696 (while (string-match "[^A-Za-z0-9-_.~#+]" buffer-name limit)
c3348e10
RS
4697 (let* ((character (aref buffer-name (match-beginning 0)))
4698 (replacement
ad80c679
JR
4699 ;; For multibyte characters, this will produce more than
4700 ;; 2 hex digits, so is not true URL encoding.
4701 (format "%%%02X" character)))
c3348e10
RS
4702 (setq buffer-name (replace-match replacement t t buffer-name))
4703 (setq limit (1+ (match-end 0)))))
a8abaf83 4704 ;; Generate the file name.
ff5c7181
RS
4705 (setq file-name
4706 (make-temp-file
4707 (let ((fname
4708 (expand-file-name
4709 (format "#%s#" buffer-name)
4710 ;; Try a few alternative directories, to get one we can
4711 ;; write it.
4712 (cond
4713 ((file-writable-p default-directory) default-directory)
4714 ((file-writable-p "/var/tmp/") "/var/tmp/")
4715 ("~/")))))
18b28ef1 4716 (if (and (memq system-type '(ms-dos windows-nt cygwin))
ff5c7181
RS
4717 ;; Don't modify remote (ange-ftp) filenames
4718 (not (string-match "^/\\w+@[-A-Za-z0-9._]+:" fname)))
4719 ;; The call to convert-standard-filename is in case
4720 ;; buffer-name includes characters not allowed by the
4721 ;; DOS/Windows filesystems. make-temp-file writes to the
4722 ;; file it creates, so we must fix the file name _before_
4723 ;; make-temp-file is called.
4724 (convert-standard-filename fname)
4725 fname))
4726 nil "#"))
4727 ;; make-temp-file creates the file,
4728 ;; but we don't want it to exist until we do an auto-save.
4729 (condition-case ()
4730 (delete-file file-name)
4731 (file-error nil))
4732 file-name)))
b4da00e9
RM
4733
4734(defun auto-save-file-name-p (filename)
4735 "Return non-nil if FILENAME can be yielded by `make-auto-save-file-name'.
4736FILENAME should lack slashes. You can redefine this for customization."
4737 (string-match "^#.*#$" filename))
4738\f
6f4983e6
RS
4739(defun wildcard-to-regexp (wildcard)
4740 "Given a shell file name pattern WILDCARD, return an equivalent regexp.
4837b516 4741The generated regexp will match a filename only if the filename
6f4983e6
RS
4742matches that wildcard according to shell rules. Only wildcards known
4743by `sh' are supported."
4744 (let* ((i (string-match "[[.*+\\^$?]" wildcard))
4745 ;; Copy the initial run of non-special characters.
4746 (result (substring wildcard 0 i))
4747 (len (length wildcard)))
4748 ;; If no special characters, we're almost done.
4749 (if i
4750 (while (< i len)
4751 (let ((ch (aref wildcard i))
4752 j)
4753 (setq
4754 result
4755 (concat result
4756 (cond
7e7c9c4e
RS
4757 ((and (eq ch ?\[)
4758 (< (1+ i) len)
4759 (eq (aref wildcard (1+ i)) ?\]))
4760 "\\[")
6f4983e6
RS
4761 ((eq ch ?\[) ; [...] maps to regexp char class
4762 (progn
4763 (setq i (1+ i))
4764 (concat
4765 (cond
4766 ((eq (aref wildcard i) ?!) ; [!...] -> [^...]
4767 (progn
4768 (setq i (1+ i))
4769 (if (eq (aref wildcard i) ?\])
4770 (progn
4771 (setq i (1+ i))
4772 "[^]")
4773 "[^")))
4774 ((eq (aref wildcard i) ?^)
4775 ;; Found "[^". Insert a `\0' character
4776 ;; (which cannot happen in a filename)
4777 ;; into the character class, so that `^'
4778 ;; is not the first character after `[',
4779 ;; and thus non-special in a regexp.
4780 (progn
4781 (setq i (1+ i))
4782 "[\000^"))
4783 ((eq (aref wildcard i) ?\])
4784 ;; I don't think `]' can appear in a
4785 ;; character class in a wildcard, but
4786 ;; let's be general here.
4787 (progn
4788 (setq i (1+ i))
4789 "[]"))
4790 (t "["))
4791 (prog1 ; copy everything upto next `]'.
4792 (substring wildcard
4793 i
4794 (setq j (string-match
4795 "]" wildcard i)))
4796 (setq i (if j (1- j) (1- len)))))))
4797 ((eq ch ?.) "\\.")
4798 ((eq ch ?*) "[^\000]*")
4799 ((eq ch ?+) "\\+")
4800 ((eq ch ?^) "\\^")
4801 ((eq ch ?$) "\\$")
4802 ((eq ch ?\\) "\\\\") ; probably cannot happen...
4803 ((eq ch ??) "[^\000]")
4804 (t (char-to-string ch)))))
4805 (setq i (1+ i)))))
4806 ;; Shell wildcards should match the entire filename,
4807 ;; not its part. Make the regexp say so.
4808 (concat "\\`" result "\\'")))
4809\f
21540597 4810(defcustom list-directory-brief-switches
b4da00e9 4811 (if (eq system-type 'vax-vms) "" "-CF")
ba83982b 4812 "Switches for `list-directory' to pass to `ls' for brief listing."
21540597
RS
4813 :type 'string
4814 :group 'dired)
b4da00e9 4815
21540597 4816(defcustom list-directory-verbose-switches
b4da00e9
RM
4817 (if (eq system-type 'vax-vms)
4818 "/PROTECTION/SIZE/DATE/OWNER/WIDTH=(OWNER:10)"
4819 "-l")
ba83982b 4820 "Switches for `list-directory' to pass to `ls' for verbose listing."
21540597
RS
4821 :type 'string
4822 :group 'dired)
b4da00e9 4823
5de148a2
RS
4824(defun file-expand-wildcards (pattern &optional full)
4825 "Expand wildcard pattern PATTERN.
4db2a7de
RS
4826This returns a list of file names which match the pattern.
4827
814af837 4828If PATTERN is written as an absolute file name,
4db2a7de
RS
4829the values are absolute also.
4830
4831If PATTERN is written as a relative file name, it is interpreted
4832relative to the current default directory, `default-directory'.
4833The file names returned are normally also relative to the current
4834default directory. However, if FULL is non-nil, they are absolute."
032388f3
RS
4835 (save-match-data
4836 (let* ((nondir (file-name-nondirectory pattern))
4837 (dirpart (file-name-directory pattern))
4838 ;; A list of all dirs that DIRPART specifies.
4839 ;; This can be more than one dir
4840 ;; if DIRPART contains wildcards.
4841 (dirs (if (and dirpart (string-match "[[*?]" dirpart))
4842 (mapcar 'file-name-as-directory
4843 (file-expand-wildcards (directory-file-name dirpart)))
4844 (list dirpart)))
4845 contents)
4846 (while dirs
4847 (when (or (null (car dirs)) ; Possible if DIRPART is not wild.
4848 (file-directory-p (directory-file-name (car dirs))))
4849 (let ((this-dir-contents
4850 ;; Filter out "." and ".."
4851 (delq nil
4852 (mapcar #'(lambda (name)
4853 (unless (string-match "\\`\\.\\.?\\'"
4854 (file-name-nondirectory name))
4855 name))
4856 (directory-files (or (car dirs) ".") full
4857 (wildcard-to-regexp nondir))))))
4858 (setq contents
4859 (nconc
4860 (if (and (car dirs) (not full))
4861 (mapcar (function (lambda (name) (concat (car dirs) name)))
4862 this-dir-contents)
4863 this-dir-contents)
4864 contents))))
4865 (setq dirs (cdr dirs)))
4866 contents)))
5de148a2 4867
b4da00e9
RM
4868(defun list-directory (dirname &optional verbose)
4869 "Display a list of files in or matching DIRNAME, a la `ls'.
4870DIRNAME is globbed by the shell if necessary.
4871Prefix arg (second arg if noninteractive) means supply -l switch to `ls'.
4872Actions controlled by variables `list-directory-brief-switches'
4873and `list-directory-verbose-switches'."
4874 (interactive (let ((pfx current-prefix-arg))
4875 (list (read-file-name (if pfx "List directory (verbose): "
4876 "List directory (brief): ")
4877 nil default-directory nil)
4878 pfx)))
4879 (let ((switches (if verbose list-directory-verbose-switches
84905190
RS
4880 list-directory-brief-switches))
4881 buffer)
b4da00e9
RM
4882 (or dirname (setq dirname default-directory))
4883 (setq dirname (expand-file-name dirname))
4884 (with-output-to-temp-buffer "*Directory*"
84905190 4885 (setq buffer standard-output)
b4da00e9
RM
4886 (buffer-disable-undo standard-output)
4887 (princ "Directory ")
4888 (princ dirname)
4889 (terpri)
c3554e95
RS
4890 (save-excursion
4891 (set-buffer "*Directory*")
4892 (let ((wildcard (not (file-directory-p dirname))))
84905190
RS
4893 (insert-directory dirname switches wildcard (not wildcard)))))
4894 ;; Finishing with-output-to-temp-buffer seems to clobber default-directory.
4895 (with-current-buffer buffer
4896 (setq default-directory
4897 (if (file-directory-p dirname)
4898 (file-name-as-directory dirname)
4899 (file-name-directory dirname))))))
c3554e95 4900
ffc0e1ca
AS
4901(defun shell-quote-wildcard-pattern (pattern)
4902 "Quote characters special to the shell in PATTERN, leave wildcards alone.
4903
4904PATTERN is assumed to represent a file-name wildcard suitable for the
4905underlying filesystem. For Unix and GNU/Linux, the characters from the
d6d61574 4906set [ \\t\\n;<>&|()'\"#$] are quoted with a backslash; for DOS/Windows, all
ffc0e1ca
AS
4907the parts of the pattern which don't include wildcard characters are
4908quoted with double quotes.
4909Existing quote characters in PATTERN are left alone, so you can pass
4910PATTERN that already quotes some of the special characters."
4911 (save-match-data
4912 (cond
c60ee5e7 4913 ((memq system-type '(ms-dos windows-nt cygwin))
ffc0e1ca
AS
4914 ;; DOS/Windows don't allow `"' in file names. So if the
4915 ;; argument has quotes, we can safely assume it is already
4916 ;; quoted by the caller.
4917 (if (or (string-match "[\"]" pattern)
4918 ;; We quote [&()#$'] in case their shell is a port of a
4919 ;; Unixy shell. We quote [,=+] because stock DOS and
4920 ;; Windows shells require that in some cases, such as
4921 ;; passing arguments to batch files that use positional
4922 ;; arguments like %1.
4923 (not (string-match "[ \t;&()#$',=+]" pattern)))
4924 pattern
4925 (let ((result "\"")
4926 (beg 0)
4927 end)
4928 (while (string-match "[*?]+" pattern beg)
4929 (setq end (match-beginning 0)
4930 result (concat result (substring pattern beg end)
4931 "\""
4932 (substring pattern end (match-end 0))
4933 "\"")
4934 beg (match-end 0)))
4935 (concat result (substring pattern beg) "\""))))
4936 (t
4937 (let ((beg 0))
d6d61574 4938 (while (string-match "[ \t\n;<>&|()'\"#$]" pattern beg)
ffc0e1ca
AS
4939 (setq pattern
4940 (concat (substring pattern 0 (match-beginning 0))
4941 "\\"
4942 (substring pattern (match-beginning 0)))
4943 beg (1+ (match-end 0)))))
4944 pattern))))
4945
4946
c3554e95
RS
4947(defvar insert-directory-program "ls"
4948 "Absolute or relative name of the `ls' program used by `insert-directory'.")
4949
f4d04672 4950(defcustom directory-free-space-program "df"
ba83982b 4951 "Program to get the amount of free space on a file system.
f4d04672
RS
4952We assume the output has the format of `df'.
4953The value of this variable must be just a command name or file name;
4954if you want to specify options, use `directory-free-space-args'.
4955
01b26b90
EZ
4956A value of nil disables this feature.
4957
4958If the function `file-system-info' is defined, it is always used in
4959preference to the program given by this variable."
f4d04672
RS
4960 :type '(choice (string :tag "Program") (const :tag "None" nil))
4961 :group 'dired)
4962
525fdbc9
AS
4963(defcustom directory-free-space-args
4964 (if (eq system-type 'darwin) "-k" "-Pk")
ba83982b 4965 "Options to use when running `directory-free-space-program'."
f4d04672
RS
4966 :type 'string
4967 :group 'dired)
4968
01b26b90 4969(defun get-free-disk-space (dir)
26b9ecbc 4970 "Return the amount of free space on directory DIR's file system.
01b26b90 4971The result is a string that gives the number of free 1KB blocks,
26b9ecbc 4972or nil if the system call or the program which retrieve the information
06531fc3 4973fail. It returns also nil when DIR is a remote directory.
01b26b90
EZ
4974
4975This function calls `file-system-info' if it is available, or invokes the
4976program specified by `directory-free-space-program' if that is non-nil."
06531fc3
MA
4977 (when (not (file-remote-p dir))
4978 ;; Try to find the number of free blocks. Non-Posix systems don't
4979 ;; always have df, but might have an equivalent system call.
4980 (if (fboundp 'file-system-info)
4981 (let ((fsinfo (file-system-info dir)))
4982 (if fsinfo
4983 (format "%.0f" (/ (nth 2 fsinfo) 1024))))
4984 (save-match-data
4985 (with-temp-buffer
4986 (when (and directory-free-space-program
4987 (eq 0 (call-process directory-free-space-program
4988 nil t nil
4989 directory-free-space-args
4990 dir)))
4991 ;; Usual format is a header line followed by a line of
4992 ;; numbers.
4993 (goto-char (point-min))
4994 (forward-line 1)
4995 (if (not (eobp))
4996 (progn
4997 ;; Move to the end of the "available blocks" number.
4998 (skip-chars-forward "^ \t")
4999 (forward-word 3)
5000 ;; Copy it into AVAILABLE.
5001 (let ((end (point)))
5002 (forward-word -1)
5003 (buffer-substring (point) end))))))))))
01b26b90 5004
9bc260cf
MA
5005;; The following expression replaces `dired-move-to-filename-regexp'.
5006(defvar directory-listing-before-filename-regexp
5007 (let* ((l "\\([A-Za-z]\\|[^\0-\177]\\)")
5008 (l-or-quote "\\([A-Za-z']\\|[^\0-\177]\\)")
5009 ;; In some locales, month abbreviations are as short as 2 letters,
5010 ;; and they can be followed by ".".
5011 ;; In Breton, a month name can include a quote character.
5012 (month (concat l-or-quote l-or-quote "+\\.?"))
5013 (s " ")
5014 (yyyy "[0-9][0-9][0-9][0-9]")
5015 (dd "[ 0-3][0-9]")
5016 (HH:MM "[ 0-2][0-9][:.][0-5][0-9]")
5017 (seconds "[0-6][0-9]\\([.,][0-9]+\\)?")
5018 (zone "[-+][0-2][0-9][0-5][0-9]")
5019 (iso-mm-dd "[01][0-9]-[0-3][0-9]")
5020 (iso-time (concat HH:MM "\\(:" seconds "\\( ?" zone "\\)?\\)?"))
5021 (iso (concat "\\(\\(" yyyy "-\\)?" iso-mm-dd "[ T]" iso-time
5022 "\\|" yyyy "-" iso-mm-dd "\\)"))
5023 (western (concat "\\(" month s "+" dd "\\|" dd "\\.?" s month "\\)"
5024 s "+"
5025 "\\(" HH:MM "\\|" yyyy "\\)"))
5026 (western-comma (concat month s "+" dd "," s "+" yyyy))
5027 ;; Japanese MS-Windows ls-lisp has one-digit months, and
5028 ;; omits the Kanji characters after month and day-of-month.
5029 ;; On Mac OS X 10.3, the date format in East Asian locales is
5030 ;; day-of-month digits followed by month digits.
5031 (mm "[ 0-1]?[0-9]")
5032 (east-asian
5033 (concat "\\(" mm l "?" s dd l "?" s "+"
5034 "\\|" dd s mm s "+" "\\)"
5035 "\\(" HH:MM "\\|" yyyy l "?" "\\)")))
5036 ;; The "[0-9]" below requires the previous column to end in a digit.
5037 ;; This avoids recognizing `1 may 1997' as a date in the line:
5038 ;; -r--r--r-- 1 may 1997 1168 Oct 19 16:49 README
5039
5040 ;; The "[BkKMGTPEZY]?" below supports "ls -alh" output.
5041 ;; The ".*" below finds the last match if there are multiple matches.
5042 ;; This avoids recognizing `jservice 10 1024' as a date in the line:
5043 ;; drwxr-xr-x 3 jservice 10 1024 Jul 2 1997 esg-host
5044
5045 ;; vc dired listings provide the state or blanks between file
5046 ;; permissions and date. The state is always surrounded by
5047 ;; parantheses:
5048 ;; -rw-r--r-- (modified) 2005-10-22 21:25 files.el
5049 ;; This is not supported yet.
5050 (concat ".*[0-9][BkKMGTPEZY]?" s
5051 "\\(" western "\\|" western-comma "\\|" east-asian "\\|" iso "\\)"
5052 s "+"))
5053 "Regular expression to match up to the file name in a directory listing.
5054The default value is designed to recognize dates and times
5055regardless of the language.")
01b26b90 5056
a1b0c2a7
RS
5057(defvar insert-directory-ls-version 'unknown)
5058
c3554e95
RS
5059;; insert-directory
5060;; - must insert _exactly_one_line_ describing FILE if WILDCARD and
5061;; FULL-DIRECTORY-P is nil.
5062;; The single line of output must display FILE's name as it was
5063;; given, namely, an absolute path name.
5064;; - must insert exactly one line for each file if WILDCARD or
5065;; FULL-DIRECTORY-P is t, plus one optional "total" line
5066;; before the file lines, plus optional text after the file lines.
5067;; Lines are delimited by "\n", so filenames containing "\n" are not
5068;; allowed.
5069;; File lines should display the basename.
5070;; - must be consistent with
5071;; - functions dired-move-to-filename, (these two define what a file line is)
5072;; dired-move-to-end-of-filename,
5073;; dired-between-files, (shortcut for (not (dired-move-to-filename)))
5074;; dired-insert-headerline
5075;; dired-after-subdir-garbage (defines what a "total" line is)
5076;; - variable dired-subdir-regexp
1fc85dae
KG
5077;; - may be passed "--dired" as the first argument in SWITCHES.
5078;; Filename handlers might have to remove this switch if their
5079;; "ls" command does not support it.
c3554e95 5080(defun insert-directory (file switches &optional wildcard full-directory-p)
a18b7c81 5081 "Insert directory listing for FILE, formatted according to SWITCHES.
c3554e95 5082Leaves point after the inserted text.
8f8607be
LT
5083SWITCHES may be a string of options, or a list of strings
5084representing individual options.
c3554e95
RS
5085Optional third arg WILDCARD means treat FILE as shell wildcard.
5086Optional fourth arg FULL-DIRECTORY-P means file is a directory and
5087switches do not contain `d', so that a full listing is expected.
5088
5089This works by running a directory listing program
406e12d9 5090whose name is in the variable `insert-directory-program'.
8f8607be
LT
5091If WILDCARD, it also runs the shell specified by `shell-file-name'.
5092
60ce7e3e 5093When SWITCHES contains the long `--dired' option, this function
8f8607be
LT
5094treats it specially, for the sake of dired. However, the
5095normally equivalent short `-D' option is just passed on to
5096`insert-directory-program', as any other option."
c870ab8e 5097 ;; We need the directory in order to find the right handler.
d2473540
AS
5098 (let ((handler (find-file-name-handler (expand-file-name file)
5099 'insert-directory)))
ebad92dc 5100 (if handler
c3554e95
RS
5101 (funcall handler 'insert-directory file switches
5102 wildcard full-directory-p)
b4da00e9 5103 (if (eq system-type 'vax-vms)
c3554e95 5104 (vms-read-directory file switches (current-buffer))
818286f4 5105 (let (result (beg (point)))
ebad92dc
RS
5106
5107 ;; Read the actual directory using `insert-directory-program'.
5108 ;; RESULT gets the status code.
99f01c91
KH
5109 (let* (;; We at first read by no-conversion, then after
5110 ;; putting text property `dired-filename, decode one
5111 ;; bunch by one to preserve that property.
5112 (coding-system-for-read 'no-conversion)
5113 ;; This is to control encoding the arguments in call-process.
c60ee5e7 5114 (coding-system-for-write
82e22b57
KH
5115 (and enable-multibyte-characters
5116 (or file-name-coding-system
99f01c91 5117 default-file-name-coding-system))))
ebad92dc
RS
5118 (setq result
5119 (if wildcard
5120 ;; Run ls in the directory part of the file pattern
5121 ;; using the last component as argument.
5122 (let ((default-directory
5123 (if (file-name-absolute-p file)
5124 (file-name-directory file)
5125 (file-name-directory (expand-file-name file))))
5126 (pattern (file-name-nondirectory file)))
5127 (call-process
5128 shell-file-name nil t nil
5129 "-c"
5130 (concat (if (memq system-type '(ms-dos windows-nt))
5131 ""
5132 "\\") ; Disregard Unix shell aliases!
5133 insert-directory-program
5134 " -d "
5135 (if (stringp switches)
5136 switches
5137 (mapconcat 'identity switches " "))
5138 " -- "
5139 ;; Quote some characters that have
5140 ;; special meanings in shells; but
5141 ;; don't quote the wildcards--we want
5142 ;; them to be special. We also
5143 ;; currently don't quote the quoting
5144 ;; characters in case people want to
5145 ;; use them explicitly to quote
5146 ;; wildcard characters.
5147 (shell-quote-wildcard-pattern pattern))))
5148 ;; SunOS 4.1.3, SVr4 and others need the "." to list the
5149 ;; directory if FILE is a symbolic link.
5150 (apply 'call-process
5151 insert-directory-program nil t nil
5152 (append
5153 (if (listp switches) switches
5154 (unless (equal switches "")
5155 ;; Split the switches at any spaces so we can
5156 ;; pass separate options as separate args.
5157 (split-string switches)))
5158 ;; Avoid lossage if FILE starts with `-'.
5159 '("--")
5160 (progn
5161 (if (string-match "\\`~" file)
5162 (setq file (expand-file-name file)))
5163 (list
5164 (if full-directory-p
5165 (concat (file-name-as-directory file) ".")
5166 file))))))))
5167
a1b0c2a7
RS
5168 ;; If we got "//DIRED//" in the output, it means we got a real
5169 ;; directory listing, even if `ls' returned nonzero.
5170 ;; So ignore any errors.
5171 (when (if (stringp switches)
5172 (string-match "--dired\\>" switches)
5173 (member "--dired" switches))
5174 (save-excursion
5175 (forward-line -2)
5176 (when (looking-at "//SUBDIRED//")
5177 (forward-line -1))
5178 (if (looking-at "//DIRED//")
5179 (setq result 0))))
5180
5181 (when (and (not (eq 0 result))
5182 (eq insert-directory-ls-version 'unknown))
5183 ;; The first time ls returns an error,
5184 ;; find the version numbers of ls,
5185 ;; and set insert-directory-ls-version
5186 ;; to > if it is more than 5.2.1, < if it is less, nil if it
5187 ;; is equal or if the info cannot be obtained.
5188 ;; (That can mean it isn't GNU ls.)
5189 (let ((version-out
5190 (with-temp-buffer
5191 (call-process "ls" nil t nil "--version")
5192 (buffer-string))))
5193 (if (string-match "ls (.*utils) \\([0-9.]*\\)$" version-out)
5194 (let* ((version (match-string 1 version-out))
5195 (split (split-string version "[.]"))
027a4b6b 5196 (numbers (mapcar 'string-to-number split))
a1b0c2a7
RS
5197 (min '(5 2 1))
5198 comparison)
5199 (while (and (not comparison) (or numbers min))
5200 (cond ((null min)
5201 (setq comparison '>))
5202 ((null numbers)
5203 (setq comparison '<))
5204 ((> (car numbers) (car min))
5205 (setq comparison '>))
5206 ((< (car numbers) (car min))
5207 (setq comparison '<))
5208 (t
5209 (setq numbers (cdr numbers)
5210 min (cdr min)))))
5211 (setq insert-directory-ls-version (or comparison '=)))
5212 (setq insert-directory-ls-version nil))))
5213
5214 ;; For GNU ls versions 5.2.2 and up, ignore minor errors.
5215 (when (and (eq 1 result) (eq insert-directory-ls-version '>))
5216 (setq result 0))
5217
ebad92dc 5218 ;; If `insert-directory-program' failed, signal an error.
15502042 5219 (unless (eq 0 result)
f2440e42
RS
5220 ;; Delete the error message it may have output.
5221 (delete-region beg (point))
15502042
EZ
5222 ;; On non-Posix systems, we cannot open a directory, so
5223 ;; don't even try, because that will always result in
5224 ;; the ubiquitous "Access denied". Instead, show the
5225 ;; command line so the user can try to guess what went wrong.
5226 (if (and (file-directory-p file)
5227 (memq system-type '(ms-dos windows-nt)))
5228 (error
5229 "Reading directory: \"%s %s -- %s\" exited with status %s"
5230 insert-directory-program
5231 (if (listp switches) (concat switches) switches)
5232 file result)
5233 ;; Unix. Access the file to get a suitable error.
5234 (access-file file "Reading directory")
5235 (error "Listing directory failed but `access-file' worked")))
ebad92dc 5236
8f8607be
LT
5237 (when (if (stringp switches)
5238 (string-match "--dired\\>" switches)
5239 (member "--dired" switches))
9bb99df6
LT
5240 ;; The following overshoots by one line for an empty
5241 ;; directory listed with "--dired", but without "-a"
5242 ;; switch, where the ls output contains a
5243 ;; "//DIRED-OPTIONS//" line, but no "//DIRED//" line.
5244 ;; We take care of that case later.
ff7affeb 5245 (forward-line -2)
9423860f
AS
5246 (when (looking-at "//SUBDIRED//")
5247 (delete-region (point) (progn (forward-line 1) (point)))
5248 (forward-line -1))
9bb99df6
LT
5249 (if (looking-at "//DIRED//")
5250 (let ((end (line-end-position))
5251 (linebeg (point))
5252 error-lines)
5253 ;; Find all the lines that are error messages,
5254 ;; and record the bounds of each one.
5255 (goto-char beg)
5256 (while (< (point) linebeg)
5257 (or (eql (following-char) ?\s)
5258 (push (list (point) (line-end-position)) error-lines))
5259 (forward-line 1))
5260 (setq error-lines (nreverse error-lines))
5261 ;; Now read the numeric positions of file names.
5262 (goto-char linebeg)
5263 (forward-word 1)
5264 (forward-char 3)
5265 (while (< (point) end)
5266 (let ((start (insert-directory-adj-pos
5267 (+ beg (read (current-buffer)))
5268 error-lines))
5269 (end (insert-directory-adj-pos
a1b0c2a7 5270 (+ beg (read (current-buffer)))
9bb99df6 5271 error-lines)))
26b9ecbc 5272 (if (memq (char-after end) '(?\n ?\s))
9bb99df6
LT
5273 ;; End is followed by \n or by " -> ".
5274 (put-text-property start end 'dired-filename t)
5275 ;; It seems that we can't trust ls's output as to
5276 ;; byte positions of filenames.
5277 (put-text-property beg (point) 'dired-filename nil)
5278 (end-of-line))))
5279 (goto-char end)
5280 (beginning-of-line)
5281 (delete-region (point) (progn (forward-line 1) (point))))
5282 ;; Take care of the case where the ls output contains a
5283 ;; "//DIRED-OPTIONS//"-line, but no "//DIRED//"-line
5284 ;; and we went one line too far back (see above).
5285 (forward-line 1))
5286 (if (looking-at "//DIRED-OPTIONS//")
5287 (delete-region (point) (progn (forward-line 1) (point)))))
ff7affeb 5288
99f01c91 5289 ;; Now decode what read if necessary.
b6647390
KH
5290 (let ((coding (or coding-system-for-read
5291 file-name-coding-system
5292 default-file-name-coding-system
5293 'undecided))
0bded065 5294 coding-no-eol
99f01c91 5295 val pos)
b6647390
KH
5296 (when (and enable-multibyte-characters
5297 (not (memq (coding-system-base coding)
5298 '(raw-text no-conversion))))
5299 ;; If no coding system is specified or detection is
5300 ;; requested, detect the coding.
5301 (if (eq (coding-system-base coding) 'undecided)
5302 (setq coding (detect-coding-region beg (point) t)))
5303 (if (not (eq (coding-system-base coding) 'undecided))
5304 (save-restriction
0bded065
AS
5305 (setq coding-no-eol
5306 (coding-system-change-eol-conversion coding 'unix))
b6647390
KH
5307 (narrow-to-region beg (point))
5308 (goto-char (point-min))
5309 (while (not (eobp))
5310 (setq pos (point)
5311 val (get-text-property (point) 'dired-filename))
5312 (goto-char (next-single-property-change
5313 (point) 'dired-filename nil (point-max)))
0bded065
AS
5314 ;; Force no eol conversion on a file name, so
5315 ;; that CR is preserved.
5316 (decode-coding-region pos (point)
5317 (if val coding-no-eol coding))
b6647390
KH
5318 (if val
5319 (put-text-property pos (point)
5320 'dired-filename t)))))))
99f01c91 5321
75bb5ca4
AS
5322 (if full-directory-p
5323 ;; Try to insert the amount of free space.
5324 (save-excursion
5325 (goto-char beg)
5326 ;; First find the line to put it on.
5327 (when (re-search-forward "^ *\\(total\\)" nil t)
5328 (let ((available (get-free-disk-space ".")))
5329 (when available
5330 ;; Replace "total" with "used", to avoid confusion.
5331 (replace-match "total used in directory" nil nil nil 1)
5332 (end-of-line)
5333 (insert " available " available)))))))))))
34342a07 5334
a1b0c2a7 5335(defun insert-directory-adj-pos (pos error-lines)
fead94d6 5336 "Convert `ls --dired' file name position value POS to a buffer position.
a1b0c2a7
RS
5337File name position values returned in ls --dired output
5338count only stdout; they don't count the error messages sent to stderr.
5339So this function converts to them to real buffer positions.
5340ERROR-LINES is a list of buffer positions of error message lines,
5341of the form (START END)."
5342 (while (and error-lines (< (caar error-lines) pos))
5343 (setq pos (+ pos (- (nth 1 (car error-lines)) (nth 0 (car error-lines)))))
5344 (pop error-lines))
5345 pos)
5346
bc22fd18
EZ
5347(defun insert-directory-safely (file switches
5348 &optional wildcard full-directory-p)
5349 "Insert directory listing for FILE, formatted according to SWITCHES.
5350
5351Like `insert-directory', but if FILE does not exist, it inserts a
5352message to that effect instead of signaling an error."
5353 (if (file-exists-p file)
5354 (insert-directory file switches wildcard full-directory-p)
5355 ;; Simulate the message printed by `ls'.
5356 (insert (format "%s: No such file or directory\n" file))))
5357
88902b35 5358(defvar kill-emacs-query-functions nil
65d5c6de 5359 "Functions to call with no arguments to query about killing Emacs.
78c793d1 5360If any of these functions returns nil, killing Emacs is cancelled.
6daab4ed
JB
5361`save-buffers-kill-emacs' calls these functions, but `kill-emacs',
5362the low level primitive, does not. See also `kill-emacs-hook'.")
88902b35 5363
11f15305 5364(defcustom confirm-kill-emacs nil
9c2ba08f
EZ
5365 "How to ask for confirmation when leaving Emacs.
5366If nil, the default, don't ask at all. If the value is non-nil, it should
5367be a predicate function such as `yes-or-no-p'."
11f15305
GM
5368 :type '(choice (const :tag "Ask with yes-or-no-p" yes-or-no-p)
5369 (const :tag "Ask with y-or-n-p" y-or-n-p)
5370 (const :tag "Don't confirm" nil))
bdd9ab6e 5371 :group 'convenience
11f15305
GM
5372 :version "21.1")
5373
b4da00e9
RM
5374(defun save-buffers-kill-emacs (&optional arg)
5375 "Offer to save each buffer, then kill this Emacs process.
5376With prefix arg, silently save all file-visiting buffers, then kill."
5377 (interactive "P")
5378 (save-some-buffers arg t)
5379 (and (or (not (memq t (mapcar (function
5380 (lambda (buf) (and (buffer-file-name buf)
5381 (buffer-modified-p buf))))
5382 (buffer-list))))
5383 (yes-or-no-p "Modified buffers exist; exit anyway? "))
5384 (or (not (fboundp 'process-list))
5385 ;; process-list is not defined on VMS.
5386 (let ((processes (process-list))
5387 active)
5388 (while processes
48a4a1fb
KS
5389 (and (memq (process-status (car processes)) '(run stop open listen))
5390 (process-query-on-exit-flag (car processes))
b4da00e9
RM
5391 (setq active t))
5392 (setq processes (cdr processes)))
5393 (or (not active)
48a4a1fb 5394 (list-processes t)
b4da00e9 5395 (yes-or-no-p "Active processes exist; kill them and exit anyway? "))))
88902b35 5396 ;; Query the user for other things, perhaps.
fb15c113 5397 (run-hook-with-args-until-failure 'kill-emacs-query-functions)
11f15305
GM
5398 (or (null confirm-kill-emacs)
5399 (funcall confirm-kill-emacs "Really exit Emacs? "))
b4da00e9 5400 (kill-emacs)))
59e085e0 5401
6ed8eeff 5402(defun save-buffers-kill-terminal (&optional arg)
59e085e0
KL
5403 "Offer to save each buffer, then kill the current connection.
5404If the current frame has no client, kill Emacs itself.
5405
5406With prefix arg, silently save all file-visiting buffers, then kill.
5407
5408If emacsclient was started with a list of filenames to edit, then
5409only these files will be asked to be saved."
5410 (interactive "P")
5411 (let ((proc (frame-parameter (selected-frame) 'client))
5412 (frame (selected-frame)))
5413 (if (null proc)
5414 (save-buffers-kill-emacs)
6ed8eeff 5415 (server-save-buffers-kill-terminal proc arg))))
59e085e0 5416
b4da00e9 5417\f
ffc0e1ca 5418;; We use /: as a prefix to "quote" a file name
47afc068
RS
5419;; so that magic file name handlers will not apply to it.
5420
5421(setq file-name-handler-alist
5422 (cons '("\\`/:" . file-name-non-special)
5423 file-name-handler-alist))
5424
5425;; We depend on being the last handler on the list,
5426;; so that anything else which does need handling
5427;; has been handled already.
5428;; So it is safe for us to inhibit *all* magic file name handlers.
5429
5430(defun file-name-non-special (operation &rest arguments)
5431 (let ((file-name-handler-alist nil)
5cb1f728
KH
5432 (default-directory
5433 (if (eq operation 'insert-directory)
5434 (directory-file-name
ffc0e1ca 5435 (expand-file-name
5cb1f728
KH
5436 (unhandled-file-name-directory default-directory)))
5437 default-directory))
47afc068
RS
5438 ;; Get a list of the indices of the args which are file names.
5439 (file-arg-indices
5440 (cdr (or (assq operation
ae3b2983 5441 ;; The first six are special because they
47afc068
RS
5442 ;; return a file name. We want to include the /:
5443 ;; in the return value.
5444 ;; So just avoid stripping it in the first place.
5445 '((expand-file-name . nil)
5446 (file-name-directory . nil)
5447 (file-name-as-directory . nil)
5448 (directory-file-name . nil)
c736f678 5449 (file-name-sans-versions . nil)
ae3b2983 5450 (find-backup-file-name . nil)
c736f678 5451 ;; `identity' means just return the first arg
6750c852
RS
5452 ;; not stripped of its quoting.
5453 (substitute-in-file-name identity)
ae3b2983
MA
5454 ;; `add' means add "/:" to the result.
5455 (file-truename add 0)
5456 ;; `quote' means add "/:" to buffer-file-name.
5457 (insert-file-contents quote 0)
5458 ;; `unquote-then-quote' means set buffer-file-name
5459 ;; temporarily to unquoted filename.
5460 (verify-visited-file-modtime unquote-then-quote)
5461 ;; List the arguments which are filenames.
c37adaa5
SM
5462 (file-name-completion 1)
5463 (file-name-all-completions 1)
ae3b2983 5464 (write-region 2 5)
47afc068
RS
5465 (rename-file 0 1)
5466 (copy-file 0 1)
5467 (make-symbolic-link 0 1)
5468 (add-name-to-file 0 1)))
5469 ;; For all other operations, treat the first argument only
5470 ;; as the file name.
5471 '(nil 0))))
6750c852 5472 method
47afc068
RS
5473 ;; Copy ARGUMENTS so we can replace elements in it.
5474 (arguments (copy-sequence arguments)))
6750c852
RS
5475 (if (symbolp (car file-arg-indices))
5476 (setq method (pop file-arg-indices)))
5477 ;; Strip off the /: from the file names that have it.
47afc068 5478 (save-match-data
18b9dced 5479 (while (consp file-arg-indices)
fe4d9852
KH
5480 (let ((pair (nthcdr (car file-arg-indices) arguments)))
5481 (and (car pair)
5482 (string-match "\\`/:" (car pair))
5483 (setcar pair
5484 (if (= (length (car pair)) 2)
5485 "/"
5486 (substring (car pair) 2)))))
47afc068 5487 (setq file-arg-indices (cdr file-arg-indices))))
6750c852
RS
5488 (cond ((eq method 'identity)
5489 (car arguments))
ae3b2983 5490 ((eq method 'add)
6750c852 5491 (concat "/:" (apply operation arguments)))
ae3b2983 5492 ((eq method 'quote)
e8f30180
RS
5493 (unwind-protect
5494 (apply operation arguments)
ae3b2983
MA
5495 (setq buffer-file-name (concat "/:" buffer-file-name))))
5496 ((eq method 'unquote-then-quote)
5497 (let (res)
5498 (setq buffer-file-name (substring buffer-file-name 2))
5499 (setq res (apply operation arguments))
5500 (setq buffer-file-name (concat "/:" buffer-file-name))
5501 res))
6750c852
RS
5502 (t
5503 (apply operation arguments)))))
47afc068 5504\f
90d10f16
MC
5505;; Symbolic modes and read-file-modes.
5506
5507(defun file-modes-char-to-who (char)
5508 "Convert CHAR to a who-mask from a symbolic mode notation.
5509CHAR is in [ugoa] and represents the users on which rights are applied."
5510 (cond ((= char ?u) #o4700)
5511 ((= char ?g) #o2070)
5512 ((= char ?o) #o1007)
5513 ((= char ?a) #o7777)
5514 (t (error "%c: bad `who' character" char))))
5515
5516(defun file-modes-char-to-right (char &optional from)
5517 "Convert CHAR to a right-mask from a symbolic mode notation.
5518CHAR is in [rwxXstugo] and represents a right.
5519If CHAR is in [Xugo], the value is extracted from FROM (or 0 if nil)."
5520 (or from (setq from 0))
5521 (cond ((= char ?r) #o0444)
5522 ((= char ?w) #o0222)
5523 ((= char ?x) #o0111)
5524 ((= char ?s) #o1000)
5525 ((= char ?t) #o6000)
5526 ;; Rights relative to the previous file modes.
5527 ((= char ?X) (if (= (logand from #o111) 0) 0 #o0111))
5528 ((= char ?u) (let ((uright (logand #o4700 from)))
5529 (+ uright (/ uright #o10) (/ uright #o100))))
5530 ((= char ?g) (let ((gright (logand #o2070 from)))
5531 (+ gright (/ gright #o10) (* gright #o10))))
5532 ((= char ?o) (let ((oright (logand #o1007 from)))
5533 (+ oright (* oright #o10) (* oright #o100))))
5534 (t (error "%c: bad right character" char))))
5535
5536(defun file-modes-rights-to-number (rights who-mask &optional from)
5537 "Convert a right string to a right-mask from a symbolic modes notation.
5538RIGHTS is the right string, it should match \"([+=-][rwxXstugo]+)+\".
5539WHO-MASK is the mask number of the users on which the rights are to be applied.
5540FROM (or 0 if nil) is the orginal modes of the file to be chmod'ed."
5541 (let* ((num-rights (or from 0))
5542 (list-rights (string-to-list rights))
5543 (op (pop list-rights)))
5544 (while (memq op '(?+ ?- ?=))
5545 (let ((num-right 0)
5546 char-right)
5547 (while (memq (setq char-right (pop list-rights))
5548 '(?r ?w ?x ?X ?s ?t ?u ?g ?o))
5549 (setq num-right
5550 (logior num-right
5551 (file-modes-char-to-right char-right num-rights))))
5552 (setq num-right (logand who-mask num-right)
5553 num-rights
5554 (cond ((= op ?+) (logior num-rights num-right))
5555 ((= op ?-) (logand num-rights (lognot num-right)))
5556 (t (logior (logand num-rights (lognot who-mask)) num-right)))
5557 op char-right)))
5558 num-rights))
5559
5560(defun file-modes-symbolic-to-number (modes &optional from)
5561 "Convert symbolic file modes to numeric file modes.
5562MODES is the string to convert, it should match
5563\"[ugoa]*([+-=][rwxXstugo]+)+,...\".
5564See (info \"(coreutils)File permissions\") for more information on this
5565notation.
5566FROM (or 0 if nil) is the orginal modes of the file to be chmod'ed."
5567 (save-match-data
5568 (let ((case-fold-search nil)
5569 (num-modes (or from 0)))
5570 (while (/= (string-to-char modes) 0)
5571 (if (string-match "^\\([ugoa]*\\)\\([+=-][rwxXstugo]+\\)+\\(,\\|\\)" modes)
5572 (let ((num-who (apply 'logior 0
5573 (mapcar 'file-modes-char-to-who
5574 (match-string 1 modes)))))
5575 (when (= num-who 0)
5576 (setq num-who (default-file-modes)))
5577 (setq num-modes
5578 (file-modes-rights-to-number (substring modes (match-end 1))
5579 num-who num-modes)
5580 modes (substring modes (match-end 3))))
5581 (error "Parse error in modes near `%s'" (substring modes 0))))
5582 num-modes)))
5583
5584(defun read-file-modes (&optional prompt orig-file)
5585 "Read file modes in octal or symbolic notation.
5586PROMPT is used as the prompt, default to `File modes (octal or symbolic): '.
5587ORIG-FILE is the original file of which modes will be change."
5588 (let* ((modes (or (if orig-file (file-modes orig-file) 0)
5589 (error "File not found")))
5590 (value (read-string (or prompt "File modes (octal or symbolic): "))))
5591 (save-match-data
5592 (if (string-match "^[0-7]+" value)
5593 (string-to-number value 8)
5594 (file-modes-symbolic-to-number value modes)))))
5595
5596\f
b4da00e9 5597(define-key ctl-x-map "\C-f" 'find-file)
b4da00e9
RM
5598(define-key ctl-x-map "\C-r" 'find-file-read-only)
5599(define-key ctl-x-map "\C-v" 'find-alternate-file)
5600(define-key ctl-x-map "\C-s" 'save-buffer)
5601(define-key ctl-x-map "s" 'save-some-buffers)
5602(define-key ctl-x-map "\C-w" 'write-file)
5603(define-key ctl-x-map "i" 'insert-file)
5604(define-key esc-map "~" 'not-modified)
5605(define-key ctl-x-map "\C-d" 'list-directory)
6ed8eeff 5606(define-key ctl-x-map "\C-c" 'save-buffers-kill-terminal)
d758359d 5607(define-key ctl-x-map "\C-q" 'toggle-read-only)
b4da00e9
RM
5608
5609(define-key ctl-x-4-map "f" 'find-file-other-window)
5610(define-key ctl-x-4-map "r" 'find-file-read-only-other-window)
5611(define-key ctl-x-4-map "\C-f" 'find-file-other-window)
5612(define-key ctl-x-4-map "b" 'switch-to-buffer-other-window)
924f0a24 5613(define-key ctl-x-4-map "\C-o" 'display-buffer)
5bbbceb1 5614
f98955ea
JB
5615(define-key ctl-x-5-map "b" 'switch-to-buffer-other-frame)
5616(define-key ctl-x-5-map "f" 'find-file-other-frame)
5617(define-key ctl-x-5-map "\C-f" 'find-file-other-frame)
5618(define-key ctl-x-5-map "r" 'find-file-read-only-other-frame)
3095ccf5 5619(define-key ctl-x-5-map "\C-o" 'display-buffer-other-frame)
c0274f38 5620
c3f6aa20 5621;; arch-tag: bc68d3ea-19ca-468b-aac6-3a4a7766101f
c0274f38 5622;;; files.el ends here