Go to the first, previous, next, last section, table of contents.

Making Certain File Names "Magic"

You can implement special handling for a class of file names. You must supply a regular expression to define the class of names (all those which match the regular expression), plus a handler that implements all the primitive Emacs file operations for file names that do match.

The value of file-name-handler-alist is a list of handlers, together with regular expressions that decide when to apply each handler. Each element has the form (regexp . handler). If a file name matches regexp, then all work on that file is done by calling handler.

All the Emacs primitives for file access and file name transformation check the given file name against file-name-handler-alist, and call handler to do the work if appropriate. 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 typically 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)

Here are the primitives that you can handle in this way:

add-name-to-file, copy-file, delete-directory, delete-file, directory-file-name, directory-files, 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-readable-p, file-symlink-p, file-writable-p, insert-directory, insert-file-contents, load, make-directory, make-symbolic-link, rename-file, set-file-modes, set-visited-file-modtime, unhandled-file-name-directory, verify-visited-file-modtime, write-region.

The handler function must handle all of the above operations, and possibly others to be added in the future. Therefore, it should always reinvoke the ordinary Lisp primitive when it receives 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 (file-name-handler-alist)
             (apply operation args)))))

The function file-local-copy copies file filename to the local site, if it isn't there 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.

The function unhandled-file-name-directory is used to get a non-magic directory name from an arbitrary file name. It uses the directory part of the specified file name if that is not magic. Otherwise, it asks the file name's handler what to do.


Go to the first, previous, next, last section, table of contents.