watch
file-watching ergonômico (sobre a primitiva do fs)
use watchA camada ergonômica de observação de filesystem, sobre a primitiva tier 0
fs.watch_raw(o wrapper fino deinotify/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 numChannel, não num callback global.
A primitiva (no core fs, tier 0): referência
Seção intitulada “A primitiva (no core fs, tier 0): referência”// 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 reportaA 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 caminhofn 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) }}Curadoria
Seção intitulada “Curadoria”- Primitiva no core, serviço no tier 1: o mesmo corte do
runtime(a primitivatraceé core, o observer é tooling) e daMemorySource(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.