Use backend for extracting cloze text to type

Closes #2311
This commit is contained in:
Damien Elmes 2023-01-18 23:05:28 +10:00
parent 03814fa1c4
commit 19bbcb4cc0
5 changed files with 51 additions and 17 deletions

View file

@ -27,6 +27,8 @@ service CardRenderingService {
rpc DecodeIriPaths(generic.String) returns (generic.String);
rpc StripHtml(StripHtmlRequest) returns (generic.String);
rpc CompareAnswer(CompareAnswerRequest) returns (generic.String);
rpc ExtractClozeForTyping(ExtractClozeForTypingRequest)
returns (generic.String);
}
message ExtractAVTagsRequest {
@ -138,3 +140,8 @@ message CompareAnswerRequest {
string expected = 1;
string provided = 2;
}
message ExtractClozeForTypingRequest {
string text = 1;
uint32 ordinal = 2;
}

View file

@ -1219,6 +1219,9 @@ class Collection(DeprecatedNamesMixin):
def compare_answer(self, expected: str, provided: str) -> str:
return self._backend.compare_answer(expected=expected, provided=provided)
def extract_cloze_for_typing(self, text: str, ordinal: int) -> str:
return self._backend.extract_cloze_for_typing(text=text, ordinal=ordinal)
# Timeboxing
##########################################################################
# fixme: there doesn't seem to be a good reason why this code is in main.py

View file

@ -630,23 +630,8 @@ class Reviewer:
return re.sub(self.typeAnsPat, repl, buf)
def _contentForCloze(self, txt: str, idx: int) -> str:
matches = re.findall(r"\{\{c%s::(.+?)\}\}" % idx, txt, re.DOTALL)
if not matches:
return None
def noHint(txt: str) -> str:
if "::" in txt:
return txt.split("::")[0]
return txt
matches = [noHint(txt) for txt in matches]
uniqMatches = set(matches)
if len(uniqMatches) == 1:
txt = matches[0]
else:
txt = ", ".join(matches)
return txt
def _contentForCloze(self, txt: str, idx: int) -> str | None:
return self.mw.col.extract_cloze_for_typing(txt, idx) or None
def _getTypedAnswer(self) -> None:
self.web.evalWithCallback("getTypedAnswer();", self._onTypedAnswer)

View file

@ -4,6 +4,7 @@
use super::Backend;
use crate::card_rendering::extract_av_tags;
use crate::card_rendering::strip_av_tags;
use crate::cloze::extract_cloze_for_typing;
use crate::latex::extract_latex;
use crate::latex::extract_latex_expanding_clozes;
use crate::latex::ExtractedLatex;
@ -12,6 +13,7 @@ use crate::notetype::CardTemplateSchema11;
use crate::notetype::RenderCardOutput;
use crate::pb;
pub(super) use crate::pb::card_rendering::cardrendering_service::Service as CardRenderingService;
use crate::pb::card_rendering::ExtractClozeForTypingRequest;
use crate::prelude::*;
use crate::template::RenderedNode;
use crate::text::decode_iri_paths;
@ -164,6 +166,15 @@ impl CardRenderingService for Backend {
) -> Result<pb::generic::String> {
Ok(compare_answer(&input.expected, &input.provided).into())
}
fn extract_cloze_for_typing(
&self,
input: ExtractClozeForTypingRequest,
) -> Result<pb::generic::String> {
Ok(extract_cloze_for_typing(&input.text, input.ordinal as u16)
.to_string()
.into())
}
}
fn rendered_nodes_to_proto(

View file

@ -306,6 +306,21 @@ pub fn reveal_cloze_text_only(text: &str, cloze_ord: u16, question: bool) -> Cow
output.join(", ").into()
}
pub fn extract_cloze_for_typing(text: &str, cloze_ord: u16) -> Cow<str> {
let mut output = Vec::new();
for node in &parse_text_with_clozes(text) {
reveal_cloze_text_in_nodes(node, cloze_ord, false, &mut output);
}
if output.is_empty() {
"".into()
} else if output.iter().min() == output.iter().max() {
// If all matches are identical text, they get collapsed into a single entry
output.pop().unwrap().into()
} else {
output.join(", ").into()
}
}
/// If text contains any LaTeX tags, render the front and back
/// of each cloze deletion so that LaTeX can be generated. If
/// no LaTeX is found, returns an empty string.
@ -419,6 +434,19 @@ mod test {
);
}
#[test]
fn clozes_for_typing() {
assert_eq!(extract_cloze_for_typing("{{c2::foo}}", 1), "");
assert_eq!(
extract_cloze_for_typing("{{c1::foo}} {{c1::bar}} {{c1::foo}}", 1),
"foo, bar, foo"
);
assert_eq!(
extract_cloze_for_typing("{{c1::foo}} {{c1::foo}} {{c1::foo}}", 1),
"foo"
);
}
#[test]
fn nested_cloze_plain_text() {
assert_eq!(