Doug Edmunds
unread,Dec 11, 2025, 8:58:04 PM (yesterday) Dec 11Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to Picat
I used chatgpt to develop a formatter for picat. Through some trial and error, we got it working rather well. It is a python program. Give the output file a different name, because this script will overwrite files without warning. Example:
python picat_formatter.py farmer-fox.pi farmer-fox-formatted.pi
Here is the code and a downloadable.
#!/usr/bin/env python3
"""
picat_formatter.py - Picat formatter with proper indentation.
Usage:
python picat_formatter.py input.pi output.pi
Features:
- Indents lines after => and ?=> (rule bodies)
- Indents inside control structures: foreach, while, if, try, else, elseif, do
- Dedents after 'end' and resets after periods
- Keeps directives (table, import, include, index, etc.) unindented
- Preserves blank lines
"""
import sys
import re
from pathlib import Path
# Keywords that increase indentation
indent_keywords = ['=>', '?=>', 'foreach', 'while', 'if', 'try', 'else', 'elseif', 'do']
# Keywords that decrease indentation
dedent_keywords = ['end']
def is_directive(line):
"""Detect Picat compiler directives"""
return bool(re.match(r'^\s*(table|import|include|export|index|pragma|cp_option|sat_option)\b', line))
def format_picat(lines, indent_size=4):
out = []
prev_blank = False
indent_level = 0
for line in lines:
stripped = line.strip()
# Skip multiple blank lines
if stripped == "":
if not prev_blank:
out.append("")
prev_blank = True
continue
prev_blank = False
# Dedent if line starts with a dedent keyword
if any(stripped.startswith(k) for k in dedent_keywords):
indent_level = max(indent_level - 1, 0)
# Insert blank line before directives if previous line is not blank
if is_directive(stripped) and out and out[-1].strip() != "":
out.append("")
# Determine the current indent for this line
current_indent = 0 if is_directive(stripped) else indent_level * indent_size
indented_line = " " * current_indent + stripped
out.append(indented_line)
# Reset indentation after period (clause end)
if stripped.endswith("."):
indent_level = 0
else:
# Increase indent if the line contains any indent keyword
if any(k in stripped for k in indent_keywords):
indent_level += 1
return out
def main():
if len(sys.argv) != 3:
print("Usage: python picat_formatter.py input.pi output.pi")
sys.exit(1)
infile, outfile = sys.argv[1], sys.argv[2]
infile_path = Path(infile)
outfile_path = Path(outfile)
# Read file
lines = infile_path.read_text(encoding="utf-8").splitlines()
# Format
formatted = format_picat(lines)
# Write output
outfile_path.write_text("\n".join(formatted) + "\n", encoding="utf-8")
print(f"Formatted Picat saved to {outfile_path}")
if __name__ == "__main__":
main()