readmes and mds plus fixed ruff
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
# Contributing to ForeignThon
|
||||
|
||||
## Project structure
|
||||
foreignthon/
|
||||
├── packages/
|
||||
│ ├── foreignthon/ # core engine + fpy CLI
|
||||
│ │ ├── src/foreignthon/
|
||||
│ │ │ ├── cli.py # fpy commands
|
||||
│ │ │ ├── transpiler.py # tokenizer-based transpiler
|
||||
│ │ │ ├── pack.py # language pack loader
|
||||
│ │ │ └── errors.py # bilingual error hook
|
||||
│ │ └── tests/
|
||||
│ └── langs/
|
||||
│ └── es/ # Spanish language pack
|
||||
│ └── src/foreignthon_es/es.json
|
||||
|
||||
## Setting up
|
||||
|
||||
```bash
|
||||
python -m venv .venv && source .venv/bin/activate
|
||||
pip install -e "packages/foreignthon[dev]"
|
||||
pip install -e packages/langs/es
|
||||
```
|
||||
|
||||
## Running tests
|
||||
|
||||
```bash
|
||||
pytest packages/foreignthon/tests/ -v
|
||||
```
|
||||
|
||||
## Adding a new language pack
|
||||
|
||||
1. Copy `packages/langs/es/` to `packages/langs/<code>/`
|
||||
2. Rename `foreignthon_es` → `foreignthon_<code>` throughout
|
||||
3. Fill in `<code>.json` following the same schema as `es.json`
|
||||
4. Validate it: `fpy pack packages/langs/<code>/src/foreignthon_<code>/<code>.json`
|
||||
5. Add tests if the language has tricky characters or edge cases
|
||||
6. Open a PR or publish independently as `foreignthon-<code>` on PyPI
|
||||
|
||||
## Language pack schema
|
||||
|
||||
Every pack must have these top-level keys:
|
||||
`meta`, `keywords`, `builtins`, `exceptions`, `error_messages`, `stdlib`
|
||||
|
||||
See `packages/langs/es/src/foreignthon_es/es.json` as the reference.
|
||||
|
||||
## Code style
|
||||
|
||||
```bash
|
||||
ruff check packages/foreignthon/src
|
||||
```
|
||||
|
||||
89
README.md
89
README.md
@@ -0,0 +1,89 @@
|
||||
DME.md << 'EOF'
|
||||
# ForeignThon
|
||||
|
||||
Write Python in any human language. ForeignThon transpiles `.es.py`, `.ta.py` (and more) files into standard Python — keywords, builtins, exceptions, all of it.
|
||||
|
||||
```python
|
||||
# hola.es.py
|
||||
definir saludar(nombre):
|
||||
retornar f"Hola, {nombre}!"
|
||||
|
||||
para i en rango(3):
|
||||
imprimir(saludar(f"mundo {i}"))
|
||||
```
|
||||
|
||||
```bash
|
||||
fpy run hola.es.py
|
||||
# Hola, mundo 0!
|
||||
# Hola, mundo 1!
|
||||
# Hola, mundo 2!
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install foreignthon
|
||||
pip install foreignthon-es # Spanish
|
||||
pip install foreignthon-ta # Tamil
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
fpy run script.es.py # transpile and run
|
||||
fpy compile script.es.py # output a .compiled.py file
|
||||
fpy check script.es.py # validate without running
|
||||
fpy pack mylang.json # validate a language pack
|
||||
```
|
||||
|
||||
### Language override
|
||||
|
||||
```python
|
||||
# foreignthon: es
|
||||
# ^ overrides the file extension
|
||||
```
|
||||
|
||||
Or via CLI flag:
|
||||
|
||||
```bash
|
||||
fpy run script.py --lang es
|
||||
```
|
||||
|
||||
## Errors
|
||||
|
||||
Errors are shown in your language first, English below:
|
||||
[ES] ErrorDeDivisionCero: Error: división por cero
|
||||
[EN] ZeroDivisionError: division by zero
|
||||
|
||||
## Language Packs
|
||||
|
||||
A language pack is a JSON file + a tiny Python wrapper published as `foreignthon-xx` on PyPI.
|
||||
See `packages/langs/es/` for the reference implementation.
|
||||
|
||||
The JSON covers:
|
||||
- **keywords** — `si → if`, `para → for`, `definir → def` …
|
||||
- **builtins** — `imprimir → print`, `rango → range` …
|
||||
- **exceptions** — `ErrorDeValor → ValueError` …
|
||||
- **error_messages** — bilingual error output
|
||||
- **stdlib** — `matematicas → math` …
|
||||
|
||||
Validate your pack before publishing:
|
||||
|
||||
```bash
|
||||
fpy pack mylang.json
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
git clone <your-repo>
|
||||
cd foreignthon
|
||||
python -m venv .venv && source .venv/bin/activate
|
||||
pip install -e "packages/foreignthon[dev]"
|
||||
pip install -e packages/langs/es
|
||||
pytest packages/foreignthon/tests/ -v
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
GPL
|
||||
|
||||
@@ -52,3 +52,7 @@ src = ["src"]
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["E", "F", "I"]
|
||||
ignore = ["E501"]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"pack.py" = ["E501"]
|
||||
|
||||
@@ -7,7 +7,7 @@ import click
|
||||
|
||||
from . import __version__
|
||||
from .errors import activate
|
||||
from .transpiler import transpile_file, run_transpiled
|
||||
from .transpiler import run_transpiled, transpile_file
|
||||
|
||||
|
||||
@click.group()
|
||||
@@ -20,7 +20,7 @@ def main():
|
||||
@main.command()
|
||||
@click.argument("file", type=click.Path(exists=True, path_type=Path))
|
||||
@click.option("--lang", "-l", default=None, help="Override language code (e.g. es, ta)")
|
||||
@click.option("--keep", is_flag=True, help="Keep the compiled .py file alongside the source")
|
||||
@click.option("--keep", is_flag=True, help="Keep the compiled .py alongside the source")
|
||||
def run(file: Path, lang: str | None, keep: bool):
|
||||
"""Transpile and run a foreign-language Python file."""
|
||||
if lang:
|
||||
@@ -44,12 +44,15 @@ def run(file: Path, lang: str | None, keep: bool):
|
||||
|
||||
@main.command()
|
||||
@click.argument("file", type=click.Path(exists=True, path_type=Path))
|
||||
@click.option("--output", "-o", default=None, help="Output path (default: same dir as source)")
|
||||
@click.option("--output", "-o", default=None, help="Output path (default: beside source)")
|
||||
def compile(file: Path, output: str | None):
|
||||
"""Transpile a file to standard Python without running it."""
|
||||
transpiled = transpile_file(file)
|
||||
|
||||
out_path = Path(output) if output else file.with_suffix("").with_suffix(".compiled.py")
|
||||
out_path = (
|
||||
Path(output) if output
|
||||
else file.with_suffix("").with_suffix(".compiled.py")
|
||||
)
|
||||
out_path.write_text(transpiled, encoding="utf-8")
|
||||
click.echo(f"Compiled: {out_path}")
|
||||
|
||||
@@ -77,6 +80,7 @@ def check(file: Path):
|
||||
def validate_pack(json_file: Path):
|
||||
"""Validate a language pack JSON file."""
|
||||
import json
|
||||
|
||||
from .pack import REQUIRED_SECTIONS
|
||||
|
||||
with open(json_file, encoding="utf-8") as f:
|
||||
|
||||
@@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
from .pack import load_pack, PackNotFoundError
|
||||
from .pack import PackNotFoundError, load_pack
|
||||
|
||||
_active_lang: str | None = None
|
||||
|
||||
|
||||
Reference in New Issue
Block a user