Adding support for chained modifiers. One can now write e.g. {{cloze:text:Field}} or {{text:cloze:Field}}, it's order independent.

This commit is contained in:
Julien Baley 2014-02-15 13:59:58 +00:00
parent 3b20de173f
commit 7e3597fb8e
3 changed files with 32 additions and 33 deletions

View file

@ -510,13 +510,11 @@ where c.nid = n.id and c.id in %s group by nid""" % ids2str(cids)):
afmt = afmt or template['afmt'] afmt = afmt or template['afmt']
for (type, format) in (("q", qfmt), ("a", afmt)): for (type, format) in (("q", qfmt), ("a", afmt)):
if type == "q": if type == "q":
format = format.replace("{{cloze:", "{{cq:%d:" % ( format = re.sub("{{(.*?)cloze:", r"{{\1cq-%d:" % (data[4]+1), format)
data[4]+1))
format = format.replace("<%cloze:", "<%%cq:%d:" % ( format = format.replace("<%cloze:", "<%%cq:%d:" % (
data[4]+1)) data[4]+1))
else: else:
format = format.replace("{{cloze:", "{{ca:%d:" % ( format = re.sub("{{(.*?)cloze:", r"{{\1ca-%d:" % (data[4]+1), format)
data[4]+1))
format = format.replace("<%cloze:", "<%%ca:%d:" % ( format = format.replace("<%cloze:", "<%%ca:%d:" % (
data[4]+1)) data[4]+1))
fields['FrontSide'] = stripSounds(d['q']) fields['FrontSide'] = stripSounds(d['q'])

View file

@ -569,7 +569,7 @@ select id from notes where mid = ?)""" % " ".join(map),
sflds = splitFields(flds) sflds = splitFields(flds)
map = self.fieldMap(m) map = self.fieldMap(m)
ords = set() ords = set()
matches = re.findall("{{cloze:(.+?)}}", m['tmpls'][0]['qfmt']) matches = re.findall("{{[^}]*?cloze:(?:.*?:)*(.+?)}}", m['tmpls'][0]['qfmt'])
matches += re.findall("<%cloze:(.+?)%>", m['tmpls'][0]['qfmt']) matches += re.findall("<%cloze:(.+?)%>", m['tmpls'][0]['qfmt'])
for fname in matches: for fname in matches:
if fname not in map: if fname not in map:

View file

@ -158,33 +158,34 @@ class Template(object):
return txt return txt
# field modifiers # field modifiers
parts = tag_name.split(':',2) parts = tag_name.split(':')
extra = None extra = None
if len(parts) == 1 or parts[0] == '': if len(parts) == 1 or parts[0] == '':
return '{unknown field %s}' % tag_name return '{unknown field %s}' % tag_name
elif len(parts) == 2: else:
(mod, tag) = parts mods, tag = parts[:-1], parts[-1] #py3k has *mods, tag = parts
elif len(parts) == 3:
(mod, extra, tag) = parts
txt = get_or_attr(context, tag) txt = get_or_attr(context, tag)
#Since 'text:' and oths mods can affect html on which Anki relies to
#process Clozes and Types, we need to make sure cloze/type are always
#treated after all the other mods, regardless of how they're specified
#in the template, so that {{cloze:text: == {{text:cloze:
mods.sort(key=lambda s: s.startswith("cq-") or s.startswith("ca-") or s=="type")
for mod in mods:
# built-in modifiers # built-in modifiers
if mod == 'text': if mod == 'text':
# strip html # strip html
if txt: txt = stripHTML(txt) if txt else ""
return stripHTML(txt)
return ""
elif mod == 'type': elif mod == 'type':
# type answer field; convert it to [[type:...]] for the gui code # type answer field; convert it to [[type:...]] for the gui code
# to process # to process
return "[[%s]]" % tag_name txt = "[[%s]]" % tag_name
elif mod == 'cq' or mod == 'ca': elif mod.startswith('cq-') or mod.startswith('ca-'):
# cloze deletion # cloze deletion
if txt and extra: mod, extra = mod.split("-")
return self.clozeText(txt, extra, mod[1]) txt = self.clozeText(txt, extra, mod[1]) if txt and extra else ""
else:
return ""
else: else:
# hook-based field modifier # hook-based field modifier
txt = runFilter('fmod_' + mod, txt or '', extra, context, txt = runFilter('fmod_' + mod, txt or '', extra, context,