support filtering by tags

This commit is contained in:
Dustin J. Mitchell 2020-12-24 16:38:08 +00:00
parent 161c38807d
commit 9c94a7b753
4 changed files with 140 additions and 13 deletions

View file

@ -1,10 +1,28 @@
use crate::argparse::{Filter, TaskId, Universe};
use crate::argparse::{Condition, Filter, TaskId, Universe};
use failure::Fallible;
use std::collections::HashSet;
use taskchampion::{Replica, Task};
use std::convert::TryInto;
use taskchampion::{Replica, Tag, Task};
fn match_task(_filter: &Filter, _task: &Task) -> bool {
// TODO: at the moment, only filtering by Universe is supported
fn match_task(filter: &Filter, task: &Task) -> bool {
for cond in &filter.conditions {
match cond {
Condition::HasTag(ref tag) => {
// see #111 for the unwrap
let tag: Tag = tag.try_into().unwrap();
if !task.has_tag(&tag) {
return false;
}
}
Condition::NoTag(ref tag) => {
// see #111 for the unwrap
let tag: Tag = tag.try_into().unwrap();
if task.has_tag(&tag) {
return false;
}
}
}
}
true
}
@ -186,6 +204,68 @@ mod test {
);
}
#[test]
fn tag_filtering() -> Fallible<()> {
let mut replica = test_replica();
let yes: Tag = "yes".try_into()?;
let no: Tag = "no".try_into()?;
let mut t1 = replica
.new_task(Status::Pending, "A".to_owned())?
.into_mut(&mut replica);
t1.add_tag(&yes)?;
let mut t2 = replica
.new_task(Status::Pending, "B".to_owned())?
.into_mut(&mut replica);
t2.add_tag(&yes)?;
t2.add_tag(&no)?;
let mut t3 = replica
.new_task(Status::Pending, "C".to_owned())?
.into_mut(&mut replica);
t3.add_tag(&no)?;
let _t4 = replica.new_task(Status::Pending, "D".to_owned())?;
// look for just "yes" (A and B)
let filter = Filter {
universe: Universe::AllTasks,
conditions: vec![Condition::HasTag("yes".to_owned())],
..Default::default()
};
let mut filtered: Vec<_> = filtered_tasks(&mut replica, &filter)?
.map(|t| t.get_description().to_owned())
.collect();
filtered.sort();
assert_eq!(vec!["A".to_owned(), "B".to_owned()], filtered);
// look for tags without "no" (A, D)
let filter = Filter {
universe: Universe::AllTasks,
conditions: vec![Condition::NoTag("no".to_owned())],
..Default::default()
};
let mut filtered: Vec<_> = filtered_tasks(&mut replica, &filter)?
.map(|t| t.get_description().to_owned())
.collect();
filtered.sort();
assert_eq!(vec!["A".to_owned(), "D".to_owned()], filtered);
// look for tags with "yes" and "no" (B)
let filter = Filter {
universe: Universe::AllTasks,
conditions: vec![
Condition::HasTag("yes".to_owned()),
Condition::HasTag("no".to_owned()),
],
..Default::default()
};
let filtered: Vec<_> = filtered_tasks(&mut replica, &filter)?
.map(|t| t.get_description().to_owned())
.collect();
assert_eq!(vec!["B".to_owned()], filtered);
Ok(())
}
#[test]
fn pending_tasks() {
let mut replica = test_replica();

View file

@ -34,14 +34,12 @@ pub(super) fn apply_modification<W: WriteColor>(
}
for tag in modification.add_tags.iter() {
// note that the parser should have already ensured that this tag was valid
let tag = tag.try_into()?;
let tag = tag.try_into()?; // see #111
task.add_tag(&tag)?;
}
for tag in modification.remove_tags.iter() {
// note that the parser should have already ensured that this tag was valid
let tag = tag.try_into()?;
let tag = tag.try_into()?; // see #111
task.remove_tag(&tag)?;
}