diff --git a/src/interscript/engine.py b/src/interscript/engine.py index 39c7c00..0d4afad 100644 --- a/src/interscript/engine.py +++ b/src/interscript/engine.py @@ -176,7 +176,7 @@ def _run_op(self, op: dict, text: str) -> str: ) if sep != "": out = re.sub( - re.escape(sep) + "(.)", + f"(?<={re.escape(sep)})(.)", lambda m: m.group(1).upper(), out, ) diff --git a/src/interscript/isc.py b/src/interscript/isc.py index 177e30d..ff132c5 100644 --- a/src/interscript/isc.py +++ b/src/interscript/isc.py @@ -655,7 +655,9 @@ def _render_item(item: dict, aliases: dict[str, str]) -> str: return " + ".join(_render_item(part, aliases) for part in item["parts"]) if kind == "set": items = item["items"] - if all(sub["type"] == "string" for sub in items): + if all(sub["type"] == "string" for sub in items) and all( + len(sub["value"]) == 1 for sub in items + ): return f'any("{_escape("".join(sub["value"] for sub in items))}")' return "any([" + ", ".join(_render_item(sub, aliases) for sub in items) + "])" if kind == "range": @@ -751,6 +753,12 @@ def _repl_of(item: dict, aliases: dict[str, str]) -> str: return "".join(_repl_of(part, aliases) for part in item["parts"]) if kind == "capture": return f"${item['index']}" + if kind == "set": + # A to-position any() lists alternative spellings; the Ruby + # runtime picks the first in non-iterating mode. + if not item["items"]: + return "" + return _repl_of(item["items"][0], aliases) if kind == "alias_ref": name = item["name"] if name not in aliases: diff --git a/tests/test_isc.py b/tests/test_isc.py index b8d715d..e39095e 100644 --- a/tests/test_isc.py +++ b/tests/test_isc.py @@ -192,3 +192,22 @@ def test_title_case_word_separator(): "kind": "title_case", "word_separator": "", } + + +def test_any_in_result_picks_first_alternative(): + src = 'system "x" { stage main { sub any("ab") any(["XA", "YB"]) } }' + tree = isc_to_tree(src) + subst = tree["stages"][0]["children"][0] + assert subst["result"] == "XA" + + +def test_any_in_result_nested_first(): + src = 'system "x" { stage main { sub "a" any([any("XY"), "Z"]) } }' + tree = isc_to_tree(src) + assert tree["stages"][0]["children"][0]["result"] == "X" + + +def test_any_in_result_none_first(): + src = 'system "x" { stage main { sub "a" any([none, " "]) } }' + tree = isc_to_tree(src) + assert tree["stages"][0]["children"][0]["result"] == ""