Merge SortKind enum into Column enum

This commit is contained in:
RumovZ 2021-04-09 18:03:29 +02:00
parent c74078ea9e
commit bdd257e140
6 changed files with 144 additions and 211 deletions

View File

@ -12,7 +12,7 @@ SearchNode = _pb.SearchNode
Progress = _pb.Progress Progress = _pb.Progress
EmptyCardsReport = _pb.EmptyCardsReport EmptyCardsReport = _pb.EmptyCardsReport
GraphPreferences = _pb.GraphPreferences GraphPreferences = _pb.GraphPreferences
BuiltinSort = _pb.SortOrder.Builtin BuiltinSort = _pb.SortOrder.Builtin.SortColumn
Preferences = _pb.Preferences Preferences = _pb.Preferences
UndoStatus = _pb.UndoStatus UndoStatus = _pb.UndoStatus
OpChanges = _pb.OpChanges OpChanges = _pb.OpChanges
@ -506,7 +506,7 @@ class Collection:
def find_cards( def find_cards(
self, self,
query: str, query: str,
order: Union[bool, str, BuiltinSort.Kind.V] = False, order: Union[bool, str, BuiltinSort.V] = False,
reverse: bool = False, reverse: bool = False,
) -> Sequence[CardId]: ) -> Sequence[CardId]:
"""Return card ids matching the provided search. """Return card ids matching the provided search.
@ -521,10 +521,10 @@ class Collection:
desc and vice versa when reverse is set in the collection config, eg desc and vice versa when reverse is set in the collection config, eg
order="c.ivl asc, c.due desc". order="c.ivl asc, c.due desc".
If order is a BuiltinSort.Kind value, sort using that builtin sort, eg If order is a BuiltinSort value, sort using that builtin sort, eg
col.find_cards("", order=BuiltinSort.Kind.DUE) col.find_cards("", order=BuiltinSort.DUE)
The reverse argument only applies when a BuiltinSort.Kind is provided; The reverse argument only applies when a BuiltinSort.V is provided;
otherwise the collection config defines whether reverse is set or not. otherwise the collection config defines whether reverse is set or not.
""" """
mode = _build_sort_mode(order, reverse) mode = _build_sort_mode(order, reverse)
@ -535,7 +535,7 @@ class Collection:
def find_notes( def find_notes(
self, self,
query: str, query: str,
order: Union[bool, str, BuiltinSort.Kind.V] = False, order: Union[bool, str, BuiltinSort.V] = False,
reverse: bool = False, reverse: bool = False,
) -> Sequence[NoteId]: ) -> Sequence[NoteId]:
"""Return note ids matching the provided search. """Return note ids matching the provided search.
@ -1123,7 +1123,7 @@ _UndoInfo = Union[_ReviewsUndo, LegacyCheckpoint, None]
def _build_sort_mode( def _build_sort_mode(
order: Union[bool, str, BuiltinSort.Kind.V], order: Union[bool, str, BuiltinSort.V],
reverse: bool, reverse: bool,
) -> _pb.SortOrder: ) -> _pb.SortOrder:
if isinstance(order, str): if isinstance(order, str):
@ -1134,4 +1134,4 @@ def _build_sort_mode(
else: else:
return _pb.SortOrder(none=_pb.Empty()) return _pb.SortOrder(none=_pb.Empty())
else: else:
return _pb.SortOrder(builtin=_pb.SortOrder.Builtin(kind=order, reverse=reverse)) return _pb.SortOrder(builtin=_pb.SortOrder.Builtin(column=order, reverse=reverse))

View File

@ -796,28 +796,22 @@ message SearchOut {
message SortOrder { message SortOrder {
message Builtin { message Builtin {
enum Kind { enum SortColumn {
NOTE_CARDS = 0; CARD_MOD = 0;
NOTE_CREATION = 1; CARDS = 1;
NOTE_DUE = 2; DECK = 2;
NOTE_EASE = 3; DUE = 3;
SORT_FIELD = 4; EASE = 4;
NOTE_INTERVAL = 5; LAPSES = 5;
NOTE_LAPSES = 6; INTERVAL = 6;
NOTE_MOD = 7; NOTE_CREATION = 7;
NOTE_REPS = 8; NOTE_MOD = 8;
TAGS = 9; NOTETYPE = 9;
NOTETYPE = 10; REPS = 10;
CARD_MOD = 11; SORT_FIELD = 11;
REPS = 12; TAGS = 12;
DUE = 13;
EASE = 14;
LAPSES = 15;
INTERVAL = 16;
DECK = 17;
CARDS = 18;
} }
Kind kind = 1; SortColumn column = 1;
bool reverse = 2; bool reverse = 2;
} }
oneof value { oneof value {

View File

@ -10,9 +10,9 @@ use super::Backend;
use crate::{ use crate::{
backend_proto as pb, backend_proto as pb,
backend_proto::{ backend_proto::{
sort_order::builtin::Kind as SortKindProto, sort_order::Value as SortOrderProto, sort_order::builtin::SortColumn as SortColumnProto, sort_order::Value as SortOrderProto,
}, },
config::SortKind, browser_table::Column,
prelude::*, prelude::*,
search::{concatenate_searches, replace_search_node, write_nodes, Node, SortMode}, search::{concatenate_searches, replace_search_node, write_nodes, Node, SortMode},
}; };
@ -108,28 +108,22 @@ impl SearchService for Backend {
} }
} }
impl From<SortKindProto> for SortKind { impl From<SortColumnProto> for Column {
fn from(kind: SortKindProto) -> Self { fn from(kind: SortColumnProto) -> Self {
match kind { match kind {
SortKindProto::NoteCards => SortKind::NoteCards, SortColumnProto::CardMod => Column::CardMod,
SortKindProto::NoteCreation => SortKind::NoteCreation, SortColumnProto::Cards => Column::Cards,
SortKindProto::NoteDue => SortKind::NoteDue, SortColumnProto::Deck => Column::Deck,
SortKindProto::NoteEase => SortKind::NoteEase, SortColumnProto::Due => Column::Due,
SortKindProto::NoteInterval => SortKind::NoteInterval, SortColumnProto::Ease => Column::Ease,
SortKindProto::NoteLapses => SortKind::NoteLapses, SortColumnProto::Lapses => Column::Lapses,
SortKindProto::NoteMod => SortKind::NoteMod, SortColumnProto::Interval => Column::Interval,
SortKindProto::SortField => SortKind::SortField, SortColumnProto::NoteCreation => Column::NoteCreation,
SortKindProto::NoteReps => SortKind::NoteReps, SortColumnProto::NoteMod => Column::NoteMod,
SortKindProto::Tags => SortKind::Tags, SortColumnProto::Notetype => Column::Notetype,
SortKindProto::Notetype => SortKind::Notetype, SortColumnProto::Reps => Column::Reps,
SortKindProto::CardMod => SortKind::CardMod, SortColumnProto::SortField => Column::SortField,
SortKindProto::Reps => SortKind::Reps, SortColumnProto::Tags => Column::Tags,
SortKindProto::Due => SortKind::Due,
SortKindProto::Ease => SortKind::Ease,
SortKindProto::Lapses => SortKind::Lapses,
SortKindProto::Interval => SortKind::Interval,
SortKindProto::Deck => SortKind::Deck,
SortKindProto::Cards => SortKind::Cards,
} }
} }
} }
@ -142,7 +136,7 @@ impl From<Option<SortOrderProto>> for SortMode {
V::Custom(s) => SortMode::Custom(s), V::Custom(s) => SortMode::Custom(s),
V::FromConfig(_) => SortMode::FromConfig, V::FromConfig(_) => SortMode::FromConfig,
V::Builtin(b) => SortMode::Builtin { V::Builtin(b) => SortMode::Builtin {
kind: b.kind().into(), column: b.column().into(),
reverse: b.reverse, reverse: b.reverse,
}, },
} }

View File

@ -4,7 +4,7 @@
use std::sync::Arc; use std::sync::Arc;
use itertools::Itertools; use itertools::Itertools;
use serde_repr::{Deserialize_repr, Serialize_repr}; use serde::{Deserialize, Serialize};
use strum::{Display, EnumIter, EnumString}; use strum::{Display, EnumIter, EnumString};
use crate::error::{AnkiError, Result}; use crate::error::{AnkiError, Result};
@ -22,37 +22,47 @@ use crate::{
timestamp::{TimestampMillis, TimestampSecs}, timestamp::{TimestampMillis, TimestampSecs},
}; };
#[derive( #[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy, Display, EnumIter, EnumString)]
Serialize_repr, Deserialize_repr, Debug, PartialEq, Clone, Copy, Display, EnumString, EnumIter, #[serde(rename_all = "camelCase")]
)]
#[strum(serialize_all = "camelCase")] #[strum(serialize_all = "camelCase")]
#[repr(u8)]
pub enum Column { pub enum Column {
#[serde(rename = "")]
#[strum(serialize = "")] #[strum(serialize = "")]
Custom, Custom,
Answer, Answer,
CardMod, CardMod,
#[serde(rename = "template")]
#[strum(serialize = "template")] #[strum(serialize = "template")]
Cards, Cards,
Deck, Deck,
#[serde(rename = "cardDue")]
#[strum(serialize = "cardDue")] #[strum(serialize = "cardDue")]
Due, Due,
#[serde(rename = "cardEase")]
#[strum(serialize = "cardEase")] #[strum(serialize = "cardEase")]
Ease, Ease,
#[serde(rename = "cardLapses")]
#[strum(serialize = "cardLapses")] #[strum(serialize = "cardLapses")]
Lapses, Lapses,
#[serde(rename = "cardIvl")]
#[strum(serialize = "cardIvl")] #[strum(serialize = "cardIvl")]
Interval, Interval,
#[serde(rename = "noteCrt")]
#[strum(serialize = "noteCrt")] #[strum(serialize = "noteCrt")]
NoteCreation, NoteCreation,
NoteMod, NoteMod,
#[serde(rename = "note")]
#[strum(serialize = "note")] #[strum(serialize = "note")]
Notetype, Notetype,
Question, Question,
#[serde(rename = "cardReps")]
#[strum(serialize = "cardReps")] #[strum(serialize = "cardReps")]
Reps, Reps,
#[serde(rename = "noteFld")]
#[strum(serialize = "noteFld")] #[strum(serialize = "noteFld")]
SortField, SortField,
#[serde(rename = "noteTags")]
#[strum(serialize = "noteTags")]
Tags, Tags,
} }

View File

@ -9,10 +9,9 @@ mod string;
pub(crate) mod undo; pub(crate) mod undo;
pub use self::{bool::BoolKey, string::StringKey}; pub use self::{bool::BoolKey, string::StringKey};
use crate::browser_table; use crate::browser_table::Column;
use crate::prelude::*; use crate::prelude::*;
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Serialize};
use serde_derive::Deserialize;
use serde_repr::{Deserialize_repr, Serialize_repr}; use serde_repr::{Deserialize_repr, Serialize_repr};
use slog::warn; use slog::warn;
use strum::IntoStaticStr; use strum::IntoStaticStr;
@ -48,9 +47,9 @@ pub(crate) enum ConfigKey {
#[strum(to_string = "timeLim")] #[strum(to_string = "timeLim")]
AnswerTimeLimitSecs, AnswerTimeLimitSecs,
#[strum(to_string = "sortType")] #[strum(to_string = "sortType")]
BrowserSortKind, BrowserSortColumn,
#[strum(to_string = "noteSortType")] #[strum(to_string = "noteSortType")]
BrowserNoteSortKind, BrowserNoteSortColumn,
#[strum(to_string = "curDeck")] #[strum(to_string = "curDeck")]
CurrentDeckId, CurrentDeckId,
#[strum(to_string = "curModel")] #[strum(to_string = "curModel")]
@ -131,33 +130,29 @@ impl Collection {
Ok(()) Ok(())
} }
pub(crate) fn get_browser_sort_kind(&self) -> SortKind { pub(crate) fn get_browser_sort_column(&self) -> Column {
self.get_config_default(ConfigKey::BrowserSortKind) self.get_config_optional(ConfigKey::BrowserSortColumn)
.unwrap_or(Column::NoteCreation)
} }
pub(crate) fn get_browser_note_sort_kind(&self) -> SortKind { pub(crate) fn get_browser_note_sort_column(&self) -> Column {
self.get_config_default(ConfigKey::BrowserNoteSortKind) self.get_config_optional(ConfigKey::BrowserNoteSortColumn)
.unwrap_or(Column::NoteCreation)
} }
pub(crate) fn get_desktop_browser_card_columns(&self) -> Option<Vec<browser_table::Column>> { pub(crate) fn get_desktop_browser_card_columns(&self) -> Option<Vec<Column>> {
self.get_config_optional(ConfigKey::DesktopBrowserCardColumns) self.get_config_optional(ConfigKey::DesktopBrowserCardColumns)
} }
pub(crate) fn set_desktop_browser_card_columns( pub(crate) fn set_desktop_browser_card_columns(&mut self, columns: Vec<Column>) -> Result<()> {
&mut self,
columns: Vec<browser_table::Column>,
) -> Result<()> {
self.set_config(ConfigKey::DesktopBrowserCardColumns, &columns) self.set_config(ConfigKey::DesktopBrowserCardColumns, &columns)
} }
pub(crate) fn get_desktop_browser_note_columns(&self) -> Option<Vec<browser_table::Column>> { pub(crate) fn get_desktop_browser_note_columns(&self) -> Option<Vec<Column>> {
self.get_config_optional(ConfigKey::DesktopBrowserNoteColumns) self.get_config_optional(ConfigKey::DesktopBrowserNoteColumns)
} }
pub(crate) fn set_desktop_browser_note_columns( pub(crate) fn set_desktop_browser_note_columns(&mut self, columns: Vec<Column>) -> Result<()> {
&mut self,
columns: Vec<browser_table::Column>,
) -> Result<()> {
self.set_config(ConfigKey::DesktopBrowserNoteColumns, &columns) self.set_config(ConfigKey::DesktopBrowserNoteColumns, &columns)
} }
@ -269,47 +264,6 @@ impl Collection {
} }
} }
#[derive(Deserialize, PartialEq, Debug, Clone, Copy)]
#[serde(rename_all = "camelCase")]
pub enum SortKind {
NoteCards,
#[serde(rename = "noteCrt")]
NoteCreation,
NoteDue,
NoteEase,
#[serde(rename = "noteIvl")]
NoteInterval,
NoteLapses,
NoteMod,
#[serde(rename = "noteFld")]
SortField,
NoteReps,
#[serde(rename = "note")]
Notetype,
#[serde(rename = "noteTags")]
Tags,
CardMod,
#[serde(rename = "cardReps")]
Reps,
#[serde(rename = "cardDue")]
Due,
#[serde(rename = "cardEase")]
Ease,
#[serde(rename = "cardLapses")]
Lapses,
#[serde(rename = "cardIvl")]
Interval,
Deck,
#[serde(rename = "template")]
Cards,
}
impl Default for SortKind {
fn default() -> Self {
Self::NoteCreation
}
}
// 2021 scheduler moves this into deck config // 2021 scheduler moves this into deck config
pub(crate) enum NewReviewMix { pub(crate) enum NewReviewMix {
Mix = 0, Mix = 0,
@ -334,7 +288,7 @@ pub(crate) enum Weekday {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::SortKind; use super::*;
use crate::collection::open_test_collection; use crate::collection::open_test_collection;
use crate::decks::DeckId; use crate::decks::DeckId;
@ -342,7 +296,7 @@ mod test {
fn defaults() { fn defaults() {
let col = open_test_collection(); let col = open_test_collection();
assert_eq!(col.get_current_deck_id(), DeckId(1)); assert_eq!(col.get_current_deck_id(), DeckId(1));
assert_eq!(col.get_browser_sort_kind(), SortKind::SortField); assert_eq!(col.get_browser_sort_column(), Column::SortField);
} }
#[test] #[test]

View File

@ -14,14 +14,8 @@ use rusqlite::types::FromSql;
use std::borrow::Cow; use std::borrow::Cow;
use crate::{ use crate::{
card::CardId, browser_table::Column, card::CardId, card::CardType, collection::Collection, config::BoolKey,
card::CardType, error::Result, notes::NoteId, prelude::AnkiError, search::parser::parse,
collection::Collection,
config::{BoolKey, SortKind},
error::Result,
notes::NoteId,
prelude::AnkiError,
search::parser::parse,
}; };
use sqlwriter::{RequiredTable, SqlWriter}; use sqlwriter::{RequiredTable, SqlWriter};
@ -35,7 +29,7 @@ pub enum SearchItems {
pub enum SortMode { pub enum SortMode {
NoOrder, NoOrder,
FromConfig, FromConfig,
Builtin { kind: SortKind, reverse: bool }, Builtin { column: Column, reverse: bool },
Custom(String), Custom(String),
} }
@ -69,7 +63,7 @@ impl SortMode {
match self { match self {
SortMode::NoOrder => RequiredTable::CardsOrNotes, SortMode::NoOrder => RequiredTable::CardsOrNotes,
SortMode::FromConfig => unreachable!(), SortMode::FromConfig => unreachable!(),
SortMode::Builtin { kind, .. } => kind.required_table(), SortMode::Builtin { column, .. } => column.required_table(),
SortMode::Custom(ref text) => { SortMode::Custom(ref text) => {
if text.contains("n.") { if text.contains("n.") {
if text.contains("c.") { if text.contains("c.") {
@ -85,28 +79,16 @@ impl SortMode {
} }
} }
impl SortKind { impl Column {
fn required_table(self) -> RequiredTable { fn required_table(self) -> RequiredTable {
match self { match self {
SortKind::NoteCards Column::Cards
| SortKind::NoteCreation | Column::NoteCreation
| SortKind::NoteDue | Column::NoteMod
| SortKind::NoteEase | Column::Notetype
| SortKind::SortField | Column::SortField
| SortKind::NoteInterval | Column::Tags => RequiredTable::Notes,
| SortKind::NoteLapses _ => RequiredTable::CardsOrNotes,
| SortKind::NoteMod
| SortKind::NoteReps
| SortKind::Tags
| SortKind::Notetype => RequiredTable::Notes,
SortKind::Cards => RequiredTable::CardsAndNotes,
SortKind::CardMod
| SortKind::Reps
| SortKind::Due
| SortKind::Ease
| SortKind::Lapses
| SortKind::Interval
| SortKind::Deck => RequiredTable::Cards,
} }
} }
} }
@ -144,10 +126,10 @@ impl Collection {
match mode { match mode {
SortMode::NoOrder => (), SortMode::NoOrder => (),
SortMode::FromConfig => unreachable!(), SortMode::FromConfig => unreachable!(),
SortMode::Builtin { kind, reverse } => { SortMode::Builtin { column, reverse } => {
prepare_sort(self, kind, items)?; prepare_sort(self, column, items)?;
sql.push_str(" order by "); sql.push_str(" order by ");
write_order(sql, items, kind, reverse)?; write_order(sql, items, column, reverse)?;
} }
SortMode::Custom(order_clause) => { SortMode::Custom(order_clause) => {
sql.push_str(" order by "); sql.push_str(" order by ");
@ -192,11 +174,11 @@ impl Collection {
if mode == &SortMode::FromConfig { if mode == &SortMode::FromConfig {
*mode = match items { *mode = match items {
SearchItems::Cards => SortMode::Builtin { SearchItems::Cards => SortMode::Builtin {
kind: self.get_browser_sort_kind(), column: self.get_browser_sort_column(),
reverse: self.get_bool(BoolKey::BrowserSortBackwards), reverse: self.get_bool(BoolKey::BrowserSortBackwards),
}, },
SearchItems::Notes => SortMode::Builtin { SearchItems::Notes => SortMode::Builtin {
kind: self.get_browser_note_sort_kind(), column: self.get_browser_note_sort_column(),
reverse: self.get_bool(BoolKey::BrowserNoteSortBackwards), reverse: self.get_bool(BoolKey::BrowserNoteSortBackwards),
}, },
} }
@ -205,15 +187,15 @@ impl Collection {
} }
/// Add the order clause to the sql. /// Add the order clause to the sql.
fn write_order(sql: &mut String, items: SearchItems, kind: SortKind, reverse: bool) -> Result<()> { fn write_order(sql: &mut String, items: SearchItems, column: Column, reverse: bool) -> Result<()> {
let order = match items { let order = match items {
SearchItems::Cards => card_order_from_sortkind(kind), SearchItems::Cards => card_order_from_sort_column(column),
SearchItems::Notes => note_order_from_sortkind(kind), SearchItems::Notes => note_order_from_sort_column(column),
}; };
if order.is_empty() { if order.is_empty() {
return Err(AnkiError::invalid_input(format!( return Err(AnkiError::invalid_input(format!(
"Can't sort {:?} by {:?}.", "Can't sort {:?} by {:?}.",
items, kind items, column
))); )));
} }
if reverse { if reverse {
@ -229,70 +211,69 @@ fn write_order(sql: &mut String, items: SearchItems, kind: SortKind, reverse: bo
Ok(()) Ok(())
} }
fn card_order_from_sortkind(kind: SortKind) -> Cow<'static, str> { fn card_order_from_sort_column(column: Column) -> Cow<'static, str> {
match kind { match column {
SortKind::NoteCreation => "n.id asc, c.ord asc".into(), Column::CardMod => "c.mod asc".into(),
SortKind::NoteMod => "n.mod asc, c.ord asc".into(), Column::Cards => concat!(
SortKind::SortField => "n.sfld collate nocase asc, c.ord asc".into(),
SortKind::CardMod => "c.mod asc".into(),
SortKind::Reps => "c.reps asc".into(),
SortKind::Due => "c.type asc, c.due asc".into(),
SortKind::Ease => format!("c.type = {} asc, c.factor asc", CardType::New as i8).into(),
SortKind::Lapses => "c.lapses asc".into(),
SortKind::Interval => "c.ivl asc".into(),
SortKind::Tags => "n.tags asc".into(),
SortKind::Deck => "(select pos from sort_order where did = c.did) asc".into(),
SortKind::Notetype => "(select pos from sort_order where ntid = n.mid) asc".into(),
SortKind::Cards => concat!(
"coalesce((select pos from sort_order where ntid = n.mid and ord = c.ord),", "coalesce((select pos from sort_order where ntid = n.mid and ord = c.ord),",
// need to fall back on ord 0 for cloze cards // need to fall back on ord 0 for cloze cards
"(select pos from sort_order where ntid = n.mid and ord = 0)) asc" "(select pos from sort_order where ntid = n.mid and ord = 0)) asc"
) )
.into(), .into(),
_ => "".into(), Column::Deck => "(select pos from sort_order where did = c.did) asc".into(),
Column::Due => "c.type asc, c.due asc".into(),
Column::Ease => format!("c.type = {} asc, c.factor asc", CardType::New as i8).into(),
Column::Interval => "c.ivl asc".into(),
Column::Lapses => "c.lapses asc".into(),
Column::NoteCreation => "n.id asc, c.ord asc".into(),
Column::NoteMod => "n.mod asc, c.ord asc".into(),
Column::Notetype => "(select pos from sort_order where ntid = n.mid) asc".into(),
Column::Reps => "c.reps asc".into(),
Column::SortField => "n.sfld collate nocase asc, c.ord asc".into(),
Column::Tags => "n.tags asc".into(),
Column::Answer | Column::Custom | Column::Question => "".into(),
} }
} }
fn note_order_from_sortkind(kind: SortKind) -> Cow<'static, str> { fn note_order_from_sort_column(column: Column) -> Cow<'static, str> {
match kind { match column {
SortKind::Deck Column::CardMod
| SortKind::CardMod | Column::Cards
| SortKind::NoteCards | Column::Deck
| SortKind::NoteDue | Column::Due
| SortKind::NoteEase | Column::Ease
| SortKind::NoteInterval | Column::Interval
| SortKind::NoteLapses | Column::Lapses
| SortKind::NoteReps => "(select pos from sort_order where nid = n.id) asc".into(), | Column::Reps => "(select pos from sort_order where nid = n.id) asc".into(),
SortKind::NoteCreation => "n.id asc".into(), Column::NoteCreation => "n.id asc".into(),
SortKind::SortField => "n.sfld collate nocase asc".into(), Column::NoteMod => "n.mod asc".into(),
SortKind::NoteMod => "n.mod asc".into(), Column::Notetype => "(select pos from sort_order where ntid = n.mid) asc".into(),
SortKind::Tags => "n.tags asc".into(), Column::SortField => "n.sfld collate nocase asc".into(),
SortKind::Notetype => "(select pos from sort_order where ntid = n.mid) asc".into(), Column::Tags => "n.tags asc".into(),
_ => "".into(), Column::Answer | Column::Custom | Column::Question => "".into(),
} }
} }
fn prepare_sort(col: &mut Collection, kind: SortKind, items: SearchItems) -> Result<()> { fn prepare_sort(col: &mut Collection, column: Column, items: SearchItems) -> Result<()> {
use SortKind::*; let sql = match items {
let notes_mode = items == SearchItems::Notes; SearchItems::Cards => match column {
let sql = match kind { Column::Cards => include_str!("template_order.sql"),
Deck => { Column::Deck => include_str!("deck_order.sql"),
if notes_mode { Column::Notetype => include_str!("notetype_order.sql"),
include_str!("note_decks_order.sql") _ => return Ok(()),
} else { },
include_str!("deck_order.sql") SearchItems::Notes => match column {
} Column::Cards => include_str!("note_cards_order.sql"),
} Column::CardMod => include_str!("card_mod_order.sql"),
CardMod if notes_mode => include_str!("card_mod_order.sql"), Column::Deck => include_str!("note_decks_order.sql"),
Cards => include_str!("template_order.sql"), Column::Due => include_str!("note_due_order.sql"),
NoteCards => include_str!("note_cards_order.sql"), Column::Ease => include_str!("note_ease_order.sql"),
NoteDue => include_str!("note_due_order.sql"), Column::Interval => include_str!("note_interval_order.sql"),
NoteEase => include_str!("note_ease_order.sql"), Column::Lapses => include_str!("note_lapses_order.sql"),
NoteInterval => include_str!("note_interval_order.sql"), Column::Reps => include_str!("note_reps_order.sql"),
NoteLapses => include_str!("note_lapses_order.sql"), Column::Notetype => include_str!("notetype_order.sql"),
NoteReps => include_str!("note_reps_order.sql"), _ => return Ok(()),
Notetype => include_str!("notetype_order.sql"), },
_ => return Ok(()),
}; };
col.storage.db.execute_batch(sql)?; col.storage.db.execute_batch(sql)?;