added custom functionality and working with new toml as well, and update cli functions
This commit is contained in:
@@ -56,3 +56,6 @@ ignore = ["E501"]
|
|||||||
|
|
||||||
[tool.ruff.lint.per-file-ignores]
|
[tool.ruff.lint.per-file-ignores]
|
||||||
"pack.py" = ["E501"]
|
"pack.py" = ["E501"]
|
||||||
|
|
||||||
|
[tool.hatch.build.targets.wheel.force-include]
|
||||||
|
"src/foreignthon/template.json" = "foreignthon/template.json"
|
||||||
|
|||||||
@@ -12,18 +12,16 @@ from .transpiler import run_transpiled, transpile_file
|
|||||||
|
|
||||||
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
|
CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
|
||||||
|
|
||||||
|
|
||||||
def _load_effective_pack(project: Path, lang: str) -> dict:
|
def _load_effective_pack(project: Path, lang: str) -> dict:
|
||||||
"""
|
"""
|
||||||
Load installed pack then merge local custom.json on top if configured.
|
Load pack for a file. Priority:
|
||||||
Walks up from project to find .foreignthon.toml.
|
1. custom_pack in .foreignthon.toml — no installed pack needed
|
||||||
|
2. installed pack via entry points
|
||||||
"""
|
"""
|
||||||
import json
|
import json
|
||||||
from .pack import load_pack
|
from .pack import load_pack
|
||||||
|
|
||||||
pack = load_pack(lang)
|
# Walk up to find .foreignthon.toml
|
||||||
|
|
||||||
# Walk up directories to find .foreignthon.toml
|
|
||||||
search = project if project.is_dir() else project.parent
|
search = project if project.is_dir() else project.parent
|
||||||
toml_path = None
|
toml_path = None
|
||||||
for parent in [search, *search.parents]:
|
for parent in [search, *search.parents]:
|
||||||
@@ -32,20 +30,29 @@ def _load_effective_pack(project: Path, lang: str) -> dict:
|
|||||||
toml_path = candidate
|
toml_path = candidate
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# Check for custom_pack first — if found, load it directly
|
||||||
|
# and merge on top of template (no installed pack required)
|
||||||
if toml_path:
|
if toml_path:
|
||||||
for line in toml_path.read_text(encoding="utf-8").splitlines():
|
for line in toml_path.read_text(encoding="utf-8").splitlines():
|
||||||
if line.strip().startswith("custom_pack"):
|
if line.strip().startswith("custom_pack") and not line.strip().startswith("#"):
|
||||||
custom_path = toml_path.parent / line.split("=", 1)[1].strip().strip('"').strip("'")
|
custom_path = toml_path.parent / line.split("=", 1)[1].strip().strip('"').strip("'")
|
||||||
if custom_path.exists():
|
if custom_path.exists():
|
||||||
custom = json.loads(custom_path.read_text(encoding="utf-8"))
|
custom = json.loads(custom_path.read_text(encoding="utf-8"))
|
||||||
|
# If custom pack has meta with a code, it's a standalone pack
|
||||||
|
if custom.get("meta", {}).get("code"):
|
||||||
|
return custom
|
||||||
|
# Otherwise it's an override — merge on top of installed pack
|
||||||
|
pack = load_pack(lang)
|
||||||
for section in ("keywords", "builtins", "exceptions", "stdlib", "error_messages"):
|
for section in ("keywords", "builtins", "exceptions", "stdlib", "error_messages"):
|
||||||
if section in custom:
|
if section in custom:
|
||||||
pack[section] = {**pack.get(section, {}), **custom[section]}
|
pack[section] = {**pack.get(section, {}), **custom[section]}
|
||||||
if "postfix_keywords" in custom:
|
if "postfix_keywords" in custom:
|
||||||
pack["postfix_keywords"] = custom["postfix_keywords"]
|
pack["postfix_keywords"] = custom["postfix_keywords"]
|
||||||
|
return pack
|
||||||
break
|
break
|
||||||
|
|
||||||
return pack
|
# Fall back to installed pack
|
||||||
|
return load_pack(lang)
|
||||||
|
|
||||||
|
|
||||||
def _pick(mapping: dict, english: str, fallback: str) -> str:
|
def _pick(mapping: dict, english: str, fallback: str) -> str:
|
||||||
@@ -104,6 +111,15 @@ def new(name: str, lang: str, no_git: bool):
|
|||||||
click.echo("✗ Current directory is not empty.", err=True)
|
click.echo("✗ Current directory is not empty.", err=True)
|
||||||
raise SystemExit(1)
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
is_custom = lang == "custom"
|
||||||
|
|
||||||
|
if is_custom:
|
||||||
|
lang_code = click.prompt("Language code (e.g. ru, fr, de)")
|
||||||
|
lang_name_en = click.prompt("Language name in English (e.g. Russian)")
|
||||||
|
lang_name_native = click.prompt("Language name in its own script (e.g. Русский)")
|
||||||
|
pack = _make_scaffold_pack(lang_code, lang_name_en, lang_name_native)
|
||||||
|
lang = lang_code
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
pack = _load_effective_pack(project, lang)
|
pack = _load_effective_pack(project, lang)
|
||||||
except PackNotFoundError:
|
except PackNotFoundError:
|
||||||
@@ -113,12 +129,23 @@ def new(name: str, lang: str, no_git: bool):
|
|||||||
|
|
||||||
lang_name = pack["meta"]["native_name"]
|
lang_name = pack["meta"]["native_name"]
|
||||||
|
|
||||||
|
if is_custom:
|
||||||
|
import json
|
||||||
|
(project / "custom.json").write_text(
|
||||||
|
json.dumps(pack, ensure_ascii=False, indent=2),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
toml_custom_line = 'custom_pack = "custom.json"'
|
||||||
|
click.echo(" Created custom.json — fill in your translations!")
|
||||||
|
else:
|
||||||
|
toml_custom_line = '# custom_pack = "custom.json"'
|
||||||
|
|
||||||
(project / ".foreignthon.toml").write_text(
|
(project / ".foreignthon.toml").write_text(
|
||||||
f'[foreignthon]\n'
|
f'[foreignthon]\n'
|
||||||
f'lang = "{lang}"\n'
|
f'lang = "{lang}"\n'
|
||||||
f'\n'
|
f'\n'
|
||||||
f'# Optional: path to a local JSON that overrides pack keywords\n'
|
f'# Optional: path to a local JSON that overrides pack keywords\n'
|
||||||
f'# custom_pack = "custom.json"\n',
|
f'{toml_custom_line}\n',
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -301,3 +328,19 @@ def decompile(file: Path, lang: str, postfix: bool, output: str | None):
|
|||||||
out_path.parent.mkdir(parents=True, exist_ok=True)
|
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
out_path.write_text(result, encoding="utf-8")
|
out_path.write_text(result, encoding="utf-8")
|
||||||
click.echo(f"Decompiled: {out_path}")
|
click.echo(f"Decompiled: {out_path}")
|
||||||
|
|
||||||
|
|
||||||
|
def _make_scaffold_pack(lang_code: str, lang_name: str, native_name: str) -> dict:
|
||||||
|
"""
|
||||||
|
Load template.json — single source of truth for all pack keys.
|
||||||
|
To add new keywords/builtins, edit template.json only.
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
from importlib.resources import files
|
||||||
|
|
||||||
|
template_path = files("foreignthon") / "template.json"
|
||||||
|
pack = json.loads(template_path.read_text(encoding="utf-8"))
|
||||||
|
pack["meta"]["name"] = lang_name
|
||||||
|
pack["meta"]["native_name"] = native_name
|
||||||
|
pack["meta"]["code"] = lang_code
|
||||||
|
return pack
|
||||||
Reference in New Issue
Block a user