Implement replace_search_term

This commit is contained in:
RumovZ 2021-01-06 14:03:43 +01:00
parent 79d0b5496b
commit 84061a6e6d
4 changed files with 50 additions and 4 deletions

View File

@ -89,6 +89,7 @@ service BackendService {
rpc SearchNotes (SearchNotesIn) returns (SearchNotesOut);
rpc NegateSearch (String) returns (String);
rpc ConcatenateSearches (ConcatenateSearchesIn) returns (String);
rpc ReplaceSearchTerm (ReplaceSearchTermIn) returns (String);
rpc FindAndReplace (FindAndReplaceIn) returns (UInt32);
// scheduling
@ -755,6 +756,20 @@ message BuiltinSearchOrder {
bool reverse = 2;
}
message ConcatenateSearchesIn {
enum Separator {
AND = 0;
OR = 1;
}
Separator sep = 1;
repeated string searches = 2;
}
message ReplaceSearchTermIn {
string search = 1;
string replacement = 2;
}
message CloseCollectionIn {
bool downgrade_to_schema11 = 1;
}

View File

@ -435,10 +435,15 @@ impl BackendService for Backend {
fn negate_search(&self, input: pb::String) -> Result<pb::String> {
Ok(negate_search(&input.val)?.into())
}
fn concatenate_searches(&self, input: pb::ConcatenateSearchesIn) -> Result<pb::String> {
Ok(concatenate_searches(input.sep, &input.searches)?.into())
}
fn replace_search_term(&self, input: pb::ReplaceSearchTermIn) -> Result<pb::String> {
Ok(replace_search_term(&input.search, &input.replacement)?.into())
}
fn find_and_replace(&self, input: pb::FindAndReplaceIn) -> BackendResult<pb::UInt32> {
let mut search = if input.regex {
input.search

View File

@ -50,7 +50,7 @@ pub(super) enum Node<'a> {
Search(SearchNode<'a>),
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub(super) enum SearchNode<'a> {
// text without a colon
UnqualifiedText(Cow<'a, str>),
@ -90,7 +90,7 @@ pub(super) enum SearchNode<'a> {
WordBoundary(Cow<'a, str>),
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub(super) enum PropertyKind {
Due(i32),
Interval(u32),
@ -99,7 +99,7 @@ pub(super) enum PropertyKind {
Ease(f32),
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub(super) enum StateKind {
New,
Review,
@ -111,7 +111,7 @@ pub(super) enum StateKind {
Suspended,
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub(super) enum TemplateKind<'a> {
Ordinal(u16),
Name(Cow<'a, str>),

View File

@ -9,6 +9,7 @@ use crate::{
search::parser::{parse, Node, PropertyKind, SearchNode, StateKind, TemplateKind},
};
use itertools::Itertools;
use std::mem;
/// Take an Anki-style search string and convert it into an equivalent
/// search string with normalized syntax.
@ -55,6 +56,31 @@ pub fn concatenate_searches(sep: i32, searches: &[String]) -> Result<String> {
))
}
/// Take two Anki-style search strings. If the second one evaluates to a single search
/// node, replace with it all search terms of the same kind in the first search.
/// Then return the possibly modified first search.
pub fn replace_search_term(search: &str, replacement: &str) -> Result<String> {
let mut nodes = parse(search)?;
let new = parse(replacement)?;
if let [Node::Search(search_node)] = &new[..] {
fn update_node_vec<'a>(old_nodes: &mut [Node<'a>], new_node: &SearchNode<'a>) {
fn update_node<'a>(old_node: &mut Node<'a>, new_node: &SearchNode<'a>) {
match old_node {
Node::Not(n) => update_node(n, new_node),
Node::Group(ns) => update_node_vec(ns, new_node),
Node::Search(n) => {
if mem::discriminant(n) == mem::discriminant(new_node) {
*n = new_node.clone();
}
}
_ => (),
}
}
old_nodes.iter_mut().for_each(|n| update_node(n, new_node));
}
update_node_vec(&mut nodes, search_node);
}
Ok(write_nodes(&nodes))
}
fn write_nodes<'a, I>(nodes: I) -> String