#![warn(missing_docs)]
mod error;
mod watch;
pub use error::Error;
pub use watch::{watch, Config, Watch};
use watch::{ARGUMENT, SHELL};
use ansi_term::Style;
use clap::Parser;
use std::env;
#[derive(clap_derive::Parser)]
#[clap(version, about, rename_all = "kebab-case")]
struct Opt {
#[structopt(short, long, default_value = ".watch.toml")]
config: String,
#[structopt(short, long)]
shell: Option<String>,
#[structopt(long, allow_hyphen_values = true)]
arg: Option<String>,
#[structopt(subcommand)]
cmd: Option<Cmd>,
}
#[derive(clap_derive::Subcommand)]
enum Cmd {
Init,
Watch,
}
const DUMMY: &str = "[[watch]]
# What does the command do?
name = \"print hello\"
# Where to look for changes?
path = \"src\"
# What to execute on change?
command = \"echo $EVENT_PATH\"
# Repeat this to watch multiple paths";
fn main() {
let opt: Opt = Parser::parse();
let bold = Style::new().bold();
match opt.cmd {
Some(Cmd::Init) => {
let config = &opt.config;
if std::fs::metadata(config).is_ok() {
println!("{} already exists, exiting", bold.paint(config))
} else if let Err(e) = std::fs::write(config, DUMMY) {
eprintln!("Error writing config file {}: {}", config, e);
} else {
println!("{} created!", bold.paint(config));
}
}
_ => {
let config = match std::fs::read(&opt.config) {
Ok(cfg) => cfg,
Err(e) => return eprintln!("Error writing config file {}: {}", &opt.config, e),
};
match toml::from_slice(&config) {
Ok(config) => {
let shell = opt.shell.or_else(|| env::var("SHELL").ok());
let arg = opt.arg.or_else(|| env::var("CARETAKER_ARG").ok());
if let Err(e) = watch(
config,
shell.as_deref().unwrap_or(SHELL),
arg.as_deref().unwrap_or(ARGUMENT),
) {
eprintln!("{}", e);
}
}
Err(e) => {
eprintln!("Unable to parse {}: {}", bold.paint(&opt.config), e);
}
};
}
}
}