defmodule FsNotify do
@moduledoc """
Filesystem watcher backed by notify-rs (via Rustler).
Watch one or more paths and receive each filesystem event in your process as
`{:fs_notify_event, %FsNotify.Event{}}` (mirroring notify-rs: one message per
event, carrying all affected `paths`).
{:ok, ref} = FsNotify.watch("/some/dir", recursive: true)
{:ok, ref} = FsNotify.watch(["/dir/a", "/dir/b"])
receive do
{:fs_notify_event, %FsNotify.Event{kind: kind, paths: paths}} -> handle(kind, paths)
end
FsNotify.unwatch(ref)
The watch is tied to the subscriber process: it stops automatically when that
process dies (and also if `ref` is garbage-collected). `unwatch/1` stops it
eagerly.
"""
@doc """
Start watching `path` (a path or a list of paths).
Returns `{:ok, ref}`; keep `ref` for as long as you want to watch. Options:
* `:recursive` (default `true`) — watch subdirectories
* `:subscriber` (default: the calling process) — process that receives events
* `:debounce` (default `0`) — coalesce events over this many ms (notify-rs
debouncer); `0` disables debouncing
* `:backend` (default `:recommended`) — `:recommended` (the OS-native
backend) or `:poll` (portable polling watcher)
* `:poll_interval` (default `0`) — poll interval in ms for the `:poll`
backend; `0` uses notify's default
## Examples
{:ok, ref} = FsNotify.watch("/tmp/dir", recursive: true)
{:ok, ref} = FsNotify.watch(["/tmp/a", "/tmp/b"], debounce: 100)
{:ok, ref} = FsNotify.watch("/tmp/dir", backend: :poll, poll_interval: 200)
"""
@spec watch(binary() | [binary()], keyword()) :: {:ok, reference()} | {:error, binary()}
def watch(path, opts \\ []) do
subscriber = Keyword.get(opts, :subscriber, self())
native_opts = %{
recursive: Keyword.get(opts, :recursive, true),
debounce: Keyword.get(opts, :debounce, 0),
backend: Keyword.get(opts, :backend, :recommended),
poll_interval: Keyword.get(opts, :poll_interval, 0)
}
FsNotify.Native.watch(subscriber, List.wrap(path), native_opts)
end
@doc """
Stop the watcher identified by `ref`.
## Examples
{:ok, ref} = FsNotify.watch("/tmp/dir")
:ok = FsNotify.unwatch(ref)
"""
@spec unwatch(reference()) :: :ok
def unwatch(ref), do: FsNotify.Native.unwatch(ref)
end