[ < ] | [ > ] | [ << ] | [Plus haut] | [ >> ] | [Top] | [Table des matières] | [Index] | [ ? ] |
You can implement special handling for certain file names. This is called making those names magic. The principal use for this feature is in implementing remote file names (voir (emacs)Remote Files section `Remote Files' dans The GNU Emacs Manual).
To define a kind of magic file name, you must supply a regular expression to define the class of names (all those that match the regular expression), plus a handler that implements all the primitive Emacs file operations for file names that do match.
The variable file-name-handler-alist
holds a list of handlers,
together with regular expressions that determine when to apply each
handler. Each element has this form:
(regexp . handler) |
All the Emacs primitives for file access and file name transformation check
the given file name against file-name-handler-alist
. If the file
name matches regexp, the primitives handle that file by calling
handler.
The first argument given to handler is the name of the primitive, as a symbol; the remaining arguments are the arguments that were passed to that primitive. (The first of these arguments is most often the file name itself.) For example, if you do this:
(file-exists-p filename) |
and filename has handler handler, then handler is called like this:
(funcall handler 'file-exists-p filename) |
When a function takes two or more arguments that must be file names, it checks each of those names for a handler. For example, if you do this:
(expand-file-name filename dirname) |
then it checks for a handler for filename and then for a handler for dirname. In either case, the handler is called like this:
(funcall handler 'expand-file-name filename dirname) |
The handler then needs to figure out whether to handle filename or dirname.
If the specified file name matches more than one handler, the one whose match starts last in the file name gets precedence. This rule 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:
access-file
, add-name-to-file
,
byte-compiler-base-file-name
,
copy-file
,
delete-directory
, delete-file
, diff-latest-backup-file
,
directory-file-name
, directory-files
,
directory-files-and-attributes
, dired-call-process
,
dired-compress-file
, dired-uncache
,
expand-file-name
,
file-accessible-directory-p
, file-attributes
,
file-directory-p
, file-executable-p
, file-exists-p
,
file-local-copy
, file-remote-p
, file-modes
,
file-name-all-completions
, file-name-as-directory
,
file-name-completion
, file-name-directory
,
file-name-nondirectory
, file-name-sans-versions
,
file-newer-than-file-p
, file-ownership-preserved-p
,
file-readable-p
, file-regular-p
, file-symlink-p
,
file-truename
, file-writable-p
, find-backup-file-name
,
find-file-noselect
,
get-file-buffer
,
insert-directory
, insert-file-contents
,
load
,
make-auto-save-file-name
, make-directory
,
make-directory-internal
, make-symbolic-link
,
rename-file
, set-file-modes
, set-file-times
,
set-visited-file-modtime
, shell-command
,
substitute-in-file-name
,
unhandled-file-name-directory
,
vc-registered
, verify-visited-file-modtime
,
write-region
.
Handlers for insert-file-contents
typically need to clear the
buffer's modified flag, with (set-buffer-modified-p nil)
, if the
visit argument is non-nil
. This also has the effect of
unlocking the buffer if it is locked.
The handler function must handle all of the above operations, and possibly others to be added in the future. It need not implement all these operations itself—when it has nothing special to do for a certain operation, it can reinvoke the primitive, to handle the operation “in the usual way.” It should always reinvoke the primitive for an operation it does not recognize. Here's one way to do this:
(defun my-file-handler (operation &rest args) ;; First check for the specific operations ;; that we have special handling for. (cond ((eq operation 'insert-file-contents) …) ((eq operation 'write-region) …) … ;; Handle any operation we don't know about. (t (let ((inhibit-file-name-handlers (cons 'my-file-handler (and (eq inhibit-file-name-operation operation) inhibit-file-name-handlers))) (inhibit-file-name-operation operation)) (apply operation args))))) |
When a handler function decides to call the ordinary Emacs primitive for the
operation at hand, it needs to prevent the primitive from calling the same
handler once again, thus leading to an infinite recursion. The example
above shows how to do this, with the variables
inhibit-file-name-handlers
and inhibit-file-name-operation
.
Be careful to use them exactly as shown above; the details are crucial for
proper behavior in the case of multiple handlers, and for operations that
have two file names that may each have handlers.
Handlers that don't really do anything special for actual access to the
file—such as the ones that implement completion of host names for remote
file names—should have a non-nil
safe-magic
property. For
instance, Emacs normally “protects” directory names it finds in
PATH
from becoming magic, if they look like magic file names, by
prefixing them with ‘/:’. But if the handler that would be used for
them has a non-nil
safe-magic
property, the ‘/:’ is not
added.
A file name handler can have an operations
property to declare which
operations it handles in a nontrivial way. If this property has a
non-nil
value, it should be a list of operations; then only those
operations will call the handler. This avoids inefficiency, but its main
purpose is for autoloaded handler 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 file-exists-p
, then it
must handle load
itself, because the usual load
code won't
work properly in that case. However, if the handler uses the
operations
property to say it doesn't handle file-exists-p
,
then it need not handle load
nontrivially.
This variable holds a list of handlers whose use is presently inhibited for a certain operation.
The operation for which certain handlers are presently inhibited.
This function returns the handler function for file name file, or
nil
if there is none. The argument operation should be the
operation to be performed on the file—the value you will pass to the
handler as its first argument when you call it. If operation equals
inhibit-file-name-operation
, or if it is not found in the
operations
property of the handler, this function returns nil
.
This function copies file filename to an ordinary non-magic file on
the local machine, if it isn't on the local machine already. Magic file
names should handle the file-local-copy
operation if they refer to
files on other machines. A magic file name that is used for other purposes
than remote file access should not handle file-local-copy
; then this
function will treat the file as local.
If filename is local, whether magic or not, this function does nothing
and returns nil
. Otherwise it returns the file name of the local
copy file.
This function tests whether filename is a remote file. If
filename is local (not remote), the return value is nil
. If
filename is indeed remote, the return value is a string that
identifies the remote system.
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
/ssh:user@host:/some/file
is /ssh:user@host:
.
If file-remote-p
returns the same identifier for two different
filenames, that means they are stored on the same file system and can be
accessed locally with respect to each other. This means, for 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.
This function returns the name of a directory that is not magic. It uses the directory part of filename if that is not magic. For a magic file name, it invokes the file name handler, which therefore decides what value to return.
This is useful for running a subprocess; every subprocess must have a non-magic directory to serve as its current directory, and this function is a good way to come up with one.
[ < ] | [ > ] | [ << ] | [Plus haut] | [ >> ] | [Top] | [Table des matières] | [Index] | [ ? ] |
Ce document a été généré par Eric Reinbold le 13 Octobre 2007 en utilisant texi2html 1.78.