diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/src/main.rs b/src/main.rs index 2e0c82f..ff882e5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::fmt; use std::fs::File; -use std::io::{BufReader, Read, Seek}; +use std::io::{BufReader, Read, Seek, Write}; use std::path::PathBuf; use std::str::FromStr; @@ -58,6 +58,10 @@ pub struct Opt { #[structopt(long = "guilds")] guilds: bool, + /// Run the REPL. + #[structopt(long)] + repl: bool, + /// The filter expression. expression: Vec<String>, } @@ -211,9 +215,13 @@ fn run() -> Result<()> { guilds::prepare_cache(); } - let filter = build_filter(&opt)?; - - grep(&opt, &*filter)?; + if !opt.repl { + let expr_string = opt.expression.join(" "); + let filter = build_filter(&expr_string)?; + grep(&opt, &*filter)?; + } else { + repl(&opt)?; + } if opt.guilds { guilds::save_cache(); @@ -222,6 +230,22 @@ fn run() -> Result<()> { Ok(()) } +fn repl(opt: &Opt) -> Result<()> { + let stdin = std::io::stdin(); + loop { + print!("Query> "); + std::io::stdout().flush()?; + let mut line = String::new(); + stdin.read_line(&mut line)?; + let line = line.trim(); + let parsed = build_filter(&line); + match parsed { + Ok(filter) => grep(&opt, &*filter)?, + Err(err) => display_error(&err.into()), + } + } +} + /// Check if the given entry represents a log file, based on the file name. fn is_log_file(entry: &DirEntry) -> bool { entry @@ -231,12 +255,8 @@ fn is_log_file(entry: &DirEntry) -> bool { .unwrap_or(false) } -fn build_filter(opt: &Opt) -> Result<Box<dyn LogFilter>> { - // Our error needs access to the string, so we make our lives easier by just leaking it into a - // 'static lifetime. Otherwise we'd need to build this string in main() and pass it in. - // We're fine with the small memory leak, as we're only dealing with a small string in a - // short-lived program. - let expr_string = Box::leak(Box::new(opt.expression.join(" "))); +/// Small wrapper around `fexpr::parse_logfilter` to convert the returned `Err` to be `'static'. +fn build_filter(expr_string: &str) -> Result<Box<dyn LogFilter>> { if expr_string.trim().is_empty() { return Err(anyhow!("Expected a filter to be given")); } |