Next: , Previous: , Up: Files   [Contents][Index]


35.11 Making Certain File Names “Magic”

You can implement special handling for certain file names. This is called making those names magic. 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 SXEmacs 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 SXEmacs 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 operation. (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 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-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-regular-p, file-symlink-p, file-truename, file-writable-p, get-file-buffer, 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.

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 filename &optional operation

This function returns the handler function for file name filename, 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. Otherwise, it asks the handler what to do.

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.


Next: , Previous: , Up: Files   [Contents][Index]