Implement replace_search_term
This commit is contained in:
parent
79d0b5496b
commit
84061a6e6d
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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>),
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user