summaryrefslogtreecommitdiff
path: root/src/unlock.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/unlock.py')
-rw-r--r--src/unlock.py65
1 files changed, 57 insertions, 8 deletions
diff --git a/src/unlock.py b/src/unlock.py
index 0f954d6..16063ca 100644
--- a/src/unlock.py
+++ b/src/unlock.py
@@ -54,7 +54,7 @@ def _parseUnlockBit(text):
m = COMBINER_RE.match(text, index + 1)
if not m:
- raise UnlockParseError('something unexpected at %d' % (index+1))
+ raise UnlockParseError('something unexpected at position %d' % (index+1))
# what is it?
nextCombiner = m.group(1)
@@ -64,23 +64,52 @@ def _parseUnlockBit(text):
# go right past this, to the next subterm
skip = len(m.group(0))
+ if (index + skip) == endAt:
+ raise UnlockParseError('%s what?!' % (whatCombiner.upper()))
else:
if pLevel == 0:
- raise UnlockParseError('something unexpected at %d' % index)
+ if index == 0:
+ raise UnlockParseError('that\'s not right')
+ else:
+ raise UnlockParseError('something unexpected at position %d' % index)
+
+ if pLevel > 0:
+ raise UnlockParseError('unclosed parenthesis')
# now that we're here, we must have parsed these subterms
# do we have a combiner?
if whatCombiner is None:
- assert len(subTerms) == 1
+ if len(subTerms) != 1:
+ raise UnlockParseError('unclosed parenthesis')
return _parseUnlockBit(subTerms[0][2])
else:
return (whatCombiner, map(lambda x: _parseUnlockBit(x[2]), subTerms))
+def stringifyUnlockData(data):
+ kind = data[0]
+
+ if kind == 'always':
+ return ''
+ elif kind == 'level':
+ return '%02d-%02d%s' % (data[1], data[2], (' secret' if data[3] else ''))
+ elif kind == 'and' or kind == 'or':
+ return (' %s ' % kind).join(map(lambda x: '(%s)' % stringifyUnlockData(x), data[1]))
+
if __name__ == '__main__':
- print repr(parseUnlockText('((01-01 secret) and (01-02)) or (02-99 secret) or (01-01)'))
+ p1 = parseUnlockText('((01-01 secret) and (01-02)) or (02-99 secret) or (01-01)')
+ p2 = parseUnlockText('(1-1 secret) or ((1-2) and (1-3 secret)) or (2-1)')
+
+ print
+ print repr(p1)
+ print
+ print stringifyUnlockData(p1)
+ print
+ print repr(p2)
+ print
+ print stringifyUnlockData(p2)
from sys import exit
exit()
@@ -109,7 +138,8 @@ class KPUnlockSpecDialog(QtGui.QDialog):
<li>(01-01 secret) and (01-02) - <i>combine two criteria</i></li>
<li>((01-01 secret) or (01-02)) and (01-04) - <i>nested criteria</i></li>
</ul>
- Each criterion used on the sides of AND and OR must be surrounded by parentheses.<br>
+ Each criterion used on the sides of AND and OR must be surrounded by parentheses.
+ You may use more than one, for example: <i>(01-01) or (02-02) or (03-03)</i><br>
<br>
To leave this {0} permanently unlocked, leave the box blank.
""".format(forWhat, unlockAdjective)
@@ -120,19 +150,38 @@ class KPUnlockSpecDialog(QtGui.QDialog):
self.textBox = QtGui.QLineEdit()
self.textBox.textChanged.connect(self.checkInputValidity)
+ self.statusLabel = QtGui.QLabel()
+ self.statusLabel.setWordWrap(True)
+
self.buttons = QtGui.QDialogButtonBox(
QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
self.buttons.accepted.connect(self.accept)
self.buttons.rejected.connect(self.reject)
- self.layout = QtGui.VBoxLayout()
+ self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.label)
self.layout.addWidget(self.textBox)
+ self.layout.addWidget(self.statusLabel)
self.layout.addWidget(self.buttons)
self.setLayout(self.layout)
+ def setSpec(self, spec):
+ self.textBox.setText(stringifyUnlockData(spec))
+
def checkInputValidity(self, text):
- self.parsed = parseUnlockText(text)
- self.buttons.button(QtGui.QDialogButtonBox.Ok).setEnabled(not (self.parsed is None))
+ valid = True
+ try:
+ self.spec = parseUnlockText(str(text))
+ except UnlockParseError as e:
+ valid = False
+ error = str(e)
+ self.spec = None
+
+ self.buttons.button(QtGui.QDialogButtonBox.Ok).setEnabled(valid)
+
+ if valid:
+ self.statusLabel.setText('Your input is valid.')
+ else:
+ self.statusLabel.setText('[!] %s' % error)