GNU Info

Info Node: (elisp)Magic File Names

(elisp)Magic File Names


Next: Format Conversion Prev: Create/Delete Dirs Up: Files
Enter node , (file) or (file)node

Making Certain File Names "Magic"
=================================

   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 (Note: Remote Files.
).

   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.

 - Variable: inhibit-file-name-handlers
     This variable holds a list of handlers whose use is presently
     inhibited for a certain operation.

 - Variable: inhibit-file-name-operation
     The operation for which certain handlers are presently inhibited.

 - Function: find-file-name-handler file operation
     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.  The operation
     is needed for comparison with `inhibit-file-name-operation'.

 - Function: file-local-copy filename
     This function copies file FILENAME to an ordinary non-magic file,
     if it isn't one already.

     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'.

 - Function: unhandled-file-name-directory filename
     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.


automatically generated by info2www version 1.2.2.9