commit 1684e813aa5fc22318fcca74764858ad7e725638
parent adb3aff10a7284eac1a1f1b3a813a5d49be7643f
Author: Antoine Amarilli <a3nm@a3nm.net>
Date: Sun, 31 Jul 2011 16:28:12 -0400
fixes and stuff
Diffstat:
4 files changed, 56 insertions(+), 27 deletions(-)
diff --git a/error.py b/error.py
@@ -1,3 +1,5 @@
+import common
+import hemistiches
class Error:
def __init__(self):
@@ -13,13 +15,15 @@ class Error:
self.prefix = "stdin:%d: " % self.line_no
def say(self, l):
- print(self.prefix + l)
+ return self.prefix + l
def report(self, s, t = []):
- self.say("error: %s" % (s))
- self.say("Line is: %s" % (self.line))
- for l in t:
- self.say(l)
+ l = []
+ l.append(self.say("error: %s" % (s)))
+ l.append(self.say("Line is: %s" % (self.line)))
+ for x in t:
+ l.append(self.say(x))
+ return '\n'.join(l)
class ErrorBadRhyme(Error):
def __init__(self, expected, inferred):
@@ -28,13 +32,16 @@ class ErrorBadRhyme(Error):
self.inferred = inferred
def report(self):
- Error.report(self, "Bad rhyme %s for type %s (expected %s, inferred %s)"
+ return Error.report(self, "Bad rhyme %s for type %s (expected %s, inferred %s)"
% (self.kind, self.get_id(), self.fmt(self.expected),
self.fmt(self.inferred)))
class ErrorBadRhymeGenre(ErrorBadRhyme):
def fmt(self, l):
- return ' or '.join(list(l))
+ result = ' or '.join(list(l))
+ if result == '':
+ result = "?"
+ return result
def get_id(self):
return self.pattern.femid
@@ -45,16 +52,18 @@ class ErrorBadRhymeGenre(ErrorBadRhyme):
class ErrorBadRhymeSound(ErrorBadRhyme):
def fmt(self, l):
+ #TODO handle other types
pron, spel, constraint = l
ok = []
if len(pron) > 0:
ok.append("")
+ return '/'.join(list(pron))
def get_id(self):
return self.pattern.myid
def report(self):
- Error.report(self, "Bad rhyme %s for type %s (expected %s)"
+ return Error.report(self, "Bad rhyme %s for type %s (expected %s)"
% (self.kind, self.pattern.myid, self.fmt(self.expected)))
@property
@@ -78,7 +87,7 @@ class ErrorBadMetric(Error):
for x in [''] + align:
if isinstance(x, tuple):
orig = ""
- while len(line) > 0 and is_vowels(line[0]):
+ while len(line) > 0 and common.is_vowels(line[0]):
orig += line[0]
line = line[1:]
l2 += ('{:^'+str(len(orig))+'}').format(str(x[1]))
@@ -87,28 +96,30 @@ class ErrorBadMetric(Error):
done = False
else:
orig = ""
- while len(line) > 0 and not is_vowels(line[0]):
+ while len(line) > 0 and not common.is_vowels(line[0]):
orig += line[0]
line = line[1:]
if count in hemis.keys() and not done:
done = True
summary.append(str(ccount))
ccount = 0
- summary.append(hemis_types[hemis[count]])
+ summary.append(hemistiches.hemis_types[hemis[count]])
l2 += ('{:^'+str(len(orig))+'}'
- ).format(hemis_types[hemis[count]])
+ ).format(hemistiches.hemis_types[hemis[count]])
else:
l2 += ' ' * len(orig)
- summary.append(str(ccount))
+ summary.append(str(ccount)+':')
result = ''.join(l2)
summary = ('{:^9}').format(''.join(summary))
return summary + result
def report(self):
num = min(len(self.possible), 4)
- Error.report(
+ return Error.report(
self,
- ("Bad metric (expected %s, inferred %d options)" %
- (self.pattern.metric, num)),
- list(map(self.align, self.possible[:num])))
+ ("Bad metric (expected %s, inferred %d option%s)" %
+ (self.pattern.metric, num, ('s' if len(self.possible) != 1 else
+ ''))),
+ list(map(self.align, self.possible[:num]))
+ )
diff --git a/metric.py b/metric.py
@@ -48,10 +48,14 @@ def fit(chunks, pos, left):
def feminine(align, verse):
for a in sure_end_fem:
if verse.endswith(a):
- return True
- if verse.endswith('ent') and align[-2][1] != 1:
- return True
- return False
+ return ['F']
+ if verse.endswith('ent') and align[-2][1] == 0:
+ return ['F'] # mute -ent
+ if verse.endswith('ent') and align[-2][1] > 0 and align[-2][0] == 'e':
+ return ['M'] # non-mute "-ent" by the choice of metric
+ # and now, what? "tient" vs. "lient" for instance,
+ # TODO check pronunciation? :-/
+ return ['M', 'F']
def parse(text, bound):
"""Return possible aligns for text, bound is an upper bound on the
diff --git a/poetlint.py b/poetlint.py
@@ -9,8 +9,8 @@ from pprint import pprint
if len(sys.argv) != 2:
print("Usage: %s TEMPLATE" % sys.argv[0], file=sys.stderr)
- print("Check stdin according to template, report errors on stdout"
- % sys.argv[0], file=sys.stderr)
+ print("Check stdin according to template, report errors on stdout",
+ file=sys.stderr)
sys.exit(1)
f = open(sys.argv[1])
@@ -22,8 +22,9 @@ def run():
line = sys.stdin.readline()
if not line:
break
- for error in template.check(line):
- error.report()
+ errors = template.check(line)
+ for error in errors:
+ print(error.report(), file=sys.stderr)
run()
diff --git a/template.py b/template.py
@@ -31,6 +31,7 @@ class Template:
self.position = 0
self.env = {}
self.femenv = {}
+ self.reject_errors = False
def load(self, stream):
"""Load from a stream"""
@@ -110,7 +111,7 @@ class Template:
self.femenv[pattern.femid] = x
else:
old = list(self.femenv[pattern.femid])
- new = list(set(['F' if x[1] else 'M' for (score, x) in possible]))
+ new = list(set(sum([x[1] for (score, x) in possible], [])))
self.femenv[pattern.femid] &= set(new)
if len(self.femenv[pattern.femid]) == 0:
errors.append(error.ErrorBadRhymeGenre(old, new))
@@ -151,17 +152,26 @@ class Template:
def get(self):
"""Get next state, resetting if needed"""
+ self.old_position = self.position
+ self.old_env = dict(self.env)
+ self.old_femenv = dict(self.femenv)
if self.position >= len(self.template):
self.reset_state()
result = self.template[self.position]
self.position += 1
return result
+ def back(self):
+ """Revert to previous state"""
+ self.position = self.old_position
+ self.env = dict(self.old_env)
+ self.femenv = dict(self.old_femenv)
+
def check(self, line):
"""Check line (wrapper)"""
self.line_no += 1
line = line.rstrip()
- if line == '':
+ if normalize(line) == '':
return []
#possible = [compute(p) for p in possible]
#possible = sorted(possible, key=rate)
@@ -169,5 +179,8 @@ class Template:
for error in errors:
# update errors with line position and pattern
error.pos(line, self.line_no, pattern)
+ if len(errors) > 0 and self.reject_errors:
+ self.back()
+ self.line_no -= 1
return errors