mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
parent
03814fa1c4
commit
19bbcb4cc0
5 changed files with 51 additions and 17 deletions
|
@ -27,6 +27,8 @@ service CardRenderingService {
|
||||||
rpc DecodeIriPaths(generic.String) returns (generic.String);
|
rpc DecodeIriPaths(generic.String) returns (generic.String);
|
||||||
rpc StripHtml(StripHtmlRequest) returns (generic.String);
|
rpc StripHtml(StripHtmlRequest) returns (generic.String);
|
||||||
rpc CompareAnswer(CompareAnswerRequest) returns (generic.String);
|
rpc CompareAnswer(CompareAnswerRequest) returns (generic.String);
|
||||||
|
rpc ExtractClozeForTyping(ExtractClozeForTypingRequest)
|
||||||
|
returns (generic.String);
|
||||||
}
|
}
|
||||||
|
|
||||||
message ExtractAVTagsRequest {
|
message ExtractAVTagsRequest {
|
||||||
|
@ -138,3 +140,8 @@ message CompareAnswerRequest {
|
||||||
string expected = 1;
|
string expected = 1;
|
||||||
string provided = 2;
|
string provided = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ExtractClozeForTypingRequest {
|
||||||
|
string text = 1;
|
||||||
|
uint32 ordinal = 2;
|
||||||
|
}
|
||||||
|
|
|
@ -1219,6 +1219,9 @@ class Collection(DeprecatedNamesMixin):
|
||||||
def compare_answer(self, expected: str, provided: str) -> str:
|
def compare_answer(self, expected: str, provided: str) -> str:
|
||||||
return self._backend.compare_answer(expected=expected, provided=provided)
|
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
|
# Timeboxing
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# fixme: there doesn't seem to be a good reason why this code is in main.py
|
# fixme: there doesn't seem to be a good reason why this code is in main.py
|
||||||
|
|
|
@ -630,23 +630,8 @@ class Reviewer:
|
||||||
|
|
||||||
return re.sub(self.typeAnsPat, repl, buf)
|
return re.sub(self.typeAnsPat, repl, buf)
|
||||||
|
|
||||||
def _contentForCloze(self, txt: str, idx: int) -> str:
|
def _contentForCloze(self, txt: str, idx: int) -> str | None:
|
||||||
matches = re.findall(r"\{\{c%s::(.+?)\}\}" % idx, txt, re.DOTALL)
|
return self.mw.col.extract_cloze_for_typing(txt, idx) or None
|
||||||
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 _getTypedAnswer(self) -> None:
|
def _getTypedAnswer(self) -> None:
|
||||||
self.web.evalWithCallback("getTypedAnswer();", self._onTypedAnswer)
|
self.web.evalWithCallback("getTypedAnswer();", self._onTypedAnswer)
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
use super::Backend;
|
use super::Backend;
|
||||||
use crate::card_rendering::extract_av_tags;
|
use crate::card_rendering::extract_av_tags;
|
||||||
use crate::card_rendering::strip_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;
|
||||||
use crate::latex::extract_latex_expanding_clozes;
|
use crate::latex::extract_latex_expanding_clozes;
|
||||||
use crate::latex::ExtractedLatex;
|
use crate::latex::ExtractedLatex;
|
||||||
|
@ -12,6 +13,7 @@ use crate::notetype::CardTemplateSchema11;
|
||||||
use crate::notetype::RenderCardOutput;
|
use crate::notetype::RenderCardOutput;
|
||||||
use crate::pb;
|
use crate::pb;
|
||||||
pub(super) use crate::pb::card_rendering::cardrendering_service::Service as CardRenderingService;
|
pub(super) use crate::pb::card_rendering::cardrendering_service::Service as CardRenderingService;
|
||||||
|
use crate::pb::card_rendering::ExtractClozeForTypingRequest;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::template::RenderedNode;
|
use crate::template::RenderedNode;
|
||||||
use crate::text::decode_iri_paths;
|
use crate::text::decode_iri_paths;
|
||||||
|
@ -164,6 +166,15 @@ impl CardRenderingService for Backend {
|
||||||
) -> Result<pb::generic::String> {
|
) -> Result<pb::generic::String> {
|
||||||
Ok(compare_answer(&input.expected, &input.provided).into())
|
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(
|
fn rendered_nodes_to_proto(
|
||||||
|
|
|
@ -306,6 +306,21 @@ pub fn reveal_cloze_text_only(text: &str, cloze_ord: u16, question: bool) -> Cow
|
||||||
output.join(", ").into()
|
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
|
/// If text contains any LaTeX tags, render the front and back
|
||||||
/// of each cloze deletion so that LaTeX can be generated. If
|
/// of each cloze deletion so that LaTeX can be generated. If
|
||||||
/// no LaTeX is found, returns an empty string.
|
/// 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]
|
#[test]
|
||||||
fn nested_cloze_plain_text() {
|
fn nested_cloze_plain_text() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
Loading…
Reference in a new issue