update-mds #2
@@ -1 +1,117 @@
|
||||
# CLI Reference
|
||||
|
||||
All commands support `-h` / `--help`.
|
||||
|
||||
---
|
||||
|
||||
## `fpy new`
|
||||
|
||||
Scaffold a new ForeignThon project.
|
||||
|
||||
```bash
|
||||
fpy new <name> --lang <code> # create in new directory
|
||||
fpy new --lang <code> # initialize current directory (must be empty)
|
||||
fpy new <name> --lang <code> --no-git
|
||||
fpy new <name> --lang custom # scaffold a blank language pack
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--lang`, `-l` | Language code — required |
|
||||
| `--no-git` | Skip `git init` and initial commit |
|
||||
|
||||
!!! note "Using `--lang custom`"
|
||||
Prompts for a language code, English name, and native name. Creates a `custom.json` with all Python keywords pre-filled as stubs and wires it up in `.foreignthon.toml` automatically.
|
||||
|
||||
---
|
||||
|
||||
## `fpy run`
|
||||
|
||||
Transpile and run a source file.
|
||||
|
||||
```bash
|
||||
fpy run script.es.py
|
||||
fpy run script.py --lang es # override language detection
|
||||
fpy run script.es.py --keep # also write the compiled .py to disk
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--lang`, `-l` | Override language detection |
|
||||
| `--keep` | Write `.compiled.py` alongside source after running |
|
||||
|
||||
---
|
||||
|
||||
## `fpy compile`
|
||||
|
||||
Transpile to standard Python without running.
|
||||
|
||||
```bash
|
||||
fpy compile script.es.py # → script.compiled.py (same directory)
|
||||
fpy compile script.es.py -o dist/ # → dist/script.compiled.py
|
||||
fpy compile script.es.py -o output.py # → output.py
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--output`, `-o` | Output file or directory |
|
||||
|
||||
---
|
||||
|
||||
## `fpy decompile`
|
||||
|
||||
Convert standard Python back to a foreign language. Keywords and builtins are translated — variable names are untouched.
|
||||
|
||||
```bash
|
||||
fpy decompile script.py --lang es
|
||||
fpy decompile script.py --lang es --postfix
|
||||
fpy decompile script.py --lang es -o out/
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|---|---|
|
||||
| `--lang`, `-l` | Target language — required |
|
||||
| `--postfix` | Rewrite conditionals to `@@` postfix style |
|
||||
| `--output`, `-o` | Output file or directory |
|
||||
|
||||
!!! note
|
||||
Decompile is lossy — variable names and comments are not translated back. It is useful for bootstrapping a foreign-language version of an existing Python file, not as a perfect round-trip.
|
||||
|
||||
---
|
||||
|
||||
## `fpy check`
|
||||
|
||||
Validate syntax without running.
|
||||
|
||||
```bash
|
||||
fpy check script.es.py
|
||||
# ✓ script.es.py looks good.
|
||||
# or
|
||||
# ✗ Syntax error: invalid syntax (script.es.py, line 4)
|
||||
```
|
||||
|
||||
Exits with code `1` on failure — useful in CI pipelines.
|
||||
|
||||
---
|
||||
|
||||
## `fpy pack`
|
||||
|
||||
Validate a language pack JSON file against the required schema.
|
||||
|
||||
```bash
|
||||
fpy pack mylang.json
|
||||
# ✓ Pack 'Russian' is valid.
|
||||
# or
|
||||
# ✗ Missing sections: {'error_messages'}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Language detection order
|
||||
|
||||
When running a file, ForeignThon resolves the language in this order:
|
||||
|
||||
1. `--lang` flag (highest priority)
|
||||
2. Shebang comment: `# foreignthon: es`
|
||||
3. File extension: `.es.py` → `es`
|
||||
4. `.foreignthon.toml` in the project root
|
||||
|
||||
@@ -1 +1,95 @@
|
||||
# Custom Packs
|
||||
## Custom Packs
|
||||
|
||||
ForeignThon lets you extend or override any installed language pack locally — no PyPI account, no new package required. You can also scaffold a completely new language from scratch.
|
||||
|
||||
---
|
||||
|
||||
## Local override
|
||||
|
||||
Create a `custom.json` in your project root with only the keys you want to change:
|
||||
|
||||
```json
|
||||
{
|
||||
"builtins": {
|
||||
"show": "print"
|
||||
},
|
||||
"keywords": {
|
||||
"when": "if"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then reference it in `.foreignthon.toml`:
|
||||
|
||||
```toml
|
||||
[foreignthon]
|
||||
lang = "es"
|
||||
custom_pack = "custom.json"
|
||||
```
|
||||
|
||||
Custom keys are merged on top of the installed pack. Installed pack keys are preserved — only the keys you define in `custom.json` are overridden.
|
||||
|
||||
!!! tip
|
||||
ForeignThon walks up the directory tree to find `.foreignthon.toml`, so you can place it at the project root and run `fpy` from any subdirectory.
|
||||
|
||||
---
|
||||
|
||||
## Scaffold a new language
|
||||
|
||||
If no pack exists for your language yet:
|
||||
|
||||
```bash
|
||||
fpy new myproject --lang custom
|
||||
```
|
||||
|
||||
You will be prompted for:
|
||||
|
||||
- Language code (e.g. `ru`, `fr`, `ar`)
|
||||
- English name (e.g. `Russian`)
|
||||
- Native name (e.g. `Русский`)
|
||||
|
||||
This generates a `custom.json` based on the official template — every Python keyword, builtin, exception, and stdlib module is listed with the English value as a placeholder. Replace the **keys** with your language's words.
|
||||
|
||||
```json
|
||||
{
|
||||
"keywords": {
|
||||
"if": "if", ← replace the key, keep the value
|
||||
"for": "for",
|
||||
"def": "def",
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `.foreignthon.toml` is automatically wired to use this file.
|
||||
|
||||
---
|
||||
|
||||
## Pack schema
|
||||
|
||||
A standalone pack must have these top-level sections:
|
||||
|
||||
| Section | Purpose |
|
||||
|---|---|
|
||||
| `meta` | Name, code, version, authors |
|
||||
| `keywords` | Python reserved words |
|
||||
| `builtins` | Built-in functions |
|
||||
| `exceptions` | Built-in exception classes |
|
||||
| `error_messages` | Translations for bilingual error output |
|
||||
| `stdlib` | Common standard library module names |
|
||||
| `postfix_keywords` | English keywords to rewrite in `--postfix` output |
|
||||
|
||||
Validate your pack at any time:
|
||||
|
||||
```bash
|
||||
fpy pack custom.json
|
||||
# ✓ Pack 'Russian' is valid.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Publishing
|
||||
|
||||
Once your `custom.json` is complete and working, you can turn it into a proper `foreignthon-xx` package on PyPI so others can install it with `pip install foreignthon-xx`.
|
||||
|
||||
See [Contributing → Language Packs](contributing/language-packs.md) for the full guide. Custom Packs
|
||||
|
||||
@@ -1 +1,135 @@
|
||||
# Getting Started
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.9 or later
|
||||
- A language pack (`pip install foreignthon-xx`)
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install foreignthon
|
||||
```
|
||||
|
||||
For global CLI access across projects, use `pipx`:
|
||||
|
||||
```bash
|
||||
pipx install foreignthon
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Create a project
|
||||
|
||||
```bash
|
||||
fpy new myproject --lang <code>
|
||||
cd myproject
|
||||
```
|
||||
|
||||
This scaffolds:
|
||||
|
||||
```
|
||||
myproject/
|
||||
├── .foreignthon.toml # project config
|
||||
├── .gitignore
|
||||
├── README.md
|
||||
└── src/
|
||||
└── main.<lang>.py # hello world in your language
|
||||
```
|
||||
|
||||
The `.foreignthon.toml` stores your language and any local pack overrides:
|
||||
|
||||
```toml
|
||||
[foreignthon]
|
||||
lang = "es"
|
||||
# custom_pack = "custom.json"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## File naming
|
||||
|
||||
ForeignThon detects the language from the file extension:
|
||||
|
||||
```
|
||||
script.es.py → Spanish
|
||||
script.ta.py → Tamil
|
||||
script.fr.py → French
|
||||
```
|
||||
|
||||
You can also declare the language at the top of the file:
|
||||
|
||||
```python
|
||||
# foreignthon: es
|
||||
```
|
||||
|
||||
Or override it at runtime:
|
||||
|
||||
```bash
|
||||
fpy run script.py --lang es
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
fpy run src/main.es.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Compile
|
||||
|
||||
```bash
|
||||
fpy compile src/main.es.py
|
||||
# → src/main.compiled.py
|
||||
```
|
||||
|
||||
```bash
|
||||
fpy compile src/main.es.py -o dist/
|
||||
# → dist/main.compiled.py
|
||||
```
|
||||
|
||||
The compiled file is standard Python. Commit it alongside your source — anyone can run it without ForeignThon installed.
|
||||
|
||||
---
|
||||
|
||||
## Validate
|
||||
|
||||
```bash
|
||||
fpy check src/main.es.py
|
||||
# ✓ main.es.py looks good.
|
||||
```
|
||||
|
||||
Checks syntax without running — useful in CI.
|
||||
|
||||
---
|
||||
|
||||
## Errors
|
||||
|
||||
When something goes wrong, ForeignThon shows the error in your language first, then English:
|
||||
|
||||
```
|
||||
[ES] ErrorDeDivisionCero: Error división por cero
|
||||
[EN] ZeroDivisionError: division by zero
|
||||
File "src/main.es.py", line 8
|
||||
```
|
||||
|
||||
Tracebacks point to your original source file, not any intermediate.
|
||||
|
||||
---
|
||||
|
||||
## Variable names
|
||||
|
||||
Variable names are completely optional — English names work alongside foreign keywords with no issues. Only keywords and builtins are ever swapped.
|
||||
|
||||
---
|
||||
|
||||
## Next steps
|
||||
|
||||
- [CLI Reference](cli-reference.md) — all commands and flags
|
||||
- [Language Packs](language-packs/index.md) — available languages
|
||||
- [Custom Packs](custom-packs.md) — extend or override a pack locally
|
||||
|
||||
@@ -1 +1,42 @@
|
||||
# ForeignThon
|
||||
|
||||
Write Python in any human language.
|
||||
|
||||
ForeignThon is a transpiler that converts `.xx.py` files into standard Python — keywords, builtins, and exceptions all translated into your language. The compiled output runs anywhere without ForeignThon installed.
|
||||
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
```
|
||||
source.es.py → fpy → source.compiled.py → Python
|
||||
```
|
||||
|
||||
ForeignThon uses Python's `tokenize` module to swap `NAME` tokens. Strings, comments, and f-strings are never touched. The result is identical, valid Python.
|
||||
|
||||
---
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
pip install foreignthon
|
||||
pip install foreignthon-es # or any other language pack
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## At a glance
|
||||
|
||||
| Feature | Description |
|
||||
|---|---|
|
||||
| Transpiler | Tokenizer-based, safe, unicode-aware |
|
||||
| File format | `.xx.py` where `xx` is the language code |
|
||||
| Errors | Shown in your language first, English below |
|
||||
| Postfix syntax | `@@` operator for SOV languages |
|
||||
| Custom packs | Local JSON override, no PyPI needed |
|
||||
| CLI | `fpy run`, `fpy compile`, `fpy decompile`, `fpy new` |
|
||||
|
||||
---
|
||||
|
||||
[Get started →](getting-started.md){ .md-button .md-button--primary }
|
||||
[CLI Reference →](cli-reference.md){ .md-button }
|
||||
|
||||
@@ -1 +1,55 @@
|
||||
# Language Packs
|
||||
|
||||
Language packs are separate PyPI packages that define keyword, builtin, and exception mappings for a specific human language. Each is installed independently and discovered automatically by ForeignThon.
|
||||
|
||||
---
|
||||
|
||||
## Install a pack
|
||||
|
||||
```bash
|
||||
pip install foreignthon-<code>
|
||||
```
|
||||
|
||||
Multiple packs can coexist — install as many as you need.
|
||||
|
||||
---
|
||||
|
||||
## Available packs
|
||||
|
||||
| Language | Code | Install |
|
||||
|---|---|---|
|
||||
| Spanish | `es` | `pip install foreignthon-es` |
|
||||
| Tamil | `ta` | `pip install foreignthon-ta` |
|
||||
|
||||
---
|
||||
|
||||
## How discovery works
|
||||
|
||||
ForeignThon uses Python [entry points](https://packaging.python.org/en/latest/specifications/entry-points/) to discover installed packs. Installing a pack is sufficient — no configuration required.
|
||||
|
||||
```toml
|
||||
# Each pack registers itself in its pyproject.toml:
|
||||
[project.entry-points."foreignthon.langs"]
|
||||
es = "foreignthon_es"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What a pack covers
|
||||
|
||||
| Section | Examples |
|
||||
|---|---|
|
||||
| Keywords | `if`, `for`, `def`, `class`, `return` … |
|
||||
| Builtins | `print`, `range`, `len`, `type` … |
|
||||
| Exceptions | `ValueError`, `TypeError`, `KeyError` … |
|
||||
| Error messages | Bilingual error output translations |
|
||||
| Stdlib | `math`, `sys`, `os`, `random` … |
|
||||
| Postfix keywords | Which keywords to rewrite with `@@` on decompile |
|
||||
|
||||
Third-party library names (numpy, pandas, etc.) are intentionally out of scope.
|
||||
|
||||
---
|
||||
|
||||
## Don't see your language?
|
||||
|
||||
Anyone can publish a `foreignthon-xx` pack — no core access required. See [Contributing → Language Packs](../contributing/language-packs.md) to get started, or use a [local custom pack](../custom-packs.md) in the meantime.
|
||||
|
||||
@@ -1 +1,87 @@
|
||||
# Postfix Syntax
|
||||
## Postfix Syntax
|
||||
|
||||
Some languages are SOV — subject-object-verb — meaning the condition naturally comes before the keyword rather than after it. ForeignThon supports this with the `@@` operator.
|
||||
|
||||
---
|
||||
|
||||
## The problem
|
||||
|
||||
In English-order Python, the keyword always comes first:
|
||||
|
||||
```python
|
||||
if condition:
|
||||
...
|
||||
```
|
||||
|
||||
In many languages, the natural order is the opposite — the condition is stated first, then the action. Forcing English word order on these languages makes the code feel unnatural.
|
||||
|
||||
---
|
||||
|
||||
## The solution
|
||||
|
||||
The `@@` operator lets you put any keyword after its expression:
|
||||
|
||||
```
|
||||
condition @@keyword:
|
||||
body
|
||||
```
|
||||
|
||||
This is equivalent to:
|
||||
|
||||
```
|
||||
keyword condition:
|
||||
body
|
||||
```
|
||||
|
||||
Both produce identical compiled Python. `@@` is purely a source-level syntax — it is processed before tokenization and never appears in the output.
|
||||
|
||||
---
|
||||
|
||||
## Rules
|
||||
|
||||
- `@@` rewrites only the line it appears on — nothing else changes
|
||||
- Indentation follows standard Python rules, unchanged
|
||||
- Prefix and postfix can be mixed freely in the same file
|
||||
- Works for any keyword in any language pack
|
||||
- `@@` is not valid Python syntax, so it never conflicts with existing code
|
||||
|
||||
---
|
||||
|
||||
## Supported constructs
|
||||
|
||||
| Construct | Prefix | Postfix |
|
||||
|---|---|---|
|
||||
| if | `keyword condition:` | `condition @@keyword:` |
|
||||
| elif | `keyword condition:` | `condition @@keyword:` |
|
||||
| while | `keyword condition:` | `condition @@keyword:` |
|
||||
| def | `keyword name(args):` | `name(args) @@keyword:` |
|
||||
| class | `keyword Name:` | `Name @@keyword:` |
|
||||
| for | `keyword var in iter:` | `var @@in_kw iter @@for_kw:` |
|
||||
|
||||
!!! note
|
||||
`for` loops with postfix require two `@@` operators and can be complex. Most users keep `for` in prefix style.
|
||||
|
||||
---
|
||||
|
||||
## Decompile with postfix
|
||||
|
||||
When converting Python back to a foreign language, pass `--postfix`:
|
||||
|
||||
```bash
|
||||
fpy decompile script.py --lang <code> --postfix
|
||||
```
|
||||
|
||||
Which keywords get rewritten is controlled by the `postfix_keywords` list in the language pack JSON. A language that uses SVO order sets this to `[]` — postfix output is never forced on languages that don't need it.
|
||||
|
||||
```json
|
||||
"postfix_keywords": ["if", "elif", "while", "def", "class"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Input vs output
|
||||
|
||||
| Direction | Mechanism | Controlled by |
|
||||
|---|---|---|
|
||||
| Input (writing `.xx.py`) | `@@` in source | Always available for any keyword |
|
||||
| Output (`fpy decompile --postfix`) | Pack's `postfix_keywords` | Language pack author | Postfix Syntax
|
||||
|
||||
Reference in New Issue
Block a user