docs: clarify Claro v1 status and validation
This commit is contained in:
@@ -1,13 +1,122 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Tiny Claro IDE helper stub for v1.17.26.
|
||||
It prints completion words. A real Language Server Protocol service can build on this.
|
||||
"""Small Claro editor/LSP helper.
|
||||
|
||||
This is not a full JSON-RPC Language Server yet. It is a stable helper that
|
||||
editor plugins can call to get metadata, completions, and diagnostics without
|
||||
re-implementing Claro parsing.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
EXE = ROOT / ("claro.exe" if os.name == "nt" else "claro")
|
||||
|
||||
KEYWORDS = [
|
||||
"SAY", "ASK", "SET", "IF", "ELSE", "END", "REPEAT", "TEACH", "DO",
|
||||
"CLASS", "NEW", "START TASK", "WAIT TASK", "HTTP GET", "OPEN WINDOW",
|
||||
"CLEAR SCREEN", "DRAW TEXT", "UPDATE SCREEN", "CLOSE WINDOW",
|
||||
"TYPE OF", "CHECK TYPE",
|
||||
"SAY", "ASK", "SET", "IF", "ELSE", "ENDIF", "END", "REPEAT", "UNTIL",
|
||||
"TEACH", "LEARNED", "DO", "RETURN", "CLASS", "HAS", "NEW", "IMPORT",
|
||||
"TRY", "CATCH", "ENDTRY", "START TASK", "WAIT TASK", "HTTP CHECK",
|
||||
"HTTP GET", "HTTP SAVE", "OPEN WINDOW", "CLEAR SCREEN", "DRAW TEXT",
|
||||
"UPDATE SCREEN", "CLOSE WINDOW", "TYPE OF", "CHECK TYPE",
|
||||
]
|
||||
TYPES = ["NUMBER", "TEXT", "YESNO", "LIST", "MAP", "OBJECT", "ANY"]
|
||||
for word in KEYWORDS + TYPES:
|
||||
print(word)
|
||||
TYPES = [
|
||||
"NUMBER", "TEXT", "YESNO", "LIST", "LIST OF TEXT", "LIST OF NUMBER",
|
||||
"LIST OF YESNO", "MAP", "MAP OF TEXT", "MAP OF NUMBER", "MAP OF YESNO",
|
||||
"OBJECT", "ANY",
|
||||
]
|
||||
COMMANDS = [
|
||||
{"name": "check", "usage": "claro check file.claro"},
|
||||
{"name": "typecheck", "usage": "claro typecheck file.claro"},
|
||||
{"name": "fmt", "usage": "claro fmt file.claro"},
|
||||
]
|
||||
|
||||
DIAG_RE = re.compile(r"^(?P<file>.*?):(?P<line>\d+):\s*(?P<message>.*)$")
|
||||
|
||||
|
||||
def print_json(value: object) -> int:
|
||||
print(json.dumps(value, indent=2))
|
||||
return 0
|
||||
|
||||
|
||||
def metadata() -> dict:
|
||||
return {
|
||||
"language": "Claro",
|
||||
"version": "v1.18.26",
|
||||
"file_extensions": [".claro"],
|
||||
"keywords": KEYWORDS,
|
||||
"types": TYPES,
|
||||
"commands": COMMANDS,
|
||||
}
|
||||
|
||||
|
||||
def completions() -> dict:
|
||||
return {"keywords": KEYWORDS, "types": TYPES}
|
||||
|
||||
|
||||
def parse_diagnostics(output: str, source: str) -> list[dict]:
|
||||
diagnostics = []
|
||||
for raw in output.splitlines():
|
||||
line = raw.strip()
|
||||
if not line or line == "OK" or line == "Type check OK":
|
||||
continue
|
||||
match = DIAG_RE.match(line)
|
||||
if not match:
|
||||
continue
|
||||
diagnostics.append(
|
||||
{
|
||||
"source": source,
|
||||
"file": match.group("file").replace("\\", "/"),
|
||||
"line": int(match.group("line")),
|
||||
"severity": "error",
|
||||
"message": match.group("message"),
|
||||
}
|
||||
)
|
||||
return diagnostics
|
||||
|
||||
|
||||
def run_claro_command(command: str, path: str) -> list[dict]:
|
||||
result = subprocess.run(
|
||||
[str(EXE), command, path],
|
||||
cwd=ROOT,
|
||||
text=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
return parse_diagnostics(result.stdout, f"claro {command}")
|
||||
|
||||
|
||||
def diagnostics(path: str) -> list[dict]:
|
||||
found = []
|
||||
found.extend(run_claro_command("check", path))
|
||||
found.extend(run_claro_command("typecheck", path))
|
||||
return found
|
||||
|
||||
|
||||
def usage() -> int:
|
||||
print("Usage:")
|
||||
print(" claro_lsp_stub.py metadata")
|
||||
print(" claro_lsp_stub.py completions")
|
||||
print(" claro_lsp_stub.py diagnostics file.claro")
|
||||
return 0
|
||||
|
||||
|
||||
def main(argv: list[str]) -> int:
|
||||
if len(argv) < 2:
|
||||
return usage()
|
||||
cmd = argv[1]
|
||||
if cmd == "metadata":
|
||||
return print_json(metadata())
|
||||
if cmd == "completions":
|
||||
return print_json(completions())
|
||||
if cmd == "diagnostics" and len(argv) >= 3:
|
||||
return print_json(diagnostics(argv[2]))
|
||||
return usage()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main(sys.argv))
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"scopeName": "source.claro",
|
||||
"name": "Claro",
|
||||
"patterns": [
|
||||
{ "name": "keyword.control.claro", "match": "\\b(SAY|ASK|SET|IF|ELSE|END|REPEAT|TEACH|DO|CLASS|NEW|START|TASK|HTTP|OPEN|WINDOW|DRAW|UPDATE|CLOSE|TYPE|CHECK|IS)\\b" },
|
||||
{ "name": "storage.type.claro", "match": "\\b(NUMBER|TEXT|YESNO|LIST|MAP|OBJECT|ANY)\\b" },
|
||||
{ "name": "string.quoted.double.claro", "begin": "\"", "end": "\"" }
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user