aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs40
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"));
}