2021-05-08 17:39:13 +02:00
|
|
|
[![Crates.io page](https://badgen.net/crates/v/watchexec)](https://crates.io/crates/watchexec)
|
|
|
|
[![API Docs](https://docs.rs/watchexec/badge.svg)][docs]
|
|
|
|
[![Crate license: Apache 2.0](https://badgen.net/badge/license/Apache%202.0)][license]
|
2022-09-02 11:12:47 +02:00
|
|
|
![MSRV: 1.60.0 (minor)](https://badgen.net/badge/MSRV/1.60.0%20%28minor%29/0b7261)
|
2021-05-08 17:39:13 +02:00
|
|
|
[![CI status](https://github.com/watchexec/watchexec/actions/workflows/check.yml/badge.svg)](https://github.com/watchexec/watchexec/actions/workflows/check.yml)
|
|
|
|
|
|
|
|
# Watchexec library
|
|
|
|
|
2021-06-28 15:15:00 +02:00
|
|
|
_The library which powers [Watchexec CLI](https://watchexec.github.io) and other tools._
|
2021-05-08 17:39:13 +02:00
|
|
|
|
|
|
|
- **[API documentation][docs]**.
|
|
|
|
- Licensed under [Apache 2.0][license].
|
2022-09-02 11:12:47 +02:00
|
|
|
- Minimum Supported Rust Version: 1.60.0 (incurs a minor semver bump).
|
2022-06-15 05:25:05 +02:00
|
|
|
- Status: maintained.
|
2021-05-08 17:39:13 +02:00
|
|
|
|
2022-06-15 05:25:05 +02:00
|
|
|
[docs]: https://docs.rs/watchexec
|
|
|
|
[license]: ../../LICENSE
|
2021-05-08 17:39:13 +02:00
|
|
|
|
|
|
|
|
|
|
|
## Quick start
|
|
|
|
|
2022-06-17 01:18:31 +02:00
|
|
|
```rust ,no_run
|
2021-10-16 16:37:12 +02:00
|
|
|
use miette::{IntoDiagnostic, Result};
|
2021-05-08 17:39:13 +02:00
|
|
|
use watchexec::{
|
2021-10-16 16:37:12 +02:00
|
|
|
Watchexec,
|
|
|
|
action::{Action, Outcome},
|
|
|
|
config::{InitConfig, RuntimeConfig},
|
2022-06-17 01:18:31 +02:00
|
|
|
handler::{Handler as _, PrintDebug},
|
2021-05-08 17:39:13 +02:00
|
|
|
};
|
|
|
|
|
2021-10-16 16:37:12 +02:00
|
|
|
#[tokio::main]
|
|
|
|
async fn main() -> Result<()> {
|
|
|
|
let mut init = InitConfig::default();
|
|
|
|
init.on_error(PrintDebug(std::io::stderr()));
|
2021-05-08 17:39:13 +02:00
|
|
|
|
2021-10-16 16:37:12 +02:00
|
|
|
let mut runtime = RuntimeConfig::default();
|
|
|
|
runtime.pathset(["watchexec.conf"]);
|
|
|
|
|
2022-01-18 10:38:15 +01:00
|
|
|
let conf = YourConfigFormat::load_from_file("watchexec.conf").await.into_diagnostic()?;
|
2021-10-16 16:37:12 +02:00
|
|
|
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 {
|
2022-01-18 10:38:15 +01:00
|
|
|
for event in action.events.iter() {
|
2021-10-16 16:37:12 +02:00
|
|
|
if event.paths().any(|(p, _)| p.ends_with("/watchexec.conf")) {
|
|
|
|
let conf = YourConfigFormat::load_from_file("watchexec.conf").await?;
|
|
|
|
|
|
|
|
conf.apply(&mut c);
|
2022-01-18 10:38:15 +01:00
|
|
|
let _ = w.reconfigure(c.clone());
|
2021-10-16 16:37:12 +02:00
|
|
|
// tada! self-reconfiguring watchexec on config file change!
|
2021-05-08 17:39:13 +02:00
|
|
|
|
2021-10-16 16:37:12 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-05-08 17:39:13 +02:00
|
|
|
|
2021-10-16 16:37:12 +02:00
|
|
|
action.outcome(Outcome::if_running(
|
|
|
|
Outcome::DoNothing,
|
|
|
|
Outcome::both(Outcome::Clear, Outcome::Start),
|
|
|
|
));
|
2021-05-08 17:39:13 +02:00
|
|
|
|
2022-06-17 01:18:31 +02:00
|
|
|
Ok(())
|
|
|
|
|
|
|
|
// (not normally required! ignore this when implementing)
|
|
|
|
as std::result::Result<_, MietteStub>
|
2021-10-16 16:37:12 +02:00
|
|
|
}
|
|
|
|
});
|
2021-05-08 17:39:13 +02:00
|
|
|
|
2022-06-17 01:18:31 +02:00
|
|
|
we.reconfigure(runtime);
|
|
|
|
we.main().await.into_diagnostic()?;
|
2021-10-16 16:37:12 +02:00
|
|
|
Ok(())
|
2021-05-08 17:39:13 +02:00
|
|
|
}
|
2022-06-17 01:18:31 +02:00
|
|
|
|
|
|
|
// 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;
|
2021-05-08 17:39:13 +02:00
|
|
|
```
|
2021-10-16 16:37:12 +02:00
|
|
|
|
|
|
|
|
|
|
|
## Kitchen sink
|
|
|
|
|
2022-06-15 05:25:05 +02:00
|
|
|
The library also exposes a number of components which are available to make your own tool, or to
|
|
|
|
make anything else you may want:
|
2021-10-16 16:37:12 +02:00
|
|
|
|
2022-01-18 12:02:34 +01:00
|
|
|
- **[Command handling](https://docs.rs/watchexec/2.0.0-pre.6/watchexec/command/index.html)**, to
|
2021-10-16 16:37:12 +02:00
|
|
|
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.
|
|
|
|
|
2022-01-18 12:02:34 +01:00
|
|
|
- **Event sources**: [Filesystem](https://docs.rs/watchexec/2.0.0-pre.6/watchexec/fs/index.html),
|
|
|
|
[Signals](https://docs.rs/watchexec/2.0.0-pre.6/watchexec/signal/source/index.html), (more to come).
|
2021-10-16 16:37:12 +02:00
|
|
|
|
2022-01-18 12:02:34 +01:00
|
|
|
- Finding **[a common prefix](https://docs.rs/watchexec/2.0.0-pre.6/watchexec/paths/fn.common_prefix.html)**
|
2021-10-16 16:37:12 +02:00
|
|
|
of a set of paths.
|
|
|
|
|
2022-06-15 05:25:05 +02:00
|
|
|
- And [more][docs]!
|
2021-10-16 16:37:12 +02:00
|
|
|
|
2022-06-15 05:25:05 +02:00
|
|
|
Filterers are split into their own crates, so they can be evolved independently:
|
2022-01-18 10:38:15 +01:00
|
|
|
|
2022-06-15 05:25:05 +02:00
|
|
|
- The **[Globset](https://docs.rs/watchexec-filterer-globset) filterer** implements the default
|
|
|
|
Watchexec filter, and mimics the pre-1.18 behaviour as much as possible.
|
|
|
|
|
|
|
|
- The **[Tagged](https://docs.rs/watchexec-filterer-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](https://docs.rs/watchexec-filterer-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.
|
2021-10-16 16:37:12 +02:00
|
|
|
|
|
|
|
There are also separate, standalone crates used to build Watchexec which you can tap into:
|
|
|
|
|
|
|
|
- **[ClearScreen](https://docs.rs/clearscreen)** makes clearing the terminal screen in a
|
|
|
|
cross-platform way easy by default, and provides advanced options to fit your usecase.
|
|
|
|
|
|
|
|
- **[Command Group](https://docs.rs/command-group)** augments the std and tokio `Command` with
|
|
|
|
support for process groups, portable between Unix and Windows.
|
|
|
|
|
2022-06-15 05:25:05 +02:00
|
|
|
- **[Ignore files](https://docs.rs/ignore-files)** finds, parses, and interprets ignore files.
|
2021-10-16 16:37:12 +02:00
|
|
|
|
2022-06-15 05:25:05 +02:00
|
|
|
- **[Project Origins](https://docs.rs/project-origins)** finds the origin (or root) path of a
|
|
|
|
project, and what kind of project it is.
|