diff --git a/rslib/src/cloze.rs b/rslib/src/cloze.rs index 4ecd4e3a3..f57d07ab0 100644 --- a/rslib/src/cloze.rs +++ b/rslib/src/cloze.rs @@ -43,6 +43,7 @@ mod mathjax_caps { #[derive(Debug)] enum Token<'a> { + // The parameter is the cloze number as is appears in the field content. OpenCloze(u16), Text(&'a str), CloseCloze, @@ -114,6 +115,7 @@ enum TextOrCloze<'a> { #[derive(Debug)] struct ExtractedCloze<'a> { + // `ordinal` is the cloze number as is appears in the field content. ordinal: u16, nodes: Vec>, hint: Option<&'a str>, @@ -409,12 +411,14 @@ pub fn expand_clozes_to_reveal_latex(text: &str) -> String { buf } +// Whether `text` contains any cloze number above 0 pub(crate) fn contains_cloze(text: &str) -> bool { parse_text_with_clozes(text) .iter() .any(|node| matches!(node, TextOrCloze::Cloze(e) if e.ordinal != 0)) } +/// Returns the set of cloze number as they appear in the fields's content. pub fn cloze_numbers_in_string(html: &str) -> HashSet { let mut set = HashSet::with_capacity(4); add_cloze_numbers_in_string(html, &mut set); @@ -432,11 +436,21 @@ fn add_cloze_numbers_in_text_with_clozes(nodes: &[TextOrCloze], set: &mut HashSe } } +/// Add to `set` the cloze numbers as they appear in `field`. #[allow(clippy::implicit_hasher)] pub fn add_cloze_numbers_in_string(field: &str, set: &mut HashSet) { add_cloze_numbers_in_text_with_clozes(&parse_text_with_clozes(field), set) } +/// The set of cloze numbers as they appear in any of the fields from `fields`. +pub fn cloze_number_in_fields(fields: impl IntoIterator>) -> HashSet { + let mut set = HashSet::with_capacity(4); + for field in fields { + add_cloze_numbers_in_string(field.as_ref(), &mut set); + } + set +} + fn strip_html_inside_mathjax(text: &str) -> Cow { MATHJAX.replace_all(text, |caps: &Captures| -> String { format!( diff --git a/rslib/src/notes/service.rs b/rslib/src/notes/service.rs index e5388da3a..aa85dd8a0 100644 --- a/rslib/src/notes/service.rs +++ b/rslib/src/notes/service.rs @@ -1,8 +1,6 @@ // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -use std::collections::HashSet; - -use crate::cloze::add_cloze_numbers_in_string; +use crate::cloze::cloze_number_in_fields; use crate::collection::Collection; use crate::decks::DeckId; use crate::error; @@ -128,10 +126,7 @@ impl crate::services::NotesService for Collection { &mut self, note: anki_proto::notes::Note, ) -> error::Result { - let mut set = HashSet::with_capacity(4); - for field in ¬e.fields { - add_cloze_numbers_in_string(field, &mut set); - } + let set = cloze_number_in_fields(note.fields); Ok(anki_proto::notes::ClozeNumbersInNoteResponse { numbers: set.into_iter().map(|n| n as u32).collect(), }) diff --git a/rslib/src/notetype/cardgen.rs b/rslib/src/notetype/cardgen.rs index 9449fed65..8ee2717ba 100644 --- a/rslib/src/notetype/cardgen.rs +++ b/rslib/src/notetype/cardgen.rs @@ -11,7 +11,7 @@ use rand::Rng; use rand::SeedableRng; use super::Notetype; -use crate::cloze::add_cloze_numbers_in_string; +use crate::cloze::cloze_number_in_fields; use crate::notetype::NotetypeKind; use crate::prelude::*; use crate::template::ParsedTemplate; @@ -148,10 +148,7 @@ impl> CardGenContext { extracted: &ExtractedCardInfo, ) -> Vec { // gather all cloze numbers - let mut set = HashSet::with_capacity(4); - for field in note.fields() { - add_cloze_numbers_in_string(field, &mut set); - } + let set = cloze_number_in_fields(note.fields()); set.into_iter() .filter_map(|cloze_ord| { let card_ord = cloze_ord.saturating_sub(1).min(499); diff --git a/rslib/src/template.rs b/rslib/src/template.rs index 8d353070e..d09ade580 100644 --- a/rslib/src/template.rs +++ b/rslib/src/template.rs @@ -15,7 +15,7 @@ use nom::combinator::map; use nom::sequence::delimited; use regex::Regex; -use crate::cloze::add_cloze_numbers_in_string; +use crate::cloze::cloze_number_in_fields; use crate::error::AnkiError; use crate::error::Result; use crate::error::TemplateError; @@ -673,11 +673,7 @@ pub fn render_card( } fn cloze_is_empty(field_map: &HashMap<&str, Cow>, card_ord: u16) -> bool { - let mut set = HashSet::with_capacity(4); - for field in field_map.values() { - add_cloze_numbers_in_string(field.as_ref(), &mut set); - } - !set.contains(&(card_ord + 1)) + !cloze_number_in_fields(field_map.values()).contains(&(card_ord + 1)) } // Field requirements