diff options
author | Daniel <kingdread@gmx.de> | 2020-04-21 14:23:50 +0200 |
---|---|---|
committer | Daniel <kingdread@gmx.de> | 2020-04-21 14:23:50 +0200 |
commit | 0a27adbc0bf3bbbf87fea9e55c00c38f61d55058 (patch) | |
tree | b93fa88f0097c49fd7cc89bae257dfb63724bb56 | |
parent | 0ad7a333dc2b45f0ba658ea455284d086294a088 (diff) | |
download | raidgrep-0a27adbc0bf3bbbf87fea9e55c00c38f61d55058.tar.gz raidgrep-0a27adbc0bf3bbbf87fea9e55c00c38f61d55058.tar.bz2 raidgrep-0a27adbc0bf3bbbf87fea9e55c00c38f61d55058.zip |
add a small repl
-rw-r--r-- | src/fexpr/mod.rs | 6 | ||||
-rw-r--r-- | src/main.rs | 40 |
2 files changed, 33 insertions, 13 deletions
diff --git a/src/fexpr/mod.rs b/src/fexpr/mod.rs index 5754d94..5610aba 100644 --- a/src/fexpr/mod.rs +++ b/src/fexpr/mod.rs @@ -46,9 +46,9 @@ pub enum FErrorKind { } /// Shortcut to create a new parser and parse the given input. -pub fn parse_logfilter( - input: &str, -) -> Result<Box<dyn filters::log::LogFilter>, ParseError<usize, Token, FError>> { +pub fn parse_logfilter<'a>( + input: &'a str, +) -> Result<Box<dyn filters::log::LogFilter>, ParseError<usize, Token<'a>, FError>> { grammar::LogFilterParser::new().parse(input) } 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")); } |