diff --git a/anki/deck.py b/anki/deck.py index 9211922ec..e1b57cf12 100644 --- a/anki/deck.py +++ b/anki/deck.py @@ -482,7 +482,11 @@ select id from cards where fid in (select id from facts where mid = ?)""", if type == "q": format = format.replace("cloze:", "cq:") else: - format = format.replace("cloze:", "ca:") + if model.conf['clozectx']: + name = "cactx:" + else: + name = "ca:" + format = format.replace("cloze:", name) fields = runFilter("mungeFields", fields, model, gname, data, self) html = anki.template.render(format, fields) d[type] = runFilter( diff --git a/anki/models.py b/anki/models.py index bb0b99a1a..a3360cc19 100644 --- a/anki/models.py +++ b/anki/models.py @@ -13,6 +13,7 @@ from anki.lang import _ defaultConf = { 'sortf': 0, 'gid': 1, + 'clozectx': False, } defaultField = { @@ -40,7 +41,7 @@ defaultTemplate = { 'bg': "#fff", 'emptyAns': True, 'typeAns': None, - 'gid': None + 'gid': None, } class Model(object): diff --git a/anki/template/template.py b/anki/template/template.py index 34bc98378..6cc596820 100644 --- a/anki/template/template.py +++ b/anki/template/template.py @@ -130,7 +130,7 @@ class Template(object): func = modifiers[tag_type] replacement = func(self, tag_name, context) template = template.replace(tag, replacement) - except: + except SyntaxError: return u"{{invalid template}}" return template @@ -157,8 +157,10 @@ class Template(object): if txt: return stripHTML(txt) return "" - elif tag_name.startswith("cq:") or tag_name.startswith("ca:"): - m = re.match("c(.):(\d+):(.+)", tag_name) + elif (tag_name.startswith("cq:") or + tag_name.startswith("ca:") or + tag_name.startswith("cactx:")): + m = re.match("c(.+):(\d+):(.+)", tag_name) (type, ord, tag) = (m.group(1), m.group(2), m.group(3)) txt = get_or_attr(context, tag) if txt: @@ -166,8 +168,6 @@ class Template(object): return "" return get_or_attr(context, tag_name, '{unknown field %s}' % tag_name) - # fixme: need a way to conditionally add these, so that including extra - # fields in the question fmt doesn't make empty clozes def clozeText(self, txt, ord, type): reg = clozeReg m = re.search(reg%ord, txt) @@ -180,8 +180,13 @@ class Template(object): txt = re.sub(reg%ord, "...(\\3)", txt) else: txt = re.sub(reg%ord, "...", txt) - else: + elif type == "actx": txt = re.sub(reg%ord, "\\1", txt) + else: + # just the answers + ans = re.findall(reg%ord, txt) + ans = [""+a[0]+"" for a in ans] + return ", ".join(ans) # and display other clozes normally return re.sub(reg%".*?", "\\1", txt) diff --git a/tests/test_models.py b/tests/test_models.py index 8c8483677..7b9969058 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -120,6 +120,11 @@ def test_cloze(): f['Text'] = "hello {{c1::world}}" assert d.addFact(f) == 1 assert "hello ..." in f.cards()[0].q() + # the default is no context + assert "world" in f.cards()[0].a() + assert "hello world" not in f.cards()[0].a() + # check context works too + f.model().conf['clozectx'] = True assert "hello world" in f.cards()[0].a() # and with a comment f = d.newFact() @@ -136,6 +141,13 @@ def test_cloze(): assert "world bar" in c1.a() assert "world ..." in c2.q() assert "world bar" in c2.a() + # if there are multiple answers for a single cloze, they are given in a + # list + f.model().conf['clozectx'] = False + f = d.newFact() + f['Text'] = "a {{c1::b}} {{c1::c}}" + assert d.addFact(f) == 1 + assert "b, c" in f.cards()[0].a() # clozes should be supported in sections too m = d.currentModel() m.templates[0]['qfmt'] = "{{#cloze:1:Text}}{{Notes}}{{/cloze:1:Text}}"