Add log, stdout, stderr

This commit is contained in:
Félix Saparelli 2023-04-08 19:47:56 +12:00
parent 497d2db588
commit b641773473
No known key found for this signature in database
3 changed files with 129 additions and 25 deletions

View file

@ -20,6 +20,7 @@ use watchexec_filterer_globset::GlobsetFilterer;
use crate::args::{Args, FsEvent}; use crate::args::{Args, FsEvent};
mod dirs; mod dirs;
mod proglib;
mod progs; mod progs;
/// A custom filterer that combines the library's Globset filterer and a switch for --no-meta /// A custom filterer that combines the library's Globset filterer and a switch for --no-meta

View file

@ -0,0 +1,124 @@
use std::iter::once;
use jaq_core::{CustomFilter, Definitions, Error, Val};
use miette::miette;
use tracing::{debug, error, info, trace, warn};
pub fn load_std_defs() -> miette::Result<Definitions> {
debug!("loading jaq core library");
let mut defs = Definitions::core();
debug!("loading jaq standard library");
let mut errs = Vec::new();
jaq_std::std()
.into_iter()
.for_each(|def| defs.insert(def, &mut errs));
if !errs.is_empty() {
return Err(miette!("failed to load jaq standard library: {:?}", errs));
}
Ok(defs)
}
macro_rules! return_err {
($err:expr) => {
return Box::new(once($err))
};
}
#[inline]
fn custom_err<T>(err: impl Into<String>) -> Result<T, Error> {
Err(Error::Custom(err.into()))
}
macro_rules! string_arg {
($args:expr, $n:expr, $ctx:expr, $val:expr) => {
match $args[$n].run(($ctx.clone(), $val.clone())).next() {
Some(Ok(Val::Str(v))) => Ok(v.to_string()),
Some(Ok(val)) => custom_err(format!("expected string but got {val:?}")),
Some(Err(e)) => Err(e),
None => custom_err("value expected but none found"),
}
};
}
macro_rules! log_action {
($level:expr, $val:expr) => {
match $level.to_ascii_lowercase().as_str() {
"trace" => trace!("jaq: {}", $val),
"debug" => debug!("jaq: {}", $val),
"info" => info!("jaq: {}", $val),
"warn" => warn!("jaq: {}", $val),
"error" => error!("jaq: {}", $val),
_ => return_err!(custom_err("invalid log level")),
}
};
}
pub fn load_watchexec_defs(defs: &mut Definitions) -> miette::Result<()> {
debug!("loading jaq watchexec library");
trace!("jaq: add log filter");
defs.insert_custom(
"log",
CustomFilter::with_update(
1,
|args, (ctx, val)| {
let level = match string_arg!(args, 0, ctx, val) {
Ok(v) => v,
Err(e) => return_err!(Err(e)),
};
log_action!(level, val);
// passthrough
Box::new(once(Ok(val)))
},
|args, (ctx, val), _| {
let level = match string_arg!(args, 0, ctx, val) {
Ok(v) => v,
Err(e) => return_err!(Err(e)),
};
log_action!(level, val);
// passthrough
Box::new(once(Ok(val)))
},
),
);
trace!("jaq: add stdout filter");
defs.insert_custom(
"stdout",
CustomFilter::with_update(
0,
|_, (_, val)| {
println!("{}", val);
Box::new(once(Ok(val)))
},
|_, (_, val), _| {
println!("{}", val);
Box::new(once(Ok(val)))
},
),
);
trace!("jaq: add stderr filter");
defs.insert_custom(
"stderr",
CustomFilter::with_update(
0,
|_, (_, val)| {
eprintln!("{}", val);
Box::new(once(Ok(val)))
},
|_, (_, val), _| {
eprintln!("{}", val);
Box::new(once(Ok(val)))
},
),
);
Ok(())
}

View file

@ -1,4 +1,4 @@
use std::{iter, marker::PhantomData}; use std::{iter::once, marker::PhantomData};
use jaq_core::{ use jaq_core::{
parse::{self, filter::Filter, Def}, parse::{self, filter::Filter, Def},
@ -72,8 +72,8 @@ impl FilterProgs {
let (requester, mut receiver) = Requester::<Event, bool>::new(BUFFER); let (requester, mut receiver) = Requester::<Event, bool>::new(BUFFER);
let task = let task =
spawn_blocking(move || { spawn_blocking(move || {
let mut defs = load_std_defs()?; let mut defs = super::proglib::load_std_defs()?;
load_watchexec_defs(&mut defs)?; super::proglib::load_watchexec_defs(&mut defs)?;
load_user_progs(&mut defs, &progs)?; load_user_progs(&mut defs, &progs)?;
'chan: while let Some((event, sender)) = receiver.blocking_recv() { 'chan: while let Some((event, sender)) = receiver.blocking_recv() {
@ -97,7 +97,7 @@ impl FilterProgs {
continue; continue;
} }
let inputs = RcIter::new(iter::once(Ok(val.clone()))); let inputs = RcIter::new(once(Ok(val.clone())));
let ctx = Ctx::new(Vec::new(), &inputs); let ctx = Ctx::new(Vec::new(), &inputs);
let mut results = filter.run(ctx, val.clone()); let mut results = filter.run(ctx, val.clone());
if let Some(res) = results.next() { if let Some(res) = results.next() {
@ -154,27 +154,6 @@ impl FilterProgs {
} }
} }
fn load_std_defs() -> miette::Result<Definitions> {
debug!("loading jaq core library");
let mut defs = Definitions::core();
debug!("loading jaq standard library");
let mut errs = Vec::new();
jaq_std::std()
.into_iter()
.for_each(|def| defs.insert(def, &mut errs));
if !errs.is_empty() {
return Err(miette!("failed to load jaq standard library: {:?}", errs));
}
Ok(defs)
}
fn load_watchexec_defs(defs: &mut Definitions) -> miette::Result<()> {
debug!("loading jaq watchexec library");
Ok(())
}
fn load_user_progs(all_defs: &mut Definitions, progs: &[String]) -> miette::Result<()> { fn load_user_progs(all_defs: &mut Definitions, progs: &[String]) -> miette::Result<()> {
debug!("loading jaq programs"); debug!("loading jaq programs");
for (n, prog) in progs.iter().enumerate() { for (n, prog) in progs.iter().enumerate() {