Next: ファイルのフォーマット変換, Previous: ディレクトリーの作成・コピー・削除, Up: ファイル [Contents][Index]
特定のファイル名にたいして特別な処理を実装できます。これはそれらの名前にたいするmagic化と呼ばれます。この機能は主にリモートファイルにたいするアクセスの実装用に使用されます(Remote Files in The GNU Emacs Manualを参照)。
magicファイル名を定義するには、名前クラスを定義するための正規表現とそれにマッチするファイル名用のEmacsファイル操作プリミティブすべてを実装するハンドラーを定義しなければなりません。
変数file-name-handler-alist
は各ハンドラーに適用するときを決定する正規表現とともにハンドラーのリストを保持します。各要素は以下の形式をもちます:
(regexp . handler)
ファイルアクセスとファイル名変換にたいするすべてのEmacsプリミティブは、file-name-handler-alist
にたいして与えられたファイル名をチェックします。そのファイル名がregexpにマッチしたら、そのプリミティブがhandlerを呼び出してファイルを処理します。
handlerの1つ目の引数には、プリミティブの名前をシンボルとして与えます。残りの引数はそのプリミティブに引数として渡されます(これらの引数の1つ目はほとんどの場合はファイル名自身)。たとえば以下を行って:
(file-exists-p filename)
filenameがハンドラーhandlerをもつなら、handlerは以下のように呼び出されます:
(funcall handler 'file-exists-p filename)
関数が2つ以上の引数を受け取る場合には、それらはファイル名でなければならず、関数はそれらのファイル名それぞれにたいしてハンドラーをチェックします。たとえば、
(expand-file-name filename dirname)
以下を行うと、filenameにたいするハンドラーをチェックした後にdirnameにたいするハンドラーをチェックします。どちらの場合でもhandlerは以下のように呼び出されます:
(funcall handler 'expand-file-name filename dirname)
その後にhandlerはfilenameとdirnameのいずれかを処理するか解決する必要があります。
指定されたファイル名が2つ以上のハンドラーにマッチする場合には、ファイル名の中で最後に開始するマッチが優先されます。リモートファイルアクセスのようなジョブにたいするハンドラーに先立って、解凍のようなジョブにたいするハンドラーが最初に処理されるようにこのルールが選択されました。
以下はmagicファイル名ハンドラーが処理する操作です:
abbreviate-file-name
、access-file
、add-name-to-file
、byte-compiler-base-file-name
、
copy-directory
、copy-file
、delete-directory
、delete-file
、diff-latest-backup-file
、directory-file-name
、directory-files
、directory-files-and-attributes
、dired-compress-file
、dired-uncache
、exec-path
、expand-file-name
、
file-accessible-directory-p
、file-acl
、file-attributes
、file-directory-p
、file-equal-p
、file-executable-p
、file-exists-p
、file-group-gid
、file-in-directory-p
、file-local-copy
、file-locked-p
、file-modes
、file-name-all-completions
、file-name-as-directory
、file-name-case-insensitive-p
、file-name-completion
、file-name-directory
、file-name-nondirectory
、file-name-sans-versions
、file-newer-than-file-p
、file-notify-add-watch
、file-notify-rm-watch
、file-notify-valid-p
、file-ownership-preserved-p
、file-readable-p
、file-regular-p
、file-remote-p
、file-selinux-context
、file-symlink-p
、file-system-info
、file-truename
、file-user-uid
、file-writable-p
、find-backup-file-name
、
get-file-buffer
、insert-directory
、insert-file-contents
、
list-system-processes
、load
、lock-file
、make-auto-save-file-name
、make-directory
、make-lock-file-name
、make-nearby-temp-file
、make-process
、make-symbolic-link
、
memory-info
、process-attributes
、process-file
、rename-file
、set-file-acl
、set-file-modes
、set-file-selinux-context
、set-file-times
、set-visited-file-modtime
、shell-command
、start-file-process
、substitute-in-file-name
、
temporary-file-directory
、unhandled-file-name-directory
、unlock-file
、vc-registered
、verify-visited-file-modtime
、
write-region
insert-file-contents
にたいするハンドラーはvisit引数が非nil
なら、通常は(set-buffer-modified-p
nil)
によりそのバッファーの変更フラグをクリアーする必要があります。これにはもしそのバッファーがロックされていたら、ロックを解除する効果もあります。
ハンドラー関数は上記すべての操作を処理しなければならず、他の操作が将来追加される可能性もあります。これらの操作自体すべてを実装する必要はありません — 特定の操作にたいして特別なことを行う必要がないときには、その操作を通常の方法で処理するように、そのプリミティブを再呼び出しできます。認識できない操作にたいしては、常にそのプリミティブを再呼び出しするべきです。以下はこれを行う方法の1つです:
(defun my-file-handler (operation &rest args) ;; 特別に処理する必要がある、 ;; 特別な操作を最初にチェックする (cond ((eq operation 'insert-file-contents) …) ((eq operation 'write-region) …) … ;; 関知しないその他の操作を処理する (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)))))
ハンドラー関数が通常のEmacsプリミティブを呼び出す決定をした際には、無限再帰を引き起こすような同一ハンドラーからのプリミティブの再呼び出しを防ぐ必要があります。上記の例では変数inhibit-file-name-handlers
とinhibit-file-name-operation
によって、これを行う方法を示しています。上記の例のように、これらを正確に使用するよう注意してください。複数ハンドラーの正しい振る舞いと、それぞれがハンドラーをもつかもしれない2つのファイル名にたいする操作にたいする詳細は非常に重要です。
ファイルへの実アクセスにたいして実際には特別なことを行わないハンドラー(たとえばリモートファイル名にたいしてホスト名の補完を実装するハンドラー等)は、safe-magic
プロパティに非nil
をもつべきです。たとえばEmacsは通常はPATH
内で見い出されるようなディレクトリーがプレフィックス‘/:’によってmagicファイル名に見えるようなら、magicファイル名にならないように保護します。しかしsafe-magic
プロパティに非nil
をもつハンドラーがそれらにたいして使用された場合には、‘/:’は追加されません。
ファイル名ハンドラーは普通とは異なる方法でそれを処理(handle)するのがどの操作(operation)なのかを宣言するために、operations
プロパティをもつことができます。このプロパティが非nil
値をもつなら、それは操作のリストであるべきです。その場合には、それらの操作だけがハンドラーを呼び出すでしょう。これは無駄を省きますが、主な目的はオートロードされるハンドラー関数が実際に処理を行うとき以外はロードされないようにすることです。
通常のプリミティブにたいして単にすべての操作を延期しても機能しません。たとえばファイル名ハンドラーがfile-exists-p
にたいして適用された場合には、通常のload
コードは正しく機能しないでしょうから、ハンドラー自身でload
を処理しなければなりません。しかしハンドラーがfile-exists-p
プロパティを使用してfile-exists-p
を処理しないことを宣言した場合には、普通とは異なる方法でload
を処理する必要はなくなります。
この変数は特定の操作にたいして現在のところ使用を抑制されているハンドラーのリストを保持する。
特定のハンドラーにたいしてその時点で抑制されている操作。
この関数はfileというファイル名にたいするハンドラー関数、それが存在しなければnil
をリターンする。引数operationはそのファイルを処理する操作であること。これはハンドラー呼び出し時に1つ目の引数として渡すことになる値である。operationがinhibit-file-name-operation
と等しいか、そのハンドラーのoperations
内に存在しなければ、この関数はnil
をリターンする。
この関数はファイルfilenameがまだローカルマシン上になければ、それをローカルマシン上の通常の非magicファイルにコピーする。magicファイル名は、それらが他のマシン上のファイルを参照する場合には、file-local-copy
操作を処理するべきである。リモートファイルアクセス以外の目的にたいして使用されるmagicファイル名は、file-local-copy
を処理するべきではない。この場合には関数はそのファイルをローカルファイルとして扱うだろう。
filenameがローカルなら、それがmagicか否かにかかわらずこの関数は何も行わずにnil
をリターンする。それ以外ならローカルコピーファイルのファイル名をリターンする。
この関数はfilenameがリモートファイルかどうかをテストする。filenameがローカル(リモートではない)ならリターン値はnil
、filenameが正にリモートならリターン値はそのリモートシステムを識別する文字列。
この識別子文字列はホスト名とユーザー名、およびリモートシステムへのアクセスに使用されるメソッドを表す文字列も同様に含めることができる。たとえばファイル名/sudo::/some/file
にたいするリモート識別子文字列は/sudo:root@localhost:
。
2つの異なるファイルにたいしてfile-remote-p
が同じ識別子をリターンした場合には、それらが同じファイルシステム上に格納されていて互いに配慮しつつアクセス可能であることを意味する。これはたとえば同時に両方のファイルにアクセスするリモートプロセスを開始することが可能なことを意味する。ファイル名ハンドラーの実装者はこの方式を保証する必要がある。
identificationは文字列としてリターンされるべき識別子の一部を指定する。identificationにはmethod
、user
、host
、あるいはlocalname
のシンボルを指定できる。他の値はすべてnil
のように扱われて、それは完全な識別子文字列をリターンすることを意味する。上記の例ではリモートのuser
識別子文字列はroot
になるだろう。
リモートのfileにメソッド、ユーザー名、ホスト名が含まれていない場合には、それぞれに応じたデフォルト値がリターンされる。identificationとlocalname
にたいしてリターンされる文字列は、既存の接続が存在するか否かに応じて異なる。ファイル名ハンドラーの特定の実装は、identification以上のシンボルをサポートするかもしれない。たとえばhop
と呼ばれるシンボルについては、(tramp)Trampを参照のこと。
connectedが非nil
なら、たとえfilenameがリモートであってもEmacsがそのホストにたいする接続をもたなければ、この関数はnil
をリターンする。これは接続が存在しない際の接続の遅延を回避したいときに有用。connectedがnever
なら、たとえ識別子がすでに与えられていたとしても(そうでなければnil
のような値になる)、識別子のリターンに既存の接続を使うことh決してない。これによりファイル名のローカル部分の展開のような接続固有のロジックを回避できる。
この関数は非magicのディレクトリーの名前をリターンする。これは非magicのfilenameには対応するディレクトリー名(ディレクトリーの名前を参照)をリターンする。magicのfilenameには、何の値をリターンするかを決定するためにファイル名ハンドラーを呼び出す。filenameがローカルプロセスからアクセス不能なら、ファイル名ハンドラーはnil
をリターンすることによってそれを示すこと。
これはサブプロセスの実行に有用。すべてのサブプロセスは自身が所属するカレントディレクトリーとして非magicディレクトリーをもたなければならず、この関数はそれを導出するよい手段である。
この関数はfilenameのローカル部分(local part)をリターンする。これはリモートホスト上でファイル名を識別する部分であり、通常はリモートファイル名からリモートホストを指定する部分とアクセス方法を取り除いた部分である。たとえば:
(file-local-name "/ssh:user@host:/foo/bar") ⇒ "/foo/bar"
この関数はリモートのfilenameにたいして、リモートプロセス(非同期プロセスの作成と同期プロセスの作成を参照)やリモートホスト上で実行されるプログラムの引数として直接使用可能なファイル名をリターンする。filenameがローカルなら、この関数はそれを変更せずにリターンする。
リモートファイルの属性は、よりよいパフォーマンスのためにキャッシュすることができる。キャッシュがEmacsの制御外で変更されると、そのキャッシュ値は無効になり再読込しなければならない。
この変数がnil
にセットされているとキャッシュ値は決して失効しない。このセッティングはEmacs以外にリモートファイルを変更するものがないことが確実な場合のみ慎重に使用すること。これがt
にセットされているとキャッシュ値は決して使用されない。これはもっとも安全な値であるがパフォーマンスは低下するかもしれない。
折衷的な値としてはこれを正の数字にセットする。これはキャッシュされてからその数字の秒数の間は、ャッシュ値を使用することを意味する。リモートファイルが定期的にチェックされる場合には、この変数を定期的なチェックの間隔より小さい値にletバインドするのは、よい考えかもしれない。たとえば:
(defun display-time-file-nonempty-p (file) (let ((remote-file-name-inhibit-cache (- display-time-interval 5))) (and (file-exists-p file) (< 0 (file-attribute-size (file-attributes (file-chase-links file)))))))
without-remote-files
マクロはリモートファイル向けファイル名ハンドラーを非アクティブにしてbodyを評価する。これらのファイル名はリテラルにそのまま処理されるだろう。
このマクロはリモートファイルが出現せず、リモートファイル名の処理を意図しないことが明白なフォームでのみ使用すること。さらにfile-name-handler-alist
によるチェックも削減されて、コードの性能がより改善されるだろう。
Next: ファイルのフォーマット変換, Previous: ディレクトリーの作成・コピー・削除, Up: ファイル [Contents][Index]