diff --git a/proto/backend.proto b/proto/backend.proto
index 71a68154c..8c240d5a3 100644
--- a/proto/backend.proto
+++ b/proto/backend.proto
@@ -52,6 +52,7 @@ message InvalidInputError {
message TemplateParseError {
string info = 1;
+ bool q_side = 2;
}
message TemplateRequirementsIn {
diff --git a/pylib/anki/template.py b/pylib/anki/template.py
index 894058242..cbd0d9226 100644
--- a/pylib/anki/template.py
+++ b/pylib/anki/template.py
@@ -121,7 +121,14 @@ def render_card(
try:
output = render_card_from_context(ctx)
except anki.rsbackend.BackendException as e:
- errmsg = _("Card template has a problem:") + f"
{e}"
+ # fixme: specific exception in 2.1.21
+ err = e.args[0].template_parse
+ if err.q_side:
+ side = _("Front")
+ else:
+ side = _("Back")
+ errmsg = _("{} template has a problem:").format(side) + f"
{e}"
+ errmsg += "
{}".format(_("More info"))
output = TemplateRenderOutput(
question_text=errmsg,
answer_text=errmsg,
diff --git a/rslib/src/backend.rs b/rslib/src/backend.rs
index 04505055a..c0a318d7e 100644
--- a/rslib/src/backend.rs
+++ b/rslib/src/backend.rs
@@ -27,7 +27,9 @@ impl std::convert::From for pt::BackendError {
use pt::backend_error::Value as V;
let value = match err {
AnkiError::InvalidInput { info } => V::InvalidInput(pt::InvalidInputError { info }),
- AnkiError::TemplateError { info } => V::TemplateParse(pt::TemplateParseError { info }),
+ AnkiError::TemplateError { info, q_side } => {
+ V::TemplateParse(pt::TemplateParseError { info, q_side })
+ }
};
pt::BackendError { value: Some(value) }
diff --git a/rslib/src/err.rs b/rslib/src/err.rs
index 9b50a9d30..ceb9626bf 100644
--- a/rslib/src/err.rs
+++ b/rslib/src/err.rs
@@ -11,7 +11,7 @@ pub enum AnkiError {
InvalidInput { info: String },
#[fail(display = "invalid card template: {}", info)]
- TemplateError { info: String },
+ TemplateError { info: String, q_side: bool },
}
// error helpers
@@ -34,33 +34,3 @@ pub enum TemplateError {
field: String,
},
}
-
-impl From for AnkiError {
- fn from(terr: TemplateError) -> Self {
- AnkiError::TemplateError {
- info: match terr {
- TemplateError::NoClosingBrackets(context) => {
- format!("missing '}}}}' in '{}'", context)
- }
- TemplateError::ConditionalNotClosed(tag) => format!("missing '{{{{/{}}}}}'", tag),
- TemplateError::ConditionalNotOpen {
- closed,
- currently_open,
- } => {
- if let Some(open) = currently_open {
- format!("Found {{{{/{}}}}}, but expected {{{{/{}}}}}", closed, open)
- } else {
- format!(
- "Found {{{{/{}}}}}, but missing '{{{{#{}}}}}' or '{{{{^{}}}}}'",
- closed, closed, closed
- )
- }
- }
- TemplateError::FieldNotFound { field, filters } => format!(
- "found '{{{{{}{}}}}}', but there is no field called '{}'",
- filters, field, field
- ),
- },
- }
- }
-}
diff --git a/rslib/src/template.rs b/rslib/src/template.rs
index cdf0b5995..739c771c6 100644
--- a/rslib/src/template.rs
+++ b/rslib/src/template.rs
@@ -1,7 +1,7 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-use crate::err::{Result, TemplateError};
+use crate::err::{AnkiError, Result, TemplateError};
use crate::template_filters::apply_filters;
use lazy_static::lazy_static;
use nom;
@@ -189,6 +189,33 @@ fn parse_inner<'a, I: Iterator- >>>(
}
}
+fn template_error_to_anki_error(err: TemplateError, q_side: bool) -> AnkiError {
+ AnkiError::TemplateError {
+ info: match err {
+ TemplateError::NoClosingBrackets(context) => format!("Missing '}}}}' in '{}'", context),
+ TemplateError::ConditionalNotClosed(tag) => format!("Missing '{{{{/{}}}}}'", tag),
+ TemplateError::ConditionalNotOpen {
+ closed,
+ currently_open,
+ } => {
+ if let Some(open) = currently_open {
+ format!("Found {{{{/{}}}}}, but expected {{{{/{}}}}}", closed, open)
+ } else {
+ format!(
+ "Found {{{{/{}}}}}, but missing '{{{{#{}}}}}' or '{{{{^{}}}}}'",
+ closed, closed, closed
+ )
+ }
+ }
+ TemplateError::FieldNotFound { field, filters } => format!(
+ "Found '{{{{{}{}}}}}', but there is no field called '{}'",
+ filters, field, field
+ ),
+ },
+ q_side,
+ }
+}
+
// Legacy support
//----------------------------------------
@@ -438,12 +465,16 @@ pub fn render_card(
// question side
let qnorm = without_legacy_template_directives(qfmt);
- let qnodes = ParsedTemplate::from_text(qnorm.as_ref())?.render(&context)?;
+ let qnodes = ParsedTemplate::from_text(qnorm.as_ref())
+ .and_then(|tmpl| tmpl.render(&context))
+ .map_err(|e| template_error_to_anki_error(e, true))?;
// answer side
context.question_side = false;
let anorm = without_legacy_template_directives(afmt);
- let anodes = ParsedTemplate::from_text(anorm.as_ref())?.render(&context)?;
+ let anodes = ParsedTemplate::from_text(anorm.as_ref())
+ .and_then(|tmpl| tmpl.render(&context))
+ .map_err(|e| template_error_to_anki_error(e, false))?;
Ok((qnodes, anodes))
}