@node Saving Buffers
@section Saving Buffers
+@cindex saving buffers
When you edit a file in Emacs, you are actually working on a buffer
that is visiting that file---that is, the contents of the file are
@end deffn
Saving a buffer runs several hooks. It also performs format
-conversion (@pxref{Format Conversion}), and may save text properties in
-``annotations'' (@pxref{Saving Properties}).
+conversion (@pxref{Format Conversion}).
@defvar write-file-functions
The value of this variable is a list of functions to be called before
@node Reading from Files
@comment node-name, next, previous, up
@section Reading from Files
+@cindex reading from files
You can copy a file from the disk and insert it into a buffer
using the @code{insert-file-contents} function. Don't use the user-level
The function @code{insert-file-contents} checks the file contents
against the defined file formats, and converts the file contents if
-appropriate. @xref{Format Conversion}. It also calls the functions in
-the list @code{after-insert-file-functions}; see @ref{Saving
-Properties}. Normally, one of the functions in the
+appropriate and also calls the functions in
+the list @code{after-insert-file-functions}. @xref{Format Conversion}.
+Normally, one of the functions in the
@code{after-insert-file-functions} list determines the coding system
(@pxref{Coding Systems}) used for decoding the file's contents,
including end-of-line conversion.
@node Writing to Files
@comment node-name, next, previous, up
@section Writing to Files
+@cindex writing to files
You can write the contents of a buffer, or part of a buffer, directly
to a file on disk using the @code{append-to-file} and
@var{filename} and @var{visit} for that purpose.
The function @code{write-region} converts the data which it writes to
-the appropriate file formats specified by @code{buffer-file-format}.
-@xref{Format Conversion}. It also calls the functions in the list
-@code{write-region-annotate-functions}; see @ref{Saving Properties}.
+the appropriate file formats specified by @code{buffer-file-format}
+and also calls the functions in the list
+@code{write-region-annotate-functions}.
+@xref{Format Conversion}.
Normally, @code{write-region} displays the message @samp{Wrote
@var{filename}} in the echo area. If @var{visit} is neither @code{t}
@node File Locks
@section File Locks
@cindex file locks
+@cindex lock file
When two users edit the same file at the same time, they are likely
to interfere with each other. Emacs tries to prevent this situation
@node Information about Files
@section Information about Files
+@cindex file, information about
The functions described in this section all operate on strings that
designate file names. With a few exceptions, all the functions have
(@pxref{Changing Files}).
@item
-The file's @acronym{UID} as a string or an integer. If a string
-value cannot be looked up, the integer value is returned.
+The file's @acronym{UID}, normally as a string. However, if it does
+not correspond to a named user, the value is an integer or a floating
+point number.
@item
-The file's @acronym{GID} likewise.
+The file's @acronym{GID}, likewise.
@item
The time of last access, as a list of two integers.
@item
The time of last modification as a list of two integers (as above).
+@cindex modification time of file
@item
The time of last status change as a list of two integers (as above).
@node Locating Files
@subsection How to Locate Files in Standard Places
-@cindex locate files
-@cindex find files
+@cindex locate file in path
+@cindex find file in path
This section explains how to search for a file in a list of
-directories. One example is when you need to look for a program's
-executable file, e.g., to find out whether a given program is
-installed on the user's system. Another example is the search for
+directories (a @dfn{path}). One example is when you need to look for
+a program's executable file, e.g., to find out whether a given program
+is installed on the user's system. Another example is the search for
Lisp libraries (@pxref{Library Search}). Such searches generally need
to try various possible file name extensions, in addition to various
possible directories. Emacs provides a function for such a
a list of one or more of these symbols.
@end defun
-@cindex find executable program
@defun executable-find program
This function searches for the executable file of the named
@var{program} and returns the full absolute name of the executable,
@node Changing Files
@section Changing File Names and Attributes
-@cindex renaming files
+@c @cindex renaming files Duplicates rename-file
@cindex copying files
@cindex deleting files
@cindex linking files
@end group
@end example
+In some cases, a leading @samp{..} component can remain in the output:
+
+@example
+@group
+(expand-file-name "../home" "/")
+ @result{} "/../home"
+@end group
+@end example
+
+@noindent
+This is for the sake of filesystems that have the concept of a
+``superroot'' above the root directory @file{/}. On other filesystems,
+@file{/../} is interpreted exactly the same as @file{/}.
+
Note that @code{expand-file-name} does @emph{not} expand environment
variables; only @code{substitute-in-file-name} does that.
@node Create/Delete Dirs
@section Creating and Deleting Directories
+@cindex creating and deleting directories
@c Emacs 19 features
Most Emacs Lisp file-manipulation functions get errors when used on
is chosen so that handlers for jobs such as uncompression are handled
first, before handlers for jobs such as remote file access.
-Here are the operations that a magic file name handler gets to handle:
+ Here are the operations that a magic file name handler gets to handle:
@ifnottex
@noindent
@code{directory-file-name},
@code{directory-files},
@code{directory-files-and-attributes},
-@code{dired-call-process},
@code{dired-compress-file}, @code{dired-uncache},@*
@code{expand-file-name},
@code{file-accessible-directory-p},
@code{make-directory},
@code{make-directory-internal},
@code{make-symbolic-link},@*
+@code{process-file},
@code{rename-file}, @code{set-file-modes}, @code{set-file-times},
@code{set-visited-file-modtime}, @code{shell-command},
+@code{start-file-process},
@code{substitute-in-file-name},@*
@code{unhandled-file-name-directory},
@code{vc-registered},
@code{directory-file-name},
@code{directory-files},
@code{directory-files-and-at@discretionary{}{}{}tributes},
-@code{dired-call-process},
@code{dired-compress-file}, @code{dired-uncache},
@code{expand-file-name},
@code{file-accessible-direc@discretionary{}{}{}tory-p},
@code{load}, @code{make-direc@discretionary{}{}{}tory},
@code{make-direc@discretionary{}{}{}tory-internal},
@code{make-symbolic-link},
+@code{process-file},
@code{rename-file}, @code{set-file-modes},
@code{set-visited-file-modtime}, @code{shell-command},
+@code{start-file-process},
@code{substitute-in-file-name},
@code{unhandled-file-name-directory},
@code{vc-regis@discretionary{}{}{}tered},
functions, so that they won't be loaded except when they have real
work to do.
+ Simply deferring all operations to the usual primitives does not
+work. For instance, if the file name handler applies to
+@code{file-exists-p}, then it must handle @code{load} itself, because
+the usual @code{load} code won't work properly in that case. However,
+if the handler uses the @code{operations} property to say it doesn't
+handle @code{file-exists-p}, then it need not handle @code{load}
+nontrivially.
+
@defvar inhibit-file-name-handlers
This variable holds a list of handlers whose use is presently inhibited
for a certain operation.
of the local copy file.
@end defun
-@defun file-remote-p filename
+@defun file-remote-p filename &optional identification connected
This function tests whether @var{filename} is a remote file. If
@var{filename} is local (not remote), the return value is @code{nil}.
If @var{filename} is indeed remote, the return value is a string that
This identifier string can include a host name and a user name, as
well as characters designating the method used to access the remote
system. For example, the remote identifier string for the filename
-@code{/ssh:user@@host:/some/file} is @code{/ssh:user@@host:}.
+@code{/sudo::/some/file} is @code{/sudo:root@@localhost:}.
If @code{file-remote-p} returns the same identifier for two different
filenames, that means they are stored on the same file system and can
example, that it is possible to start a remote process accessing both
files at the same time. Implementors of file handlers need to ensure
this principle is valid.
+
+@var{identification} specifies which part of the identifier shall be
+returned as string. @var{identification} can be the symbol
+@code{method}, @code{user} or @code{host}; any other value is handled
+like @code{nil} and means to return the complete identifier string.
+In the example above, the remote @code{user} identifier string would
+be @code{root}.
+
+If @var{connected} is non-@code{nil}, this function returns @code{nil}
+even if @var{filename} is remote, if Emacs has no network connection
+to its host. This is useful when you want to avoid the delay of
+making connections when they don't exist.
@end defun
@defun unhandled-file-name-directory filename
@cindex file format conversion
@cindex encoding file formats
@cindex decoding file formats
- The variable @code{format-alist} defines a list of @dfn{file formats},
-which describe textual representations used in files for the data (text,
-text-properties, and possibly other information) in an Emacs buffer.
-Emacs performs format conversion if appropriate when reading and writing
-files.
+@cindex text properties in files
+@cindex saving text properties
+ Emacs performs several steps to convert the data in a buffer (text,
+text properties, and possibly other information) to and from a
+representation suitable for storing into a file. This section describes
+the fundamental functions that perform this @dfn{format conversion},
+namely @code{insert-file-contents} for reading a file into a buffer,
+and @code{write-region} for writing a buffer into a file.
+
+@menu
+* Overview: Format Conversion Overview. @code{insert-file-contents} and @code{write-region}
+* Round-Trip: Format Conversion Round-Trip. Using @code{format-alist}.
+* Piecemeal: Format Conversion Piecemeal. Specifying non-paired conversion.
+@end menu
+
+@node Format Conversion Overview
+@subsection Overview
+@noindent
+The function @code{insert-file-contents}:
+
+@itemize
+@item initially, inserts bytes from the file into the buffer;
+@item decodes bytes to characters as appropriate;
+@item processes formats as defined by entries in @code{format-alist}; and
+@item calls functions in @code{after-insert-file-functions}.
+@end itemize
+
+@noindent
+The function @code{write-region}:
+
+@itemize
+@item initially, calls functions in @code{write-region-annotate-functions};
+@item processes formats as defined by entries in @code{format-alist};
+@item encodes characters to bytes as appropriate; and
+@item modifies the file with the bytes.
+@end itemize
+
+ This shows the symmetry of the lowest-level operations; reading and
+writing handle things in opposite order. The rest of this section
+describes the two facilities surrounding the three variables named
+above, as well as some related functions. @ref{Coding Systems}, for
+details on character encoding and decoding.
+
+@node Format Conversion Round-Trip
+@subsection Round-Trip Specification
+
+ The most general of the two facilities is controlled by the variable
+@code{format-alist}, a list of @dfn{file format} specifications, which
+describe textual representations used in files for the data in an Emacs
+buffer. The descriptions for reading and writing are paired, which is
+why we call this ``round-trip'' specification
+(@pxref{Format Conversion Piecemeal}, for non-paired specification).
@defvar format-alist
This list contains one format definition for each defined file format.
-@end defvar
-
-@cindex format definition
Each format definition is a list of this form:
@example
(@var{name} @var{doc-string} @var{regexp} @var{from-fn} @var{to-fn} @var{modify} @var{mode-fn})
@end example
+@end defvar
+@cindex format definition
+@noindent
Here is what the elements in a format definition mean:
@table @var
If @var{to-fn} is a string, it is a shell command; Emacs runs the
command as a filter to perform the conversion.
-If @var{to-fn} is a function, it is called with two arguments, @var{begin}
-and @var{end}, which specify the part of the buffer it should convert.
-There are two ways it can do the conversion:
+If @var{to-fn} is a function, it is called with three arguments:
+@var{begin} and @var{end}, which specify the part of the buffer it
+should convert, and @var{buffer}, which specifies which buffer. There
+are two ways it can do the conversion:
@itemize @bullet
@item
in all buffers.
@end defvar
+@node Format Conversion Piecemeal
+@subsection Piecemeal Specification
+
+ In contrast to the round-trip specification described in the previous
+subsection (@pxref{Format Conversion Round-Trip}), you can use the variables
+@code{after-insert-file-functions} and @code{write-region-annotate-functions}
+to separately control the respective reading and writing conversions.
+
+ Conversion starts with one representation and produces another
+representation. When there is only one conversion to do, there is no
+conflict about what to start with. However, when there are multiple
+conversions involved, conflict may arise when two conversions need to
+start with the same data.
+
+ This situation is best understood in the context of converting text
+properties during @code{write-region}. For example, the character at
+position 42 in a buffer is @samp{X} with a text property @code{foo}. If
+the conversion for @code{foo} is done by inserting into the buffer, say,
+@samp{FOO:}, then that changes the character at position 42 from
+@samp{X} to @samp{F}. The next conversion will start with the wrong
+data straight away.
+
+ To avoid conflict, cooperative conversions do not modify the buffer,
+but instead specify @dfn{annotations}, a list of elements of the form
+@code{(@var{position} . @var{string})}, sorted in order of increasing
+@var{position}.
+
+ If there is more than one conversion, @code{write-region} merges their
+annotations destructively into one sorted list. Later, when the text
+from the buffer is actually written to the file, it intermixes the
+specified annotations at the corresponding positions. All this takes
+place without modifying the buffer.
+
+@c ??? What about ``overriding'' conversions like those allowed
+@c ??? for `write-region-annotate-functions', below? --ttn
+
+ In contrast, when reading, the annotations intermixed with the text
+are handled immediately. @code{insert-file-contents} sets point to the
+beginning of some text to be converted, then calls the conversion
+functions with the length of that text. These functions should always
+return with point at the beginning of the inserted text. This approach
+makes sense for reading because annotations removed by the first
+converter can't be mistakenly processed by a later converter.
+
+ Each conversion function should scan for the annotations it
+recognizes, remove the annotation, modify the buffer text (to set a text
+property, for example), and return the updated length of the text, as it
+stands after those changes. The value returned by one function becomes
+the argument to the next function.
+
+@defvar write-region-annotate-functions
+A list of functions for @code{write-region} to call. Each function in
+the list is called with two arguments: the start and end of the region
+to be written. These functions should not alter the contents of the
+buffer. Instead, they should return annotations.
+
+@c ??? Following adapted from comment in `build_annotations' (fileio.c).
+@c ??? Perhaps this is intended for internal use only?
+@c ??? Someone who understands this, please reword it. --ttn
+As a special case, if a function returns with a different buffer
+current, Emacs takes it to mean the current buffer contains altered text
+to be output, and discards all previous annotations because they should
+have been dealt with by this function.
+@end defvar
+
+@defvar after-insert-file-functions
+Each function in this list is called by @code{insert-file-contents}
+with one argument, the number of characters inserted, and with point
+at the beginning of the inserted text. Each function should leave
+point unchanged, and return the new character count describing the
+inserted text as modified by the function.
+@c ??? The docstring mentions a handler from `file-name-handler-alist'
+@c "intercepting" `insert-file-contents'. Hmmm. --ttn
+@end defvar
+
+ We invite users to write Lisp programs to store and retrieve text
+properties in files, using these hooks, and thus to experiment with
+various data formats and find good ones. Eventually we hope users
+will produce good, general extensions we can install in Emacs.
+
+ We suggest not trying to handle arbitrary Lisp objects as text property
+names or values---because a program that general is probably difficult
+to write, and slow. Instead, choose a set of possible data types that
+are reasonably flexible, and not too hard to encode.
+
@ignore
arch-tag: 141f74ce-6ae3-40dc-a6c4-ef83fc4ec35c
@end ignore