mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
support matches on card properties
This commit is contained in:
parent
a76d34dc19
commit
3755a8f82d
2 changed files with 66 additions and 1 deletions
40
anki/find.py
40
anki/find.py
|
@ -14,6 +14,7 @@ SEARCH_TEMPLATE = 4
|
|||
SEARCH_FIELD = 5
|
||||
SEARCH_MODEL = 6
|
||||
SEARCH_DECK = 7
|
||||
SEARCH_PROP = 8
|
||||
|
||||
# Tools
|
||||
##########################################################################
|
||||
|
@ -119,6 +120,8 @@ and c.nid=n.id %s""" % (q, order)
|
|||
self._findModel(token, isNeg)
|
||||
elif type == SEARCH_DECK:
|
||||
self._findDeck(token, isNeg)
|
||||
elif type == SEARCH_PROP:
|
||||
self._findProp(token, isNeg)
|
||||
else:
|
||||
self._findText(token, isNeg, c)
|
||||
|
||||
|
@ -161,6 +164,40 @@ and c.nid=n.id %s""" % (q, order)
|
|||
else:
|
||||
self.lims['valid'] = False
|
||||
|
||||
def _findProp(self, val, neg):
|
||||
# extract
|
||||
m = re.match("(^.+?)(<=|>=|=|<|>)(.+?$)", val)
|
||||
if not m:
|
||||
self.lims['valid'] = False
|
||||
return
|
||||
prop, cmp, val = m.groups()
|
||||
prop = prop.lower()
|
||||
# is val valid?
|
||||
try:
|
||||
if prop == "ease":
|
||||
val = float(val)
|
||||
else:
|
||||
val = int(val)
|
||||
except ValueError:
|
||||
self.lims['valid'] = False
|
||||
return
|
||||
# is prop valid?
|
||||
if prop not in ("due", "ivl", "reps", "lapses", "ease"):
|
||||
self.lims['valid'] = False
|
||||
return
|
||||
# query
|
||||
extra = "not" if neg else ""
|
||||
if prop == "due":
|
||||
val += self.col.sched.today
|
||||
# only valid for review/daily learning
|
||||
self.lims['preds'].append("queue in (2,3)")
|
||||
elif prop == "ease":
|
||||
prop = "factor"
|
||||
val = int(val*1000)
|
||||
sql = "%s (%s %s %s)" % ("not" if neg else "",
|
||||
prop, cmp, val)
|
||||
self.lims['preds'].append(sql)
|
||||
|
||||
def _findText(self, val, neg, c):
|
||||
val = val.replace("*", "%")
|
||||
if not self.full:
|
||||
|
@ -378,6 +415,9 @@ n.mid in %s and n.id %s in %s""" % (
|
|||
elif token['value'].startswith("deck:"):
|
||||
token['value'] = token['value'][5:].lower()
|
||||
type = SEARCH_DECK
|
||||
elif token['value'].startswith("prop:"):
|
||||
token['value'] = token['value'][5:].lower()
|
||||
type = SEARCH_PROP
|
||||
elif token['value'].startswith("nid:") and len(token['value']) > 4:
|
||||
dec = token['value'][4:]
|
||||
try:
|
||||
|
|
|
@ -68,8 +68,8 @@ def test_findCards():
|
|||
assert len(deck.findCards("-is:due")) == 4
|
||||
c.queue = -1
|
||||
# ensure this card gets a later mod time
|
||||
import time; time.sleep(1)
|
||||
c.flush()
|
||||
deck.db.execute("update cards set mod = mod + 1 where id = ?", c.id)
|
||||
assert deck.findCards("is:suspended") == [c.id]
|
||||
# nids
|
||||
assert deck.findCards("nid:54321") == []
|
||||
|
@ -135,6 +135,31 @@ def test_findCards():
|
|||
assert len(deck.findCards("deck:default")) == 7
|
||||
assert len(deck.findCards("deck:default::child")) == 1
|
||||
assert len(deck.findCards("deck:default -deck:default::*")) == 6
|
||||
# properties
|
||||
id = deck.db.scalar("select id from cards limit 1")
|
||||
deck.db.execute(
|
||||
"update cards set queue=2, ivl=10, reps=20, due=30, factor=2200 "
|
||||
"where id = ?", id)
|
||||
assert len(deck.findCards("prop:ivl>5")) == 1
|
||||
assert len(deck.findCards("prop:ivl<5")) > 1
|
||||
assert len(deck.findCards("prop:ivl>=5")) == 1
|
||||
assert len(deck.findCards("prop:ivl=9")) == 0
|
||||
assert len(deck.findCards("prop:ivl=10")) == 1
|
||||
assert len(deck.findCards("prop:due>0")) == 1
|
||||
# due dates should work
|
||||
deck.sched.today = 15
|
||||
assert len(deck.findCards("prop:due=14")) == 0
|
||||
assert len(deck.findCards("prop:due=15")) == 1
|
||||
assert len(deck.findCards("prop:due=16")) == 0
|
||||
# including negatives
|
||||
deck.sched.today = 32
|
||||
assert len(deck.findCards("prop:due=-1")) == 0
|
||||
assert len(deck.findCards("prop:due=-2")) == 1
|
||||
# ease factors
|
||||
assert len(deck.findCards("prop:ease=2.3")) == 0
|
||||
assert len(deck.findCards("prop:ease=2.2")) == 1
|
||||
assert len(deck.findCards("prop:ease>2")) == 1
|
||||
assert len(deck.findCards("-prop:ease>2")) > 1
|
||||
|
||||
def test_findReplace():
|
||||
deck = getEmptyDeck()
|
||||
|
|
Loading…
Reference in a new issue