Files
BondGraph/formatter.py
2026-03-08 23:43:57 +01:00

86 lines
2.3 KiB
Python
Executable File

#!/usr/bin/env python3
import sys
import re
from pathlib import Path
INDENT = " " * 4
CLASS_START_RE = re.compile(
r"^\s*(?:partial\s+)?(?:package|model|connector|record|function|block|type|operator)\b"
)
SECTION_RE = re.compile(
r"^\s*(?:equation|algorithm|initial\s+equation|initial\s+algorithm|protected|public)\b"
)
IF_RE = re.compile(r"^\s*if\b.*\bthen\b")
ELSEIF_RE = re.compile(r"^\s*elseif\b.*\bthen\b")
ELSE_RE = re.compile(r"^\s*else\b")
FOR_RE = re.compile(r"^\s*for\b.*\bloop\b")
WHEN_RE = re.compile(r"^\s*when\b.*\bthen\b")
ELSEWHEN_RE = re.compile(r"^\s*elsewhen\b.*\bthen\b")
END_RE = re.compile(r"^\s*end\b")
def format_modelica(text: str) -> str:
lines = text.replace("\t", " ").splitlines()
out = []
indent = 0
for raw in lines:
stripped = raw.strip()
if not stripped:
out.append("")
continue
# Closing constructs outdent before printing
if END_RE.match(stripped):
indent = max(indent - 1, 0)
# else / elseif / elsewhen align with matching if/when
elif ELSE_RE.match(stripped) or ELSEIF_RE.match(stripped) or ELSEWHEN_RE.match(stripped):
indent = max(indent - 1, 0)
# Sections stay at model level, not one level deeper
elif SECTION_RE.match(stripped):
indent = max(indent - 1, 0)
out.append(f"{INDENT * indent}{stripped}")
# Increase indent only for real blocks
if CLASS_START_RE.match(stripped):
indent += 1
elif IF_RE.match(stripped):
indent += 1
elif FOR_RE.match(stripped):
indent += 1
elif WHEN_RE.match(stripped):
indent += 1
elif ELSEIF_RE.match(stripped) or ELSE_RE.match(stripped) or ELSEWHEN_RE.match(stripped):
indent += 1
elif SECTION_RE.match(stripped):
indent += 1
return "\n".join(out) + "\n"
def main():
if len(sys.argv) < 2:
print("Usage: python format_mo.py input.mo [output.mo]")
sys.exit(1)
input_file = Path(sys.argv[1])
output_file = Path(sys.argv[2]) if len(sys.argv) > 2 else input_file
text = input_file.read_text(encoding="utf-8")
formatted = format_modelica(text)
output_file.write_text(formatted, encoding="utf-8")
print(f"Formatted {output_file}")
if __name__ == "__main__":
main()