logo

Crate watchexec[][src]

Expand description

Watchexec: a library for utilities and programs which respond to events; file changes, human interaction, and more.

Also see the CLI tool: https://watchexec.github.io/

This library is powered by Tokio.

The main way to use this crate involves constructing a Watchexec around an InitConfig and a RuntimeConfig, then running it. Handlers are used to hook into watchexec at various points. The runtime config can be changed at any time with the Watchexec::reconfigure() method.

It’s recommended to use the miette erroring library in applications, but all errors implement std::error::Error so your favourite error handling library can of course be used.

use miette::{IntoDiagnostic, Result};
use watchexec::{
    Watchexec,
    action::{Action, Outcome},
    config::{InitConfig, RuntimeConfig},
    handler::{Handler as _, PrintDebug},
};

#[tokio::main]
async fn main() -> Result<()> {
    let mut init = InitConfig::default();
    init.on_error(PrintDebug(std::io::stderr()));

    let mut runtime = RuntimeConfig::default();
    runtime.pathset(["watchexec.conf"]);

    let conf = YourConfigFormat::load_from_file("watchexec.conf").await?;
    conf.apply(&mut runtime);

    let we = Watchexec::new(init, runtime.clone())?;
    let w = we.clone();

    let c = runtime.clone();
    runtime.on_action(move |action: Action| {
        let mut c = c.clone();
        let w = w.clone();
        async move {
            for event in action.events.iter() {
                if event.paths().any(|(p, _)| p.ends_with("/watchexec.conf")) {
                    let conf = YourConfigFormat::load_from_file("watchexec.conf").await?;

                    conf.apply(&mut c);
                    w.reconfigure(c.clone());
                    // tada! self-reconfiguring watchexec on config file change!

                    break;
                }
            }

            action.outcome(Outcome::if_running(
                Outcome::DoNothing,
                Outcome::both(Outcome::Clear, Outcome::Start),
            ));

            Ok(())
        }
    });

    we.main().await.into_diagnostic()?;
    Ok(())
}

Alternatively, one can use the modules exposed by the crate and the external crates such as ClearScreen and Command Group to build something more advanced, at the cost of reimplementing the glue code. See the examples folder for some basic/demo tools written with the individual modules.

Note that the library generates a lot of debug messaging with tracing. You should not enable printing even error log messages for this crate unless it’s for debugging. Instead, make use of the InitConfig::on_error() method to define a handler for errors occurring at runtime that are meant for you to handle (by printing out or otherwise).

This crate does not itself use unsafe. However, it depends on a number of libraries which do, most because they interact with the operating system.

Modules

Processor responsible for receiving events, filtering them, and scheduling actions in response.

Command construction, configuration, and tracking.

Configuration and builders for crate::Watchexec.

Error types for critical, runtime, and specialised errors.

Synthetic event type, derived from inputs, triggers actions.

The Filterer trait, two implementations, and some helper functions.

Event source for changes to files and directories.

Trait and implementations for hook handlers.

Find ignore files, like .gitignore, .ignore, and others.

Utilities for paths and sets of paths.

Detect project type and origin.

Signal handling.

Structs

The main watchexec runtime.