Adds NOT search operator

This commit is contained in:
Antoine Gersant 2024-09-25 17:22:40 -07:00
parent f971b78856
commit b943d9aa11
2 changed files with 31 additions and 1 deletions

View file

@ -54,6 +54,7 @@ pub enum Literal {
pub enum BoolOp { pub enum BoolOp {
And, And,
Or, Or,
Not,
} }
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
@ -128,7 +129,12 @@ pub fn make_parser() -> impl Parser<char, Expr, Error = Simple<char>> {
let filter = choice((text_cmp, number_cmp, fuzzy)); let filter = choice((text_cmp, number_cmp, fuzzy));
let atom = choice((filter, expr.delimited_by(just('('), just(')')))); let atom = choice((filter, expr.delimited_by(just('('), just(')'))));
let bool_op = choice((just("&&").to(BoolOp::And), just("||").to(BoolOp::Or))).padded(); let bool_op = choice((
just("&&").to(BoolOp::And),
just("||").to(BoolOp::Or),
just("!!").to(BoolOp::Not),
))
.padded();
let combined = atom let combined = atom
.clone() .clone()

View file

@ -119,6 +119,8 @@ impl Search {
match (left, op, right) { match (left, op, right) {
(Some(l), BoolOp::And, Some(r)) => l.intersection(&r).cloned().collect(), (Some(l), BoolOp::And, Some(r)) => l.intersection(&r).cloned().collect(),
(Some(l), BoolOp::Or, Some(r)) => l.union(&r).cloned().collect(), (Some(l), BoolOp::Or, Some(r)) => l.union(&r).cloned().collect(),
(Some(l), BoolOp::Not, Some(r)) => l.difference(&r).cloned().collect(),
(None, BoolOp::Not, _) => IntSet::default(),
(Some(l), _, None) => l, (Some(l), _, None) => l,
(None, _, Some(r)) => r, (None, _, Some(r)) => r,
(None, _, None) => IntSet::default(), (None, _, None) => IntSet::default(),
@ -605,6 +607,28 @@ mod test {
assert!(songs.contains(&PathBuf::from("whales in space.mp3"))); assert!(songs.contains(&PathBuf::from("whales in space.mp3")));
} }
#[test]
fn can_use_not_operator() {
let ctx = setup_test(vec![
scanner::Song {
virtual_path: PathBuf::from("whale.mp3"),
..Default::default()
},
scanner::Song {
virtual_path: PathBuf::from("space.mp3"),
..Default::default()
},
scanner::Song {
virtual_path: PathBuf::from("whales in space.mp3"),
..Default::default()
},
]);
let songs = ctx.search("whale !! space");
assert_eq!(songs.len(), 1);
assert!(songs.contains(&PathBuf::from("whale.mp3")));
}
#[test] #[test]
fn results_are_sorted() { fn results_are_sorted() {
let ctx = setup_test(vec![ let ctx = setup_test(vec![