# tecs.io.watcher Polls loaded content and dispatches changes to reload handlers. ```teal local watcher = tecs.io.watcher if watcher.isSupported() then watcher.on( "document", function(change: watcher.Change) print("reload " .. change.path) end ) watcher.install({intervalSeconds = 0.25}) end ``` An [`Application`](/modules/Application/) with `watch` in its configuration installs the watcher and calls `tecs.runtime.poll` once per host iteration, including while the game is suspended or handling a crash. Game systems, plugins, and update functions do not poll. A headless program without an application owns the manual loop shown on `poll`. The watcher scans only paths recorded by `tecs.io.files.read` and the asset loaders. It waits for a changed file's size and modification time to settle before dispatching it. Empty, missing, and directory paths do not dispatch. Handlers run between frames. A handler error reaches the log and does not replace the current resource. Release builds report `isSupported() == false` and do not poll. ## Module contents ### Types | Type | Kind | Description | | --- | --- | --- | | [`Change`](/modules/io/watcher/#tecs.io.watcher.Change) | record | Change describes one settled content change. | | [`ChangeHandler`](/modules/io/watcher/#tecs.io.watcher.ChangeHandler) | type | ChangeHandler receives one settled change. | | [`Config`](/modules/io/watcher/#tecs.io.watcher.Config) | record | Config controls polling frequency, settling and path scope. | ### Functions | Function | Kind | Description | | --- | --- | --- | | [`dispatched`](/modules/io/watcher/#tecs.io.watcher.dispatched) | Static | Returns the changes dispatched since install. | | [`install`](/modules/io/watcher/#tecs.io.watcher.install) | Static | Starts watching loaded content. | | [`isInstalled`](/modules/io/watcher/#tecs.io.watcher.isInstalled) | Static | Returns whether the watcher is running. | | [`isSupported`](/modules/io/watcher/#tecs.io.watcher.isSupported) | Static | Returns whether this build supports hot reload. | | [`kinds`](/modules/io/watcher/#tecs.io.watcher.kinds) | Static | Returns registered content kinds in sorted order. | | [`on`](/modules/io/watcher/#tecs.io.watcher.on) | Static | Registers the handler for a content kind. | | [`poll`](/modules/io/watcher/#tecs.io.watcher.poll) | Static | Advances a manually driven headless watcher. | | [`scan`](/modules/io/watcher/#tecs.io.watcher.scan) | Static | Looks at every watched path once, whatever the interval says. | | [`uninstall`](/modules/io/watcher/#tecs.io.watcher.uninstall) | Static | Stops watching and forgets every path's state. | | [`unsettled`](/modules/io/watcher/#tecs.io.watcher.unsettled) | Static | Returns unsettled changed paths in sorted order. | | [`watching`](/modules/io/watcher/#tecs.io.watcher.watching) | Static | Returns watched paths in sorted order. | ## Types ### tecs.io.watcher.Change record `Change` describes one settled content change. ```teal record tecs.io.watcher.Change path: string kind: string end ``` #### tecs.io.watcher.Change.path field Read-only. The watcher sets `path` to the changed loaded path before it calls the handler. ```teal tecs.io.watcher.Change.path: string ``` #### tecs.io.watcher.Change.kind field Read-only. The watcher sets `kind` to the content kind recorded by the original load. Built-in loaders use `"image"`, `"sound"`, `"font"`, `"shader"` or `"document"`; a custom loader supplies its own kind to `tecs.io.files.read`. ```teal tecs.io.watcher.Change.kind: string ``` ### tecs.io.watcher.ChangeHandler type `ChangeHandler` receives one settled change. ```teal type tecs.io.watcher.ChangeHandler = function(Change) ``` ### tecs.io.watcher.Config record `Config` controls polling frequency, settling and path scope. ```teal record tecs.io.watcher.Config intervalSeconds: number settle: integer root: string end ``` #### tecs.io.watcher.Config.intervalSeconds field Caller-writable. Sets the delay between automatic polls in seconds. It defaults to 0.5. Direct calls to `scan` ignore this delay. ```teal tecs.io.watcher.Config.intervalSeconds: number ``` #### tecs.io.watcher.Config.settle field Caller-writable. Requires this many additional matching scans after a change is first observed. It defaults to 1, so one scan observes the change and the next confirms it. Zero dispatches immediately. ```teal tecs.io.watcher.Config.settle: integer ``` #### tecs.io.watcher.Config.root field Caller-writable. Limits watched paths to this root. It defaults to the content root. ```teal tecs.io.watcher.Config.root: string ``` ## Functions ### tecs.io.watcher.dispatched Static Returns the changes dispatched since `install`. ```teal function tecs.io.watcher.dispatched(): integer ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `integer` | Returns the cumulative handler count. | ### tecs.io.watcher.install Static Starts watching loaded content. The watcher records the current state of loaded paths and dispatches only later changes. It raises when the build lacks hot-reload support. ```teal function tecs.io.watcher.install(config: watcher.Config) ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `config` | [`watcher.Config`](/modules/io/watcher/#tecs.io.watcher.Config) | The caller supplies polling options or omits them for the documented defaults. | #### Returns None. ### tecs.io.watcher.isInstalled Static Returns whether the watcher is running. ```teal function tecs.io.watcher.isInstalled(): boolean ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `boolean` | Returns true after `install` and before `uninstall`. | ### tecs.io.watcher.isSupported Static Returns whether this build supports hot reload. ```teal function tecs.io.watcher.isSupported(): boolean ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `boolean` | Returns true when this build can install the watcher. | ### tecs.io.watcher.kinds Static Returns registered content kinds in sorted order. ```teal function tecs.io.watcher.kinds(): {string} ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `{string}` | Returns a fresh caller-owned list. | ### tecs.io.watcher.on Static Registers the handler for a content kind. Re-registering a kind replaces its handler. Nil removes it. ```teal function tecs.io.watcher.on( kind: string, handler: watcher.ChangeHandler ) ``` #### Arguments | Name | Type | Description | | --- | --- | --- | | `kind` | `string` | The caller supplies the content kind to register. | | `handler` | [`watcher.ChangeHandler`](/modules/io/watcher/#tecs.io.watcher.ChangeHandler) | The caller supplies the replacement handler or nil to remove the current one. | #### Returns None. ### tecs.io.watcher.poll Static Advances a manually driven headless watcher. [`runtime.poll`](/modules/runtime/#tecs.runtime.poll) calls this while the watcher is installed. Game systems, plugins, and update functions must not call it. A second call in the same loop can distort `intervalSeconds` and the number of matching observations counted by `Config.settle`. A headless program normally calls `tecs.runtime.poll` once per loop after `install`. Call this narrower operation when a test or tool deliberately drives only the watcher. It returns immediately until `intervalSeconds` has elapsed, then scans only content already recorded by file or asset loading. It performs no sleeping. ```teal function tecs.io.watcher.poll(): integer ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `integer` | Returns how many handlers ran during this call. | #### Examples ```teal local watcher = tecs.io.watcher local function runHeadlessWatcher(keepRunning: function(): boolean) watcher.install({intervalSeconds = 0.25}) while keepRunning() do watcher.poll() end watcher.uninstall() end ``` ### tecs.io.watcher.scan Static Looks at every watched path once, whatever the interval says. Call this directly when a headless tool or test controls poll timing. ```teal function tecs.io.watcher.scan(): integer ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `integer` | Returns how many handlers ran, or zero when no watcher runs. | ### tecs.io.watcher.uninstall Static Stops watching and forgets every path's state. Registered handlers remain available for a later installation. ```teal function tecs.io.watcher.uninstall() ``` #### Arguments None. #### Returns None. ### tecs.io.watcher.unsettled Static Returns unsettled changed paths in sorted order. ```teal function tecs.io.watcher.unsettled(): {string} ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `{string}` | Returns a fresh caller-owned list. | ### tecs.io.watcher.watching Static Returns watched paths in sorted order. ```teal function tecs.io.watcher.watching(): {string} ``` #### Arguments None. #### Returns | Type | Description | | --- | --- | | `{string}` | Returns a fresh caller-owned list. |