Some documentation and reduce copy/paste (#3917)

* NF: document that cloze number are kept as they are in the field

I needed to know because {{c1 generate card 0 for example. And storing
the card ordinal would have been another consistent choice.

* NF: introduce method that return the cloze number in fields

This slightly reduce code duplication.

* Apply suggestions from code review
This commit is contained in:
Arthur Milchior 2025-04-24 11:02:11 +02:00 committed by GitHub
parent fe2c1510ca
commit 7bebcad864
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 20 additions and 18 deletions

View file

@ -43,6 +43,7 @@ mod mathjax_caps {
#[derive(Debug)] #[derive(Debug)]
enum Token<'a> { enum Token<'a> {
// The parameter is the cloze number as is appears in the field content.
OpenCloze(u16), OpenCloze(u16),
Text(&'a str), Text(&'a str),
CloseCloze, CloseCloze,
@ -114,6 +115,7 @@ enum TextOrCloze<'a> {
#[derive(Debug)] #[derive(Debug)]
struct ExtractedCloze<'a> { struct ExtractedCloze<'a> {
// `ordinal` is the cloze number as is appears in the field content.
ordinal: u16, ordinal: u16,
nodes: Vec<TextOrCloze<'a>>, nodes: Vec<TextOrCloze<'a>>,
hint: Option<&'a str>, hint: Option<&'a str>,
@ -409,12 +411,14 @@ pub fn expand_clozes_to_reveal_latex(text: &str) -> String {
buf buf
} }
// Whether `text` contains any cloze number above 0
pub(crate) fn contains_cloze(text: &str) -> bool { pub(crate) fn contains_cloze(text: &str) -> bool {
parse_text_with_clozes(text) parse_text_with_clozes(text)
.iter() .iter()
.any(|node| matches!(node, TextOrCloze::Cloze(e) if e.ordinal != 0)) .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<u16> { pub fn cloze_numbers_in_string(html: &str) -> HashSet<u16> {
let mut set = HashSet::with_capacity(4); let mut set = HashSet::with_capacity(4);
add_cloze_numbers_in_string(html, &mut set); 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)] #[allow(clippy::implicit_hasher)]
pub fn add_cloze_numbers_in_string(field: &str, set: &mut HashSet<u16>) { pub fn add_cloze_numbers_in_string(field: &str, set: &mut HashSet<u16>) {
add_cloze_numbers_in_text_with_clozes(&parse_text_with_clozes(field), set) 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<Item: AsRef<str>>) -> HashSet<u16> {
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<str> { fn strip_html_inside_mathjax(text: &str) -> Cow<str> {
MATHJAX.replace_all(text, |caps: &Captures| -> String { MATHJAX.replace_all(text, |caps: &Captures| -> String {
format!( format!(

View file

@ -1,8 +1,6 @@
// 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 std::collections::HashSet; use crate::cloze::cloze_number_in_fields;
use crate::cloze::add_cloze_numbers_in_string;
use crate::collection::Collection; use crate::collection::Collection;
use crate::decks::DeckId; use crate::decks::DeckId;
use crate::error; use crate::error;
@ -128,10 +126,7 @@ impl crate::services::NotesService for Collection {
&mut self, &mut self,
note: anki_proto::notes::Note, note: anki_proto::notes::Note,
) -> error::Result<anki_proto::notes::ClozeNumbersInNoteResponse> { ) -> error::Result<anki_proto::notes::ClozeNumbersInNoteResponse> {
let mut set = HashSet::with_capacity(4); let set = cloze_number_in_fields(note.fields);
for field in &note.fields {
add_cloze_numbers_in_string(field, &mut set);
}
Ok(anki_proto::notes::ClozeNumbersInNoteResponse { Ok(anki_proto::notes::ClozeNumbersInNoteResponse {
numbers: set.into_iter().map(|n| n as u32).collect(), numbers: set.into_iter().map(|n| n as u32).collect(),
}) })

View file

@ -11,7 +11,7 @@ use rand::Rng;
use rand::SeedableRng; use rand::SeedableRng;
use super::Notetype; use super::Notetype;
use crate::cloze::add_cloze_numbers_in_string; use crate::cloze::cloze_number_in_fields;
use crate::notetype::NotetypeKind; use crate::notetype::NotetypeKind;
use crate::prelude::*; use crate::prelude::*;
use crate::template::ParsedTemplate; use crate::template::ParsedTemplate;
@ -148,10 +148,7 @@ impl<N: Deref<Target = Notetype>> CardGenContext<N> {
extracted: &ExtractedCardInfo, extracted: &ExtractedCardInfo,
) -> Vec<CardToGenerate> { ) -> Vec<CardToGenerate> {
// gather all cloze numbers // gather all cloze numbers
let mut set = HashSet::with_capacity(4); let set = cloze_number_in_fields(note.fields());
for field in note.fields() {
add_cloze_numbers_in_string(field, &mut set);
}
set.into_iter() set.into_iter()
.filter_map(|cloze_ord| { .filter_map(|cloze_ord| {
let card_ord = cloze_ord.saturating_sub(1).min(499); let card_ord = cloze_ord.saturating_sub(1).min(499);

View file

@ -15,7 +15,7 @@ use nom::combinator::map;
use nom::sequence::delimited; use nom::sequence::delimited;
use regex::Regex; 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::AnkiError;
use crate::error::Result; use crate::error::Result;
use crate::error::TemplateError; use crate::error::TemplateError;
@ -673,11 +673,7 @@ pub fn render_card(
} }
fn cloze_is_empty(field_map: &HashMap<&str, Cow<str>>, card_ord: u16) -> bool { fn cloze_is_empty(field_map: &HashMap<&str, Cow<str>>, card_ord: u16) -> bool {
let mut set = HashSet::with_capacity(4); !cloze_number_in_fields(field_map.values()).contains(&(card_ord + 1))
for field in field_map.values() {
add_cloze_numbers_in_string(field.as_ref(), &mut set);
}
!set.contains(&(card_ord + 1))
} }
// Field requirements // Field requirements