mirror of
https://github.com/ankitects/anki.git
synced 2025-09-25 01:06:35 -04:00
move browser_row method into search service
For want of a better place to put it. Also split the node conversion into a separate file.
This commit is contained in:
parent
95dea7f20a
commit
ff0d346927
5 changed files with 133 additions and 133 deletions
|
@ -108,7 +108,6 @@ enum ServiceIndex {
|
||||||
SERVICE_INDEX_I18N = 12;
|
SERVICE_INDEX_I18N = 12;
|
||||||
SERVICE_INDEX_COLLECTION = 13;
|
SERVICE_INDEX_COLLECTION = 13;
|
||||||
SERVICE_INDEX_CARDS = 14;
|
SERVICE_INDEX_CARDS = 14;
|
||||||
SERVICE_INDEX_BROWSER_ROWS = 15;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
service SchedulingService {
|
service SchedulingService {
|
||||||
|
@ -241,6 +240,7 @@ service SearchService {
|
||||||
rpc JoinSearchNodes(JoinSearchNodesIn) returns (String);
|
rpc JoinSearchNodes(JoinSearchNodesIn) returns (String);
|
||||||
rpc ReplaceSearchNode(ReplaceSearchNodeIn) returns (String);
|
rpc ReplaceSearchNode(ReplaceSearchNodeIn) returns (String);
|
||||||
rpc FindAndReplace(FindAndReplaceIn) returns (OpChangesWithCount);
|
rpc FindAndReplace(FindAndReplaceIn) returns (OpChangesWithCount);
|
||||||
|
rpc BrowserRowForCard(CardID) returns (BrowserRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
service StatsService {
|
service StatsService {
|
||||||
|
@ -283,10 +283,6 @@ service CardsService {
|
||||||
rpc SetFlag(SetFlagIn) returns (OpChanges);
|
rpc SetFlag(SetFlagIn) returns (OpChanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
service BrowserRowsService {
|
|
||||||
rpc BrowserRowForCard(CardID) returns (BrowserRow);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Protobuf stored in .anki2 files
|
// Protobuf stored in .anki2 files
|
||||||
// These should be moved to a separate file in the future
|
// These should be moved to a separate file in the future
|
||||||
///////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
mod adding;
|
mod adding;
|
||||||
mod browser_rows;
|
|
||||||
mod card;
|
mod card;
|
||||||
mod cardrendering;
|
mod cardrendering;
|
||||||
mod collection;
|
mod collection;
|
||||||
|
@ -25,7 +24,6 @@ mod sync;
|
||||||
mod tags;
|
mod tags;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
browser_rows::BrowserRowsService,
|
|
||||||
card::CardsService,
|
card::CardsService,
|
||||||
cardrendering::CardRenderingService,
|
cardrendering::CardRenderingService,
|
||||||
collection::CollectionService,
|
collection::CollectionService,
|
||||||
|
@ -139,9 +137,6 @@ impl Backend {
|
||||||
pb::ServiceIndex::I18n => I18nService::run_method(self, method, input),
|
pb::ServiceIndex::I18n => I18nService::run_method(self, method, input),
|
||||||
pb::ServiceIndex::Collection => CollectionService::run_method(self, method, input),
|
pb::ServiceIndex::Collection => CollectionService::run_method(self, method, input),
|
||||||
pb::ServiceIndex::Cards => CardsService::run_method(self, method, input),
|
pb::ServiceIndex::Cards => CardsService::run_method(self, method, input),
|
||||||
pb::ServiceIndex::BrowserRows => {
|
|
||||||
BrowserRowsService::run_method(self, method, input)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
let backend_err = anki_error_to_proto_error(err, &self.i18n);
|
let backend_err = anki_error_to_proto_error(err, &self.i18n);
|
||||||
|
|
|
@ -1,15 +1,7 @@
|
||||||
// Copyright: Ankitects Pty Ltd and contributors
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
use super::Backend;
|
use crate::{backend_proto as pb, browser_rows};
|
||||||
use crate::{backend_proto as pb, browser_rows, prelude::*};
|
|
||||||
pub(super) use pb::browserrows_service::Service as BrowserRowsService;
|
|
||||||
|
|
||||||
impl BrowserRowsService for Backend {
|
|
||||||
fn browser_row_for_card(&self, input: pb::CardId) -> Result<pb::BrowserRow> {
|
|
||||||
self.with_col(|col| col.browser_row_for_card(input.cid.into()).map(Into::into))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<browser_rows::Row> for pb::BrowserRow {
|
impl From<browser_rows::Row> for pb::BrowserRow {
|
||||||
fn from(row: browser_rows::Row) -> Self {
|
fn from(row: browser_rows::Row) -> Self {
|
129
rslib/src/backend/search/mod.rs
Normal file
129
rslib/src/backend/search/mod.rs
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
// Copyright: Ankitects Pty Ltd and contributors
|
||||||
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
|
mod browser_row;
|
||||||
|
mod search_node;
|
||||||
|
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
use super::Backend;
|
||||||
|
use crate::{
|
||||||
|
backend_proto as pb,
|
||||||
|
backend_proto::{
|
||||||
|
sort_order::builtin::Kind as SortKindProto, sort_order::Value as SortOrderProto,
|
||||||
|
},
|
||||||
|
config::SortKind,
|
||||||
|
prelude::*,
|
||||||
|
search::{concatenate_searches, replace_search_node, write_nodes, Node, SortMode},
|
||||||
|
};
|
||||||
|
pub(super) use pb::search_service::Service as SearchService;
|
||||||
|
|
||||||
|
impl SearchService for Backend {
|
||||||
|
fn build_search_string(&self, input: pb::SearchNode) -> Result<pb::String> {
|
||||||
|
let node: Node = input.try_into()?;
|
||||||
|
Ok(write_nodes(&node.into_node_list()).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn search_cards(&self, input: pb::SearchCardsIn) -> Result<pb::SearchCardsOut> {
|
||||||
|
self.with_col(|col| {
|
||||||
|
let order = input.order.unwrap_or_default().value.into();
|
||||||
|
let cids = col.search_cards(&input.search, order)?;
|
||||||
|
Ok(pb::SearchCardsOut {
|
||||||
|
card_ids: cids.into_iter().map(|v| v.0).collect(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn search_notes(&self, input: pb::SearchNotesIn) -> Result<pb::SearchNotesOut> {
|
||||||
|
self.with_col(|col| {
|
||||||
|
let nids = col.search_notes(&input.search)?;
|
||||||
|
Ok(pb::SearchNotesOut {
|
||||||
|
note_ids: nids.into_iter().map(|v| v.0).collect(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn join_search_nodes(&self, input: pb::JoinSearchNodesIn) -> Result<pb::String> {
|
||||||
|
let sep = input.joiner().into();
|
||||||
|
let existing_nodes = {
|
||||||
|
let node: Node = input.existing_node.unwrap_or_default().try_into()?;
|
||||||
|
node.into_node_list()
|
||||||
|
};
|
||||||
|
let additional_node = input.additional_node.unwrap_or_default().try_into()?;
|
||||||
|
Ok(concatenate_searches(sep, existing_nodes, additional_node).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn replace_search_node(&self, input: pb::ReplaceSearchNodeIn) -> Result<pb::String> {
|
||||||
|
let existing = {
|
||||||
|
let node = input.existing_node.unwrap_or_default().try_into()?;
|
||||||
|
if let Node::Group(nodes) = node {
|
||||||
|
nodes
|
||||||
|
} else {
|
||||||
|
vec![node]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let replacement = input.replacement_node.unwrap_or_default().try_into()?;
|
||||||
|
Ok(replace_search_node(existing, replacement).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_and_replace(&self, input: pb::FindAndReplaceIn) -> Result<pb::OpChangesWithCount> {
|
||||||
|
let mut search = if input.regex {
|
||||||
|
input.search
|
||||||
|
} else {
|
||||||
|
regex::escape(&input.search)
|
||||||
|
};
|
||||||
|
if !input.match_case {
|
||||||
|
search = format!("(?i){}", search);
|
||||||
|
}
|
||||||
|
let nids = input.nids.into_iter().map(NoteID).collect();
|
||||||
|
let field_name = if input.field_name.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(input.field_name)
|
||||||
|
};
|
||||||
|
let repl = input.replacement;
|
||||||
|
self.with_col(|col| {
|
||||||
|
col.find_and_replace(nids, &search, &repl, field_name)
|
||||||
|
.map(Into::into)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn browser_row_for_card(&self, input: pb::CardId) -> Result<pb::BrowserRow> {
|
||||||
|
self.with_col(|col| col.browser_row_for_card(input.cid.into()).map(Into::into))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SortKindProto> for SortKind {
|
||||||
|
fn from(kind: SortKindProto) -> Self {
|
||||||
|
match kind {
|
||||||
|
SortKindProto::NoteCreation => SortKind::NoteCreation,
|
||||||
|
SortKindProto::NoteMod => SortKind::NoteMod,
|
||||||
|
SortKindProto::NoteField => SortKind::NoteField,
|
||||||
|
SortKindProto::NoteTags => SortKind::NoteTags,
|
||||||
|
SortKindProto::NoteType => SortKind::NoteType,
|
||||||
|
SortKindProto::CardMod => SortKind::CardMod,
|
||||||
|
SortKindProto::CardReps => SortKind::CardReps,
|
||||||
|
SortKindProto::CardDue => SortKind::CardDue,
|
||||||
|
SortKindProto::CardEase => SortKind::CardEase,
|
||||||
|
SortKindProto::CardLapses => SortKind::CardLapses,
|
||||||
|
SortKindProto::CardInterval => SortKind::CardInterval,
|
||||||
|
SortKindProto::CardDeck => SortKind::CardDeck,
|
||||||
|
SortKindProto::CardTemplate => SortKind::CardTemplate,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Option<SortOrderProto>> for SortMode {
|
||||||
|
fn from(order: Option<SortOrderProto>) -> Self {
|
||||||
|
use pb::sort_order::Value as V;
|
||||||
|
match order.unwrap_or(V::FromConfig(pb::Empty {})) {
|
||||||
|
V::None(_) => SortMode::NoOrder,
|
||||||
|
V::Custom(s) => SortMode::Custom(s),
|
||||||
|
V::FromConfig(_) => SortMode::FromConfig,
|
||||||
|
V::Builtin(b) => SortMode::Builtin {
|
||||||
|
kind: b.kind().into(),
|
||||||
|
reverse: b.reverse,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,92 +4,15 @@
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
|
||||||
use super::Backend;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend_proto as pb,
|
backend_proto as pb,
|
||||||
backend_proto::{
|
|
||||||
sort_order::builtin::Kind as SortKindProto, sort_order::Value as SortOrderProto,
|
|
||||||
},
|
|
||||||
config::SortKind,
|
|
||||||
prelude::*,
|
prelude::*,
|
||||||
search::{
|
search::{
|
||||||
concatenate_searches, parse_search, replace_search_node, write_nodes, BoolSeparator, Node,
|
parse_search, BoolSeparator, Node, PropertyKind, RatingKind, SearchNode, StateKind,
|
||||||
PropertyKind, RatingKind, SearchNode, SortMode, StateKind, TemplateKind,
|
TemplateKind,
|
||||||
},
|
},
|
||||||
text::escape_anki_wildcards,
|
text::escape_anki_wildcards,
|
||||||
};
|
};
|
||||||
pub(super) use pb::search_service::Service as SearchService;
|
|
||||||
|
|
||||||
impl SearchService for Backend {
|
|
||||||
fn build_search_string(&self, input: pb::SearchNode) -> Result<pb::String> {
|
|
||||||
let node: Node = input.try_into()?;
|
|
||||||
Ok(write_nodes(&node.into_node_list()).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn search_cards(&self, input: pb::SearchCardsIn) -> Result<pb::SearchCardsOut> {
|
|
||||||
self.with_col(|col| {
|
|
||||||
let order = input.order.unwrap_or_default().value.into();
|
|
||||||
let cids = col.search_cards(&input.search, order)?;
|
|
||||||
Ok(pb::SearchCardsOut {
|
|
||||||
card_ids: cids.into_iter().map(|v| v.0).collect(),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn search_notes(&self, input: pb::SearchNotesIn) -> Result<pb::SearchNotesOut> {
|
|
||||||
self.with_col(|col| {
|
|
||||||
let nids = col.search_notes(&input.search)?;
|
|
||||||
Ok(pb::SearchNotesOut {
|
|
||||||
note_ids: nids.into_iter().map(|v| v.0).collect(),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn join_search_nodes(&self, input: pb::JoinSearchNodesIn) -> Result<pb::String> {
|
|
||||||
let sep = input.joiner().into();
|
|
||||||
let existing_nodes = {
|
|
||||||
let node: Node = input.existing_node.unwrap_or_default().try_into()?;
|
|
||||||
node.into_node_list()
|
|
||||||
};
|
|
||||||
let additional_node = input.additional_node.unwrap_or_default().try_into()?;
|
|
||||||
Ok(concatenate_searches(sep, existing_nodes, additional_node).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn replace_search_node(&self, input: pb::ReplaceSearchNodeIn) -> Result<pb::String> {
|
|
||||||
let existing = {
|
|
||||||
let node = input.existing_node.unwrap_or_default().try_into()?;
|
|
||||||
if let Node::Group(nodes) = node {
|
|
||||||
nodes
|
|
||||||
} else {
|
|
||||||
vec![node]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let replacement = input.replacement_node.unwrap_or_default().try_into()?;
|
|
||||||
Ok(replace_search_node(existing, replacement).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_and_replace(&self, input: pb::FindAndReplaceIn) -> Result<pb::OpChangesWithCount> {
|
|
||||||
let mut search = if input.regex {
|
|
||||||
input.search
|
|
||||||
} else {
|
|
||||||
regex::escape(&input.search)
|
|
||||||
};
|
|
||||||
if !input.match_case {
|
|
||||||
search = format!("(?i){}", search);
|
|
||||||
}
|
|
||||||
let nids = input.nids.into_iter().map(NoteID).collect();
|
|
||||||
let field_name = if input.field_name.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(input.field_name)
|
|
||||||
};
|
|
||||||
let repl = input.replacement;
|
|
||||||
self.with_col(|col| {
|
|
||||||
col.find_and_replace(nids, &search, &repl, field_name)
|
|
||||||
.map(Into::into)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<pb::SearchNode> for Node {
|
impl TryFrom<pb::SearchNode> for Node {
|
||||||
type Error = AnkiError;
|
type Error = AnkiError;
|
||||||
|
@ -229,38 +152,3 @@ impl pb::search_node::IdList {
|
||||||
.join(",")
|
.join(",")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SortKindProto> for SortKind {
|
|
||||||
fn from(kind: SortKindProto) -> Self {
|
|
||||||
match kind {
|
|
||||||
SortKindProto::NoteCreation => SortKind::NoteCreation,
|
|
||||||
SortKindProto::NoteMod => SortKind::NoteMod,
|
|
||||||
SortKindProto::NoteField => SortKind::NoteField,
|
|
||||||
SortKindProto::NoteTags => SortKind::NoteTags,
|
|
||||||
SortKindProto::NoteType => SortKind::NoteType,
|
|
||||||
SortKindProto::CardMod => SortKind::CardMod,
|
|
||||||
SortKindProto::CardReps => SortKind::CardReps,
|
|
||||||
SortKindProto::CardDue => SortKind::CardDue,
|
|
||||||
SortKindProto::CardEase => SortKind::CardEase,
|
|
||||||
SortKindProto::CardLapses => SortKind::CardLapses,
|
|
||||||
SortKindProto::CardInterval => SortKind::CardInterval,
|
|
||||||
SortKindProto::CardDeck => SortKind::CardDeck,
|
|
||||||
SortKindProto::CardTemplate => SortKind::CardTemplate,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Option<SortOrderProto>> for SortMode {
|
|
||||||
fn from(order: Option<SortOrderProto>) -> Self {
|
|
||||||
use pb::sort_order::Value as V;
|
|
||||||
match order.unwrap_or(V::FromConfig(pb::Empty {})) {
|
|
||||||
V::None(_) => SortMode::NoOrder,
|
|
||||||
V::Custom(s) => SortMode::Custom(s),
|
|
||||||
V::FromConfig(_) => SortMode::FromConfig,
|
|
||||||
V::Builtin(b) => SortMode::Builtin {
|
|
||||||
kind: b.kind().into(),
|
|
||||||
reverse: b.reverse,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue