diff --git a/src/bin/ent/main.rs b/src/bin/ent/main.rs index 2a8f1f4..2892d6a 100644 --- a/src/bin/ent/main.rs +++ b/src/bin/ent/main.rs @@ -71,18 +71,30 @@ fn handle_command(args: &Args, issues_dir: &std::path::Path) -> anyhow::Result<( Commands::List { filter } => { let issues = entomologist::issues::Issues::new_from_dir(std::path::Path::new(issues_dir))?; - let filter = entomologist::parse_filter(filter)?; + let filter = entomologist::Filter::new_from_str(filter)?; let mut uuids_by_state = std::collections::HashMap::< entomologist::issue::State, Vec<&entomologist::issue::IssueHandle>, >::new(); for (uuid, issue) in issues.issues.iter() { - if filter.include_states.contains(&issue.state) { - uuids_by_state - .entry(issue.state.clone()) - .or_default() - .push(uuid); + if !filter.include_states.contains(&issue.state) { + continue; } + if filter.include_assignees.len() > 0 { + let assignee = match &issue.assignee { + Some(assignee) => assignee, + None => "", + }; + if !filter.include_assignees.contains(assignee) { + continue; + } + } + + // This issue passed all the filters, include it in list. + uuids_by_state + .entry(issue.state.clone()) + .or_default() + .push(uuid); } use entomologist::issue::State; diff --git a/src/lib.rs b/src/lib.rs index 77a00d9..b28fb74 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,24 +17,50 @@ pub enum ParseFilterError { // i'm starting with obvious easy things. Chumsky looks appealing but // more research is needed. #[derive(Debug)] -pub struct Filter { +pub struct Filter<'a> { pub include_states: std::collections::HashSet, + pub include_assignees: std::collections::HashSet<&'a str>, } -// Parses a filter description matching "state=STATE[,STATE*]" -pub fn parse_filter(filter_str: &str) -> Result { - let tokens: Vec<&str> = filter_str.split("=").collect(); - if tokens.len() != 2 { - return Err(ParseFilterError::ParseError); - } - if tokens[0] != "state" { - return Err(ParseFilterError::ParseError); - } +impl<'a> Filter<'a> { + pub fn new_from_str(filter_str: &'a str) -> Result, ParseFilterError> { + use crate::issue::State; + let mut f = Filter { + include_states: std::collections::HashSet::::from([ + State::InProgress, + State::Blocked, + State::Backlog, + State::New, + ]), + include_assignees: std::collections::HashSet::<&'a str>::new(), + }; - let mut include_states = std::collections::HashSet::::new(); - for s in tokens[1].split(",") { - include_states.insert(crate::issue::State::from_str(s)?); - } + for filter_chunk_str in filter_str.split(":") { + let tokens: Vec<&str> = filter_chunk_str.split("=").collect(); + if tokens.len() != 2 { + return Err(ParseFilterError::ParseError); + } - Ok(Filter { include_states }) + match tokens[0] { + "state" => { + f.include_states.clear(); + for s in tokens[1].split(",") { + f.include_states.insert(crate::issue::State::from_str(s)?); + } + } + "assignee" => { + f.include_assignees.clear(); + for s in tokens[1].split(",") { + f.include_assignees.insert(s); + } + } + _ => { + println!("unknown filter chunk '{}'", filter_chunk_str); + return Err(ParseFilterError::ParseError); + } + } + } + + Ok(f) + } }