mirror of
https://github.com/watchexec/watchexec.git
synced 2024-11-16 09:08:37 +01:00
Add read filter
This commit is contained in:
parent
e82a7dbc14
commit
309b7583bd
2 changed files with 62 additions and 3 deletions
|
@ -802,8 +802,11 @@ pub struct Args {
|
|||
///
|
||||
/// - 'path | metadata' returns file metadata or null if the file does not exist.
|
||||
///
|
||||
/// - 'path | read' and 'path read(bytes)' return a string containing the file at path, or
|
||||
/// the first n bytes of it. Obviously care should be taken not to read large files.
|
||||
/// - 'path | filesize' returns the size of the file at path, or null if it does not exist.
|
||||
///
|
||||
/// - 'path | read(bytes)' returns a string containing the first n bytes of the file at path.
|
||||
/// If the file is smaller than n bytes, the whole file is returned. There is no filter to
|
||||
/// read the whole file at once to encourage limiting the amount of data read and processed.
|
||||
///
|
||||
/// - 'string | hash', and 'path | hashfile' return the hash of the string or file at path.
|
||||
/// No guarantee is made about the algorithm used: treat it as an opaque value.
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
use std::{iter::once, sync::Arc};
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufReader, Read},
|
||||
iter::once,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use dashmap::DashMap;
|
||||
use jaq_core::{CustomFilter, Definitions, Error, Val};
|
||||
|
@ -43,6 +48,17 @@ macro_rules! string_arg {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! int_arg {
|
||||
($args:expr, $n:expr, $ctx:expr, $val:expr) => {
|
||||
match $args[$n].run(($ctx.clone(), $val.clone())).next() {
|
||||
Some(Ok(Val::Int(v))) => Ok(v as _),
|
||||
Some(Ok(val)) => custom_err(format!("expected int 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() {
|
||||
|
@ -170,5 +186,45 @@ pub fn load_watchexec_defs(defs: &mut Definitions) -> miette::Result<()> {
|
|||
}),
|
||||
);
|
||||
|
||||
trace!("jaq: add read filter");
|
||||
defs.insert_custom(
|
||||
"read",
|
||||
CustomFilter::new(1, {
|
||||
move |args, (ctx, val)| {
|
||||
let path = match &val {
|
||||
Val::Str(v) => v.to_string(),
|
||||
_ => return_err!(custom_err("expected string (path) but got {val:?}")),
|
||||
};
|
||||
|
||||
let bytes = match int_arg!(args, 0, ctx, &val) {
|
||||
Ok(v) => v,
|
||||
Err(e) => return_err!(Err(e)),
|
||||
};
|
||||
|
||||
Box::new(once(Ok(match File::open(&path) {
|
||||
Ok(file) => {
|
||||
let buf_reader = BufReader::new(file);
|
||||
let mut limited = buf_reader.take(bytes);
|
||||
let mut buffer = String::with_capacity(bytes as _);
|
||||
match limited.read_to_string(&mut buffer) {
|
||||
Ok(read) => {
|
||||
debug!("jaq: read {read} bytes from {path:?}");
|
||||
Val::Str(buffer.into())
|
||||
}
|
||||
Err(err) => {
|
||||
error!("jaq: failed to read from {path:?}: {err:?}");
|
||||
Val::Null
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
error!("jaq: failed to open file {path:?}: {err:?}");
|
||||
Val::Null
|
||||
}
|
||||
})))
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue