watchexec/lib
Félix Saparelli 446a8d95a7 Replace event queue with a priority queue (#302)
Solves several issues, generally through delivering signals before filesystem events, preventing situations where an overwhelming amount of events makes it impossible to quit.

Does _not_ solve the problem of a queue full of lower-priority events not accepting an urgent message, but that's a rarer issue that's more complicated to overcome.

Changes the Filterer trait: adds Priority to `check_event()`

Makes some events unfilterable (Urgent priority): SIGINT, SIGTERM, and CTRL_C to the main process. These still need to be handled by `on_action` to do anything, but cannot be stopped before reaching that.
2022-06-11 06:43:11 +00:00
..
examples Replace event queue with a priority queue (#302) 2022-06-11 06:43:11 +00:00
src Replace event queue with a priority queue (#302) 2022-06-11 06:43:11 +00:00
tests Replace event queue with a priority queue (#302) 2022-06-11 06:43:11 +00:00
CITATION.cff lib: v2.0.0-pre.14 2022-04-04 11:47:36 +12:00
Cargo.toml Replace event queue with a priority queue (#302) 2022-06-11 06:43:11 +00:00
README.md Use lib pre.6 2022-01-19 00:04:41 +13:00
release.toml Use exact version reqs for prereleases 2022-03-16 16:02:29 +13:00

README.md

Crates.io page API Docs Crate license: Apache 2.0 MSRV: 1.58.0 (minor) CI status

Watchexec library

The library which powers Watchexec CLI and other tools.

  • API documentation.
  • Licensed under Apache 2.0.
  • Minimum Supported Rust Version: 1.58.0 (incurs a minor semver bump).
  • Status: in preview (2.0.0-pre.N series).

Quick start

use miette::{IntoDiagnostic, Result};
use watchexec::{
    Watchexec,
    action::{Action, Outcome},
    config::{InitConfig, RuntimeConfig},
    handler::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::<(), std::io::Error>(())
        }
    });

    let _ = we.main().await.into_diagnostic()?;
    Ok(())
}

Kitchen sink

The library also exposes a large amount 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, (more to come).

  • Finding a common prefix of a set of paths.

  • Detecting the origin(s) and types of projects.

  • Discovering project-local and global ignore files.

  • And more!

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.

Tagged filters (alpha)

This library is also the home of Watchexec's current two filtering implementations: the v1 behaviour which has proven confusing and inconsistent over the years, and an upcoming complete overhaul called "tagged filtering" which will potentially replace the legacy one.

Have a look at the docs!