Implement negate_search

This commit is contained in:
RumovZ 2021-01-06 13:57:35 +01:00
parent 95b4e4cc84
commit 713db05f27
4 changed files with 34 additions and 4 deletions

View file

@ -87,6 +87,7 @@ service BackendService {
rpc NormalizeSearch (String) returns (String); rpc NormalizeSearch (String) returns (String);
rpc SearchCards (SearchCardsIn) returns (SearchCardsOut); rpc SearchCards (SearchCardsIn) returns (SearchCardsOut);
rpc SearchNotes (SearchNotesIn) returns (SearchNotesOut); rpc SearchNotes (SearchNotesIn) returns (SearchNotesOut);
rpc NegateSearch (String) returns (String);
rpc FindAndReplace (FindAndReplaceIn) returns (UInt32); rpc FindAndReplace (FindAndReplaceIn) returns (UInt32);
// scheduling // scheduling

View file

@ -32,7 +32,9 @@ use crate::{
}, },
sched::cutoff::local_minutes_west_for_stamp, sched::cutoff::local_minutes_west_for_stamp,
sched::timespan::{answer_button_time, time_span}, sched::timespan::{answer_button_time, time_span},
search::{normalize_search, SortMode}, search::{
concatenate_searches, negate_search, normalize_search, replace_search_term, SortMode,
},
stats::studied_today, stats::studied_today,
sync::{ sync::{
get_remote_sync_meta, sync_abort, sync_login, FullSyncProgress, NormalSyncProgress, get_remote_sync_meta, sync_abort, sync_login, FullSyncProgress, NormalSyncProgress,
@ -430,6 +432,9 @@ impl BackendService for Backend {
}) })
} }
fn negate_search(&self, input: pb::String) -> Result<pb::String> {
Ok(negate_search(&input.val)?.into())
}
fn find_and_replace(&self, input: pb::FindAndReplaceIn) -> BackendResult<pb::UInt32> { fn find_and_replace(&self, input: pb::FindAndReplaceIn) -> BackendResult<pb::UInt32> {
let mut search = if input.regex { let mut search = if input.regex {
input.search input.search

View file

@ -5,4 +5,4 @@ mod sqlwriter;
mod writer; mod writer;
pub use cards::SortMode; pub use cards::SortMode;
pub use writer::normalize_search; pub use writer::{concatenate_searches, negate_search, normalize_search, replace_search_term};

View file

@ -14,8 +14,32 @@ pub fn normalize_search(input: &str) -> Result<String> {
Ok(write_nodes(&parse(input)?)) Ok(write_nodes(&parse(input)?))
} }
fn write_nodes(nodes: &[Node]) -> String { /// Take an Anki-style search string and return the negated counterpart.
nodes.iter().map(|node| write_node(node)).collect() /// Empty searches (whole collection) remain unchanged.
pub fn negate_search(input: &str) -> Result<String> {
let mut nodes = parse(input)?;
use Node::*;
Ok(if nodes.len() == 1 {
let node = nodes.remove(0);
match node {
Not(n) => write_node(&n),
Search(SearchNode::WholeCollection) => "".to_string(),
Group(_) | Search(_) => write_node(&Not(Box::new(node))),
_ => unreachable!(),
}
} else {
write_node(&Not(Box::new(Group(nodes))))
})
}
}
}
fn write_nodes<'a, I>(nodes: I) -> String
where
I: IntoIterator<Item = &'a Node<'a>>,
{
nodes.into_iter().map(|node| write_node(node)).collect()
} }
fn write_node(node: &Node) -> String { fn write_node(node: &Node) -> String {