add enum for controlling sort order

eg col.find_cards("", order=BuiltinSortKind.CARD_DUE)
This commit is contained in:
Damien Elmes 2020-03-22 12:59:24 +10:00
parent 199713a39a
commit f28e57a367
6 changed files with 89 additions and 6 deletions

View file

@ -331,6 +331,7 @@ message SortOrder {
Empty from_config = 1;
Empty none = 2;
string custom = 3;
BuiltinSearchOrder builtin = 4;
}
}
@ -341,3 +342,24 @@ message SearchNotesIn {
message SearchNotesOut {
repeated int64 note_ids = 2;
}
message BuiltinSearchOrder {
BuiltinSortKind kind = 1;
bool reverse = 2;
}
enum BuiltinSortKind {
NOTE_CREATION = 0;
NOTE_MOD = 1;
NOTE_FIELD = 2;
NOTE_TAGS = 3;
NOTE_TYPE = 4;
CARD_MOD = 5;
CARD_REPS = 6;
CARD_DUE = 7;
CARD_EASE = 8;
CARD_LAPSES = 9;
CARD_INTERVAL = 10;
CARD_DECK = 11;
CARD_TEMPLATE = 12;
}

View file

@ -616,8 +616,16 @@ where c.nid = n.id and c.id in %s group by nid"""
# Finding cards
##########################################################################
def find_cards(self, query: str, order: Union[bool, str] = False) -> Sequence[int]:
return self.backend.search_cards(query, order)
# if order=True, use the sort order stored in the collection config
# if order=False, do no ordering
# if order is a string, that text is added after 'order by' in the sql statement
# if order is an int enum, sort using that builtin sort.
#
# the reverse argument only applies when a BuiltinSortKind is provided.
def find_cards(
self, query: str, order: Union[bool, str, int] = False, reverse: bool = False,
) -> Sequence[int]:
return self.backend.search_cards(query, order, reverse)
def find_notes(self, query: str) -> Sequence[int]:
return self.backend.search_notes(query)

View file

@ -34,6 +34,7 @@ from anki.types import assert_impossible_literal
assert ankirspy.buildhash() == anki.buildinfo.buildhash
SchedTimingToday = pb.SchedTimingTodayOut
BuiltinSortKind = pb.BuiltinSortKind
try:
import orjson
@ -435,13 +436,23 @@ class RustBackend:
def _db_command(self, input: Dict[str, Any]) -> Any:
return orjson.loads(self._backend.db_command(orjson.dumps(input)))
def search_cards(self, search: str, order: Union[bool, str]) -> Sequence[int]:
def search_cards(
self, search: str, order: Union[bool, str, int], reverse: bool = False
) -> Sequence[int]:
if isinstance(order, str):
mode = pb.SortOrder(custom=order)
elif not order:
elif order is True:
mode = pb.SortOrder(from_config=pb.Empty())
elif order is False:
mode = pb.SortOrder(none=pb.Empty())
else:
mode = pb.SortOrder(from_config=pb.Empty())
# sadly we can't use the protobuf type in a Union, so we
# have to accept an int and convert it
kind = BuiltinSortKind.Value(BuiltinSortKind.Name(order))
mode = pb.SortOrder(
builtin=pb.BuiltinSearchOrder(kind=kind, reverse=reverse)
)
return self._run_command(
pb.BackendInput(search_cards=pb.SearchCardsIn(search=search, order=mode))
).search_cards.card_ids

View file

@ -2,6 +2,7 @@
import pytest
from anki.consts import *
from anki.rsbackend import BuiltinSortKind
from tests.shared import getEmptyCol
@ -120,6 +121,14 @@ def test_findCards():
deck.conf["sortBackwards"] = True
deck.flush()
assert deck.findCards("", order=True)[0] in latestCardIds
assert (
deck.find_cards("", order=BuiltinSortKind.CARD_DUE, reverse=False)[0]
== firstCardId
)
assert (
deck.find_cards("", order=BuiltinSortKind.CARD_DUE, reverse=True)[0]
!= firstCardId
)
# model
assert len(deck.findCards("note:basic")) == 5
assert len(deck.findCards("-note:basic")) == 0

View file

@ -3,8 +3,9 @@
use crate::backend::dbproxy::db_command_bytes;
use crate::backend_proto::backend_input::Value;
use crate::backend_proto::{Empty, RenderedTemplateReplacement, SyncMediaIn};
use crate::backend_proto::{BuiltinSortKind, Empty, RenderedTemplateReplacement, SyncMediaIn};
use crate::collection::{open_collection, Collection};
use crate::config::SortKind;
use crate::err::{AnkiError, NetworkErrorKind, Result, SyncErrorKind};
use crate::i18n::{tr_args, FString, I18n};
use crate::latex::{extract_latex, extract_latex_expanding_clozes, ExtractedLatex};
@ -588,6 +589,10 @@ impl Backend {
Some(V::None(_)) => SortMode::NoOrder,
Some(V::Custom(s)) => SortMode::Custom(s),
Some(V::FromConfig(_)) => SortMode::FromConfig,
Some(V::Builtin(b)) => SortMode::Builtin {
kind: sort_kind_from_pb(b.kind),
reverse: b.reverse,
},
None => SortMode::FromConfig,
}
} else {
@ -677,3 +682,25 @@ fn media_sync_progress(p: &MediaSyncProgress, i18n: &I18n) -> pb::MediaSyncProgr
),
}
}
fn sort_kind_from_pb(kind: i32) -> SortKind {
use SortKind as SK;
match pb::BuiltinSortKind::from_i32(kind) {
Some(pbkind) => match pbkind {
BuiltinSortKind::NoteCreation => SK::NoteCreation,
BuiltinSortKind::NoteMod => SK::NoteMod,
BuiltinSortKind::NoteField => SK::NoteField,
BuiltinSortKind::NoteTags => SK::NoteTags,
BuiltinSortKind::NoteType => SK::NoteType,
BuiltinSortKind::CardMod => SK::CardMod,
BuiltinSortKind::CardReps => SK::CardReps,
BuiltinSortKind::CardDue => SK::CardDue,
BuiltinSortKind::CardEase => SK::CardEase,
BuiltinSortKind::CardLapses => SK::CardLapses,
BuiltinSortKind::CardInterval => SK::CardInterval,
BuiltinSortKind::CardDeck => SK::CardDeck,
BuiltinSortKind::CardTemplate => SK::CardTemplate,
},
_ => SortKind::NoteCreation,
}
}

View file

@ -13,6 +13,7 @@ use rusqlite::params;
pub(crate) enum SortMode {
NoOrder,
FromConfig,
Builtin { kind: SortKind, reverse: bool },
Custom(String),
}
@ -37,6 +38,11 @@ pub(crate) fn search_cards<'a, 'b>(
sql.push_str(" order by ");
write_order(&mut sql, &conf.browser_sort_kind, conf.browser_sort_reverse)?;
}
SortMode::Builtin { kind, reverse } => {
prepare_sort(req, &kind)?;
sql.push_str(" order by ");
write_order(&mut sql, &kind, reverse)?;
}
SortMode::Custom(order_clause) => {
sql.push_str(" order by ");
sql.push_str(&order_clause);