Некоторые операционные системы поддерживают наблюдение за файловыми системами на предмет изменений файлов или их атрибутов. При правильной настройке Emacs статически связывает соответствующую библиотеку, такую как inotify, kqueue, gfilenotify или w32notify. Эти библиотеки позволяют наблюдать за файловыми системами на локальной машине.
Также возможно наблюдение за файловыми системами на удалённых машинах; см. Удалённые файлы в Руководстве по GNU Emacs. Это не зависит ни от одной из библиотек, связанных с Emacs.
Поскольку все эти библиотеки генерируют различные события при уведомлении об изменениях файлов, Emacs предоставляет специальную библиотеку filenotify, которая представляет унифицированный интерфейс для приложений. Lisp-программы, которые хотят получать уведомления о файлах, должны всегда использовать эту библиотеку вместо нативных. В этом разделе документируются функции и переменные библиотеки filenotify.
Добавляет наблюдение за событиями файловой системы, относящимися к файлу. Это обеспечивает передачу событий файловой системы, относящихся к файлу, в Emacs.
Возвращаемое значение — это дескриптор добавленного наблюдения. Его тип зависит от используемой библиотеки, и в общем случае нельзя предполагать, что это целое число, как в примере ниже. Его следует использовать только для сравнения с помощью equal.
Если за файлом по какой-либо причине невозможно наблюдать, эта функция сигнализирует об ошибке file-notify-error.
Иногда за смонтированными файловыми системами невозможно наблюдать на предмет изменений файлов. Это не обнаруживается данной функцией, поэтому возвращаемое значение, не равное nil, не гарантирует, что изменения в файле будут действительно уведомлены.
Если файл является символической ссылкой, эта ссылка не разыменовывается. Наблюдение ведётся именно за самим файлом.
флаги — это список условий, определяющих, за чем вести наблюдение. Он может содержать следующие символы:
changeнаблюдать за изменениями содержимого файла
attribute-changeнаблюдать за изменениями атрибутов файла, таких как права доступа или время изменения
Если файл является каталогом, change отслеживает создание и удаление файлов в этом каталоге. Некоторые нативные библиотеки уведомлений о файлах также сообщают об изменениях файлов в этом случае. Это не работает рекурсивно.
При возникновении любого события Emacs вызовет функцию обратный-вызов, передав ей единственный аргумент событие вида
(дескриптор действие файл [файл1])
дескриптор — это тот же объект, который возвращает данная функция. действие — это описание события. Оно может быть одним из следующих символов:
createdфайл был создан
deletedфайл был удалён
changedсодержимое файла изменилось; в библиотеке w32notify также сообщает об изменениях атрибутов
renamedфайл был переименован в файл1
attribute-changedизменился атрибут файла
stoppedнаблюдение за файлом остановлено
Обратите внимание, что библиотека w32notify не сообщает о событиях attribute-changed. Когда изменяется какой-либо атрибут файла, например права доступа или время изменения, эта библиотека сообщает о событии changed. Аналогично, библиотека kqueue не надёжно сообщает об изменениях атрибутов файлов при наблюдении за каталогом.
Событие stopped означает, что наблюдение за файлом было прекращено. Это может произойти, если была вызвана file-notify-rm-watch (см. ниже), или если наблюдаемый файл был удалён, или файловая система наблюдаемого файла была размонтирована, либо из-за другой ошибки, сообщённой нижележащей библиотекой, которая делает дальнейшее наблюдение невозможным.
файл и файл1 — это имена файлов, о событии которых сообщается. Например:
(require 'filenotify)
⇒ filenotify
(defun my-notify-callback (событие)
(message "Событие %S" событие))
⇒ my-notify-callback
(file-notify-add-watch
"/tmp" '(change attribute-change) 'my-notify-callback)
⇒ 35025468
(write-region "foo" nil "/tmp/foo")
⇒ Событие (35025468 created "/tmp/.#foo")
Событие (35025468 created "/tmp/foo")
Событие (35025468 changed "/tmp/foo")
Событие (35025468 deleted "/tmp/.#foo")
(write-region "bla" nil "/tmp/foo")
⇒ Событие (35025468 created "/tmp/.#foo")
Событие (35025468 changed "/tmp/foo")
Событие (35025468 deleted "/tmp/.#foo")
(set-file-modes "/tmp/foo" (default-file-modes) 'nofollow)
⇒ Событие (35025468 attribute-changed "/tmp/foo")
Возврат действия renamed зависит от используемой библиотеки наблюдения. В противном случае действия deleted и created могут возвращаться в случайном порядке.
(rename-file "/tmp/foo" "/tmp/bla")
⇒ Событие (35025468 renamed "/tmp/foo" "/tmp/bla")
(delete-file "/tmp/bla")
⇒ Событие (35025468 deleted "/tmp/bla")
Удаляет существующее наблюдение за файлом, заданное его дескриптором.
дескриптор должен быть объектом, возвращённым file-notify-add-watch.
Удаляет все существующие наблюдения за уведомлениями о файлах из Emacs.
Используйте эту команду с осторожностью, так как она может иметь неожиданные побочные эффекты для пакетов, полагающихся на наблюдения за файлами. Она предназначена главным образом для целей отладки или когда Emacs завис.
Проверяет наблюдение, заданное его дескриптором, на действительность.
дескриптор должен быть объектом, возвращённым file-notify-add-watch.
Наблюдение может стать недействительным, если файл или каталог, за которым оно ведётся, будет удалён, или если поток наблюдателя завершится аномально по любой другой причине. Удаление наблюдения вызовом file-notify-rm-watch также делает его недействительным.
(make-directory "/tmp/foo")
⇒ Событие (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")
⇒ Событие (11359632 created "/tmp/foo/.#bla")
Событие (11359632 created "/tmp/foo/bla")
Событие (11359632 changed "/tmp/foo/bla")
Событие (11359632 deleted "/tmp/foo/.#bla")
;; Удаление файла в каталоге не делает наблюдение недействительным.
(delete-file "/tmp/foo/bla")
⇒ Событие (11359632 deleted "/tmp/foo/bla")
(write-region "bla" nil "/tmp/foo/bla")
⇒ Событие (11359632 created "/tmp/foo/.#bla")
Событие (11359632 created "/tmp/foo/bla")
Событие (11359632 changed "/tmp/foo/bla")
Событие (11359632 deleted "/tmp/foo/.#bla")
;; Удаление каталога делает наблюдение недействительным.
;; События поступают для разных дескрипторов наблюдения.
(delete-directory "/tmp/foo" 'recursive)
⇒ Событие (35025468 deleted "/tmp/foo")
Событие (11359632 deleted "/tmp/foo/bla")
Событие (11359632 deleted "/tmp/foo")
Событие (11359632 stopped "/tmp/foo")
(file-notify-valid-p desc)
⇒ nil