Pular para o conteúdo

Stdlib · extensões

watch

file-watching ergonômico (sobre a primitiva do fs)

extensions.md · 63 linhas · 2 min de leitura

use watch

A camada ergonômica de observação de filesystem, sobre a primitiva tier 0 fs.watch_raw (o wrapper fino de inotify/kqueue/FSEvents/ReadDirectoryChangesW, que vive no core, por ser syscall e mecanismo). O compilador/LSP usa a primitiva direto (tier 0 não depende de tier 1); quem quer conveniência (debounce, recursão, normalização entre OSes, ignore-globs) importa esta lib. Coerente com sinais-como-channel: eventos chegam num Channel, não num callback global.

// vive em `fs` (tier 0); listada aqui só para contexto:
fn fs.watch_raw(path: string) -> Result[Channel[->RawFsEvent], error{NotFound, Io}]
decl RawFsEvent { pub path: string; pub kind: RawKind }
decl RawKind { Created; Modified; Deleted; MovedFrom; MovedTo } // cru, como o SO reporta

A lib (tier 1): eventos normalizados e coalescidos

Seção intitulada “A lib (tier 1): eventos normalizados e coalescidos”
fn watch(path: string) -> Result[Watcher, error{NotFound, Io}] // um caminho
fn watch_tree(root: string) -> Result[Watcher, error{NotFound, Io}] // recursivo
decl Watcher { pub events: Channel[->FsEvent] }
fn (w: *Watcher) with_debounce(d: Duration) -> Watcher // coalesce rajadas (salvar dispara N eventos crus)
fn (w: *Watcher) ignore(glob: string) -> Watcher // ignora caminhos (node_modules, .git)
fn (w: *Watcher) close() // fecha o channel / encerra a observação
decl FsEvent {
Created(string)
Modified(string)
Deleted(string)
Renamed(from: string, to: string) // rename-tracking: junta MovedFrom+MovedTo do SO num evento só
}
use watch
w := watch.watch_tree("src").or_panic().with_debounce(200ms).ignore("**/.git/**")
loop ev in w.events {
match ev {
Modified(p) => rebuild(p)
Renamed(from, to) => { drop(from); rebuild(to) }
Created(p) => rebuild(p)
Deleted(p) => drop(p)
}
}
  • Primitiva no core, serviço no tier 1: o mesmo corte do runtime (a primitiva trace é core, o observer é tooling) e da MemorySource (syscall core, estratégia lib). A parte que o compilador/LSP precisa (fs.watch_raw) é tier 0; só a conveniência é tier 1, e a regra de dependência se mantém.
  • Eventos como channel (sinais-como-channel, §4): sem callback global; cancelar é fechar o channel ou matar o processo.
  • A lib normaliza o que o SO bagunça: debounce de rajadas, recursão coalescida, rename-tracking (junta os dois meio-eventos de move do SO), ignore-globs. Política que gira fica no tier 1, não no core.