diff --git a/app.py b/app.py index e73c565..864ca31 100644 --- a/app.py +++ b/app.py @@ -212,10 +212,11 @@ def founding_projections(key: str) -> dict[str, str]: vowels = [p for p in ph if p in ARPA_VOWELS] if vowels: out["slant"] = "v:" + " ".join(vowels) - if len(ph) > 1 and ph[1] not in ARPA_VOWELS: - out["vc"] = "c:" + ph[0] + " " + _coda_class(ph[1]) - else: - out["vc"] = "c:" + ph[0] + if len(vowels) <= 2: # consonance only for short rimes + if len(ph) > 1 and ph[1] not in ARPA_VOWELS: + out["vc"] = "c:" + ph[0] + " " + _coda_class(ph[1]) + else: + out["vc"] = "c:" + ph[0] mk = _multi_key(vowels) if mk: out["multi"] = mk @@ -336,6 +337,11 @@ def vc_key(word: str) -> str | None: tail = pl[start:] if not tail or not tail[0][-1].isdigit(): return None + # consonance is an ENDING sound: allow at most one trailing syllable + # (people/sleep), but not a stress buried deep in a long word + # (meticulous's IH-K under -ulous shouldn't consonance-rhyme quick) + if sum(p[-1].isdigit() for p in tail) > 2: + return None key = DIGITS.sub("", tail[0]) if len(tail) > 1: key += " " + _coda_class(tail[1]) diff --git a/tests/test_rhymes.py b/tests/test_rhymes.py index a2daf45..4a04380 100644 --- a/tests/test_rhymes.py +++ b/tests/test_rhymes.py @@ -754,3 +754,16 @@ def test_near_miss_radar(): res = analyze(Draft(text=text)) near = {res["lines"][t["l"]][t["s"]:t["e"]].lower() for t in res["near"]} assert near == {"hand", "bond"} + + +def test_consonance_only_on_final_syllable(): + # me-TIC-ulous's mid-word IH-K must not consonance-rhyme quick + text = "a maverick imagine that I travel quick\nso meticulous and ridiculous" + res = analyze(Draft(text=text)) + from collections import defaultdict + bg = defaultdict(set) + for t in res["tokens"]: + bg[t["g"]].add(res["lines"][t["l"]][t["s"]:t["e"]].lower()) + assert not any({"meticulous", "quick"} <= s for s in bg.values()) + # bliss/exist (final-syllable consonance) still works + group_with("bliss whisps in the nights exist", "bliss", "exist")