add support for --grep

This commit is contained in:
Abraham Toriz 2021-07-07 10:49:29 -05:00
parent 1bcf09c1f9
commit 91b98ed6e5
No known key found for this signature in database
GPG Key ID: D5B4A746DB5DD42A
5 changed files with 56 additions and 13 deletions

View File

@ -6,6 +6,7 @@ use clap::ArgMatches;
use chrono::{DateTime, Utc, Local, LocalResult, TimeZone};
use terminal_size::{Width, terminal_size};
use ansi_term::Color::Yellow;
use regex::Regex;
use crate::error::{Result, Error};
use crate::database::{Database, DBVersion};
@ -13,6 +14,7 @@ use crate::formatters::Formatter;
use crate::config::Config;
use crate::timeparse::parse_time;
use crate::models::Entry;
use crate::regex::parse_regex;
use super::Command;
@ -76,14 +78,14 @@ impl FromStr for Sheet {
pub fn entries_for_display<D, O, E>(
start: Option<DateTime<Utc>>, end: Option<DateTime<Utc>>,
sheet: Option<Sheet>, db: &mut D, out: &mut O, err: &mut E,
format: Formatter, ids: bool,
format: Formatter, ids: bool, grep: Option<Regex>,
) -> Result<()>
where
D: Database,
O: Write,
E: Write,
{
let entries = match sheet {
let mut entries = match sheet {
Some(Sheet::All) => db.entries_all_visible(start, end)?,
Some(Sheet::Full) => db.entries_full(start, end)?,
Some(Sheet::Sheet(name)) => db.entries_by_sheet(&name, start, end)?,
@ -94,6 +96,10 @@ where
}
};
if let Some(re) = grep {
entries.retain(|e| re.is_match(e.note.as_ref().unwrap_or(&String::new())));
}
let (entries, needs_warning) = if let DBVersion::Timetrap = db.version()? {
// this indicates that times in the database are specified in the
// local time and need to be converted to utc before displaying
@ -133,7 +139,7 @@ pub struct Args {
start: Option<DateTime<Utc>>,
end: Option<DateTime<Utc>>,
format: Formatter,
grep: Option<String>,
grep: Option<Regex>,
sheet: Option<Sheet>,
}
@ -146,7 +152,7 @@ impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
start: matches.value_of("start").map(|s| parse_time(s)).transpose()?,
end: matches.value_of("end").map(|s| parse_time(s)).transpose()?,
format: matches.value_of("format").unwrap().parse()?,
grep: matches.value_of("grep").map(|s| s.into()),
grep: matches.value_of("grep").map(parse_regex).transpose()?,
sheet: matches.value_of("sheet").map(|s| s.parse()).transpose()?,
})
}
@ -163,7 +169,7 @@ impl<'a> Command<'a> for DisplayCommand {
O: Write,
E: Write,
{
entries_for_display(args.start, args.end, args.sheet, db, out, err, args.format, args.ids)
entries_for_display(args.start, args.end, args.sheet, db, out, err, args.format, args.ids, args.grep)
}
}
@ -171,6 +177,7 @@ impl<'a> Command<'a> for DisplayCommand {
mod tests {
use chrono::TimeZone;
use ansi_term::Color::Yellow;
use pretty_assertions::assert_eq;
use crate::database::SqliteDatabase;
use crate::test_utils::PrettyString;
@ -239,14 +246,37 @@ mod tests {
}
#[test]
#[ignore]
fn filter_by_end() {
unimplemented!()
}
#[test]
#[ignore]
fn filter_by_start_and_end() {
unimplemented!()
}
#[test]
fn filter_by_match() {
let mut db = SqliteDatabase::from_memory().unwrap();
let mut out = Vec::new();
let mut err = Vec::new();
db.init().unwrap();
db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 0, 0), None, Some("hola".into()), "default".into()).unwrap();
db.entry_insert(Utc.ymd(2021, 6, 30).and_hms(10, 10, 0), None, Some("adios".into()), "default".into()).unwrap();
entries_for_display(None, None, None, &mut db, &mut out, &mut err, Formatter::Csv, true, Some("io".parse().unwrap())).unwrap();
assert_eq!(PrettyString(&String::from_utf8_lossy(&out)), PrettyString("id,start,end,note,sheet
2,2021-06-30T10:10:00Z,,adios,default
"));
assert_eq!(
String::from_utf8_lossy(&err),
String::new(),
);
}
}

View File

@ -3,12 +3,14 @@ use std::io::Write;
use clap::ArgMatches;
use chrono::{DateTime, Utc, Local};
use regex::Regex;
use crate::error;
use crate::error::{Result, Error};
use crate::database::Database;
use crate::formatters::Formatter;
use crate::config::Config;
use crate::timeparse::parse_time;
use crate::regex::parse_regex;
use super::{Command, display::{Sheet, entries_for_display}};
@ -17,19 +19,19 @@ pub struct Args {
ids: bool,
end: Option<DateTime<Utc>>,
format: Formatter,
grep: Option<String>,
grep: Option<Regex>,
sheet: Option<Sheet>,
}
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
type Error = error::Error;
type Error = Error;
fn try_from(matches: &'a ArgMatches) -> error::Result<Args> {
fn try_from(matches: &'a ArgMatches) -> Result<Args> {
Ok(Args {
ids: matches.is_present("ids"),
end: matches.value_of("end").map(|s| parse_time(s)).transpose()?,
format: matches.value_of("format").unwrap().parse()?,
grep: matches.value_of("grep").map(|s| s.into()),
grep: matches.value_of("grep").map(parse_regex).transpose()?,
sheet: matches.value_of("sheet").map(|s| s.parse()).transpose()?,
})
}
@ -40,7 +42,7 @@ pub struct TodayCommand { }
impl<'a> Command<'a> for TodayCommand {
type Args = Args;
fn handle<D, O, E>(args: Self::Args, db: &mut D, out: &mut O, err: &mut E, _config: &Config) -> error::Result<()>
fn handle<D, O, E>(args: Self::Args, db: &mut D, out: &mut O, err: &mut E, _config: &Config) -> Result<()>
where
D: Database,
O: Write,
@ -48,6 +50,6 @@ impl<'a> Command<'a> for TodayCommand {
{
let start = Some(Local::now().date().and_hms(0, 0, 0).with_timezone(&Utc));
entries_for_display(start, args.end, args.sheet, db, out, err, args.format, args.ids)
entries_for_display(start, args.end, args.sheet, db, out, err, args.format, args.ids, args.grep)
}
}

View File

@ -47,7 +47,10 @@ pub enum Error {
orig: String,
t1: NaiveDateTime,
t2: NaiveDateTime,
}
},
#[error("The provided regex '{0}' could not be parsed")]
InvalidRegex(String),
}
pub type Result<T> = result::Result<T, Error>;

View File

@ -9,6 +9,7 @@ pub mod formatters;
pub mod error;
pub mod models;
pub mod timeparse;
pub mod regex;
#[cfg(test)]
pub mod test_utils;

7
src/regex.rs Normal file
View File

@ -0,0 +1,7 @@
use regex::Regex;
use crate::error::{Error, Result};
pub fn parse_regex(s: &str) -> Result<Regex> {
Regex::new(s).map_err(|_| Error::InvalidRegex(s.into()))
}