diff --git a/app.py b/app.py index 0291c18..42808ea 100644 --- a/app.py +++ b/app.py @@ -476,7 +476,22 @@ def analyze(draft: Draft): for i, line in enumerate(lines): if sids[i] is None: continue - matches = list(WORD_RE.finditer(line)) + # ad-libs — anything in (parens) mid-line — are delivery, not + # text: they don't rhyme and can't claim the line-ending slot + adlib, depth, astart = [], 0, None + for j, ch in enumerate(line): + if ch == "(": + if depth == 0: + astart = j + depth += 1 + elif ch == ")" and depth: + depth -= 1 + if depth == 0: + adlib.append((astart, j + 1)) + if depth: + adlib.append((astart, len(line))) + matches = [m for m in WORD_RE.finditer(line) + if not any(s <= m.start() < e for s, e in adlib)] for j, m in enumerate(matches): tokens.append({ "line": i, "start": m.start(), "end": m.end(), diff --git a/static/index.html b/static/index.html index b26d01c..fa42568 100644 --- a/static/index.html +++ b/static/index.html @@ -602,6 +602,10 @@ function buildReadout(){ parts.push(p); } const st = caretStanza(); + if(st){ + const bi = st.lines.indexOf(ln); + if(bi >= 0) parts.unshift(`bar ${bi + 1}/${st.lines.length}`); + } if(st && st.scheme){ const sch = st.scheme.toUpperCase(); const shown = sch.slice(0, 16).split('').join(' ') + (sch.length > 16 ? ' …' : ''); diff --git a/tests/test_rhymes.py b/tests/test_rhymes.py index 18d5db1..1949e56 100644 --- a/tests/test_rhymes.py +++ b/tests/test_rhymes.py @@ -533,3 +533,12 @@ def test_word_inside_grouped_phrase_still_rhymes(): "wastin' all this time with style") group_with(text, "mind", "time") group_with(text, "while", "style") + + +def test_inline_adlibs_excluded(): + # (yeah) is delivery, not text — bunch keeps the line-ending slot + text = ("Six-foot, seven-foot, eight-foot bunch (yeah)\n" + "I roll with the gang, throw a punch (what)") + assert scheme(text) == "aa" + assert "yeah" not in highlighted(text) + group_with(text, "bunch", "punch")