watchexec/crates/lib
2023-04-06 00:48:48 +00:00
..
examples --emit-events-to (#515) 2023-03-18 21:32:24 +13:00
src Add Outcome::Race (#548) 2023-03-22 14:47:26 +13:00
tests Clippy fixes (#465) 2023-01-07 02:53:49 +13:00
Cargo.toml Update clearscreen requirement from 2.0.0 to 2.0.1 in /crates/lib (#570) 2023-04-06 00:48:48 +00:00
CHANGELOG.md release: watchexec v2.3.0 (#550) 2023-03-22 02:02:01 +00:00
README.md --emit-events-to (#515) 2023-03-18 21:32:24 +13:00
release.toml Roll lib changelog on release (#328) 2022-06-17 00:10:10 +00:00

Crates.io page API Docs Crate license: Apache 2.0 CI status

Watchexec library

The library which powers Watchexec CLI and other tools.

Quick start

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.into_diagnostic()?;
    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);
                    let _ = 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(())

            // (not normally required! ignore this when implementing)
            as std::result::Result<_, MietteStub>
        }
    });

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

// ignore this! it's stuff to make the above code get checked by cargo doc tests!
struct YourConfigFormat; impl YourConfigFormat { async fn load_from_file(_: &str) -> std::result::Result<Self, MietteStub> { Ok(Self) } fn apply(&self, _: &mut RuntimeConfig) {} } use miette::Diagnostic; use thiserror::Error; #[derive(Debug, Error, Diagnostic)] #[error("stub")] struct MietteStub;

Kitchen sink

The library also exposes a number of components which are available to make your own tool, or to make anything else you may want:

  • Command handling, to build a command with an arbitrary shell, deal with grouped and ungrouped processes the same way, and supervise a process while also listening for & acting on interventions such as sending signals.

  • Event sources: Filesystem, Signals, Keyboard, (more to come).

  • Finding a common prefix of a set of paths.

  • And more!

Filterers are split into their own crates, so they can be evolved independently:

  • The Globset filterer implements the default Watchexec filter, and mimics the pre-1.18 behaviour as much as possible.

  • The Tagged filterer is an experiment in creating a more powerful filtering solution, which can operate on every part of events, not just their paths.

  • The Ignore filterer implements ignore-file semantics, and especially supports trees of ignore files. It is used as a subfilterer in both of the main filterers above.

There are also separate, standalone crates used to build Watchexec which you can tap into:

  • ClearScreen makes clearing the terminal screen in a cross-platform way easy by default, and provides advanced options to fit your usecase.

  • Command Group augments the std and tokio Command with support for process groups, portable between Unix and Windows.

  • Event types contains the event types used by Watchexec, including the JSON format used for passing event data to child processes.

  • Signal types contains the signal types used by Watchexec.

  • Ignore files finds, parses, and interprets ignore files.

  • Project Origins finds the origin (or root) path of a project, and what kind of project it is.

Rust version (MSRV)

Due to the unpredictability of dependencies changing their MSRV, this library no longer tries to keep to a minimum supported Rust version behind stable. Instead, it is assumed that developers use the latest stable at all times.

Applications that wish to support lower-than-stable Rust (such as the Watchexec CLI does) should:

  • use a lock file
  • recommend the use of --locked when installing from source
  • provide pre-built binaries (and Binstall support) for non-distro users
  • avoid using newer features until some time has passed, to let distro users catch up
  • consider recommending that distro-Rust users switch to distro rustup where available