複数のオペレーティングシステムが、ファイルやその属性の変更をファイルシステム上で監視する機能をサポートしています。適切に設定されていれば、Emacsはinotify、kqueue、gfilenotify、またはw32notifyといった対応するライブラリを静的にリンクします。これらのライブラリにより、ローカルマシン上のファイルシステムの監視が可能になります。
リモートマシン上のファイルシステムを監視することも可能です。The GNU Emacs ManualのRemote Filesを参照してください。これは、Emacsにリンクされているライブラリのいずれかに依存するものではありません。
これらのライブラリはいずれもファイル変更の通知時に異なるイベントを発生させるため、Emacsではアプリケーションに統一されたインターフェースを提供する専用ライブラリ
filenotify
を用意しています。ファイル通知を受信したいLispプログラムでは、標準のライブラリよりも常にこのライブラリを使用するようにしてください。本節では、filenotify ライブラリの関数と変数について解説します。
file に関するファイルシステムイベントのウォッチを追加します。これにより、file に関するファイルシステムイベントが Emacs に報告されるようになります。
戻り値は、追加されたウォッチのディスクリプタです。その型は基盤となるライブラリに依存しており、一般的に以下の例のように整数であるとは想定できません。equal による比較にのみ使用してください。
何らかの理由で file を監視できない場合、この関数は file-notify-error エラーを通知します。
マウントされたファイルシステムでは、ファイルの変更を監視できない場合があります。この関数ではこれを検知できないため、戻り値がnil以外であっても、fileでの変更が実際に通知されるとは限りません。
file がシンボリックリンクの場合、そのリンクは辿りません。file 自体のみが監視対象となります。
flags は、監視対象を指定するための条件リストです。以下の記号を含めることができます:
changeファイルの内容の変更を監視する
attribute-change権限や更新日時などのファイル属性の変更を監視する
file がディレクトリの場合、change
はそのディレクトリ内でのファイルの作成および削除を監視します。ネイティブのファイル通知ライブラリの中にも、このような場合にファイルの変更を報告するものがあります。これは再帰的には動作しません。
何らかのイベントが発生すると、Emacsはcallback関数を呼び出し、単一の引数eventを渡します。この引数は、次のような形式になっています。
(descriptor action file [file1])
descriptor は、この関数が返すものと同じオブジェクトです。 action はイベントの説明です。 以下のいずれかのシンボルになります:
createdfile が作成されました
deletedfile が削除されました
changedfileの内容が変更されました。w32notifyライブラリでは、レポートでも属性の変更が反映されます。
renamedfile は file1 に名称変更されました
attribute-changeda file 属性が変更されました
stoppedfile の視聴が停止しました
なお、w32notify ライブラリは attribute-changed
イベントを報告しません。権限や更新日時など、ファイルの属性が変更された場合、このライブラリは changed イベントを報告します。同様に、kqueue
ライブラリはディレクトリを監視している際、ファイル属性の変更を確実に報告するわけではありません。
stopped イベントは、ファイルの監視が停止したことを示します。これは、file-notify-rm-watch
が呼び出されたため(後述)、監視対象のファイルが削除されたため、監視対象ファイルのファイルシステムがアンマウントされたため、あるいは基盤となるライブラリから報告されたその他のエラーにより以降の監視が不可能になったためと考えられます。
file および file1 は、イベントが報告されているファイルの名称です。例えば:
(require 'filenotify)
⇒ filenotify
(defun my-notify-callback (event)
(message "Event %S" event))
⇒ my-notify-callback
(file-notify-add-watch
"/tmp" '(change attribute-change) 'my-notify-callback)
⇒ 35025468
(write-region "foo" nil "/tmp/foo")
⇒ Event (35025468 created "/tmp/.#foo")
Event (35025468 created "/tmp/foo")
Event (35025468 changed "/tmp/foo")
Event (35025468 deleted "/tmp/.#foo")
(write-region "bla" nil "/tmp/foo")
⇒ Event (35025468 created "/tmp/.#foo")
Event (35025468 changed "/tmp/foo")
Event (35025468 deleted "/tmp/.#foo")
(set-file-modes "/tmp/foo" (default-file-modes) 'nofollow)
⇒ Event (35025468 attribute-changed "/tmp/foo")
アクション renamed
が返されるかどうかは、使用するウォッチライブラリによって異なります。そうでない場合、アクション deleted と created
がランダムな順序で返される可能性があります。
(rename-file "/tmp/foo" "/tmp/bla")
⇒ Event (35025468 renamed "/tmp/foo" "/tmp/bla")
(delete-file "/tmp/bla")
⇒ Event (35025468 deleted "/tmp/bla")
descriptorで指定された既存のファイルウォッチを削除します。descriptorはfile-notify-add-watchから返されたオブジェクトである必要があります。
Emacsから既存のファイル通知ウォッチをすべて削除します。
このコマンドは、ファイルウォッチに依存するパッケージに予期せぬ副作用を及ぼす可能性があるため、慎重に使用してください。主にデバッグ目的や、Emacsがフリーズした際に使用することを想定しています。
descriptor で指定されたウォッチの有効性を確認します。descriptor は file-notify-add-watch が返すオブジェクトである必要があります。
監視対象のファイルやディレクトリが削除されたり、その他の理由で監視スレッドが異常終了したりすると、ウォッチが無効になることがあります。file-notify-rm-watch を呼び出してウォッチを削除した場合も、同様に無効になります。
(make-directory "/tmp/foo")
⇒ Event (35025468 created "/tmp/foo")
(setq desc
(file-notify-add-watch
"/tmp/foo" '(change) 'my-notify-callback))
⇒ 11359632
(file-notify-valid-p desc)
⇒ t
(write-region "bla" nil "/tmp/foo/bla")
⇒ Event (11359632 created "/tmp/foo/.#bla")
Event (11359632 created "/tmp/foo/bla")
Event (11359632 changed "/tmp/foo/bla")
Event (11359632 deleted "/tmp/foo/.#bla")
;; Deleting a file in the directory doesn't invalidate the watch.
(delete-file "/tmp/foo/bla")
⇒ Event (11359632 deleted "/tmp/foo/bla")
(write-region "bla" nil "/tmp/foo/bla")
⇒ Event (11359632 created "/tmp/foo/.#bla")
Event (11359632 created "/tmp/foo/bla")
Event (11359632 changed "/tmp/foo/bla")
Event (11359632 deleted "/tmp/foo/.#bla")
;; Deleting the directory invalidates the watch.
;; Events arrive for different watch descriptors.
(delete-directory "/tmp/foo" 'recursive)
⇒ Event (35025468 deleted "/tmp/foo")
Event (11359632 deleted "/tmp/foo/bla")
Event (11359632 deleted "/tmp/foo")
Event (11359632 stopped "/tmp/foo")
(file-notify-valid-p desc)
⇒ nil