[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [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 (see section `Remote Files' in 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; 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.
Here are the operations that a magic file name handler gets to handle:
add-name-to-file
, copy-file
, delete-directory
,
delete-file
,
diff-latest-backup-file
,
directory-file-name
,
directory-files
,
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-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
,
get-file-buffer
,
insert-directory
,
insert-file-contents
,
load
, make-directory
,
make-symbolic-link
, rename-file
, set-file-modes
,
set-visited-file-modtime
, shell-command
,
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.
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. The operation is needed
for comparison with inhibit-file-name-operation
.
If filename specifies a magic file name, which programs outside Emacs cannot directly read or write, this copies the contents to an ordinary file and returns that file's name.
If filename is an ordinary file name, not magic, then this function
does nothing and returns nil
.
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.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |