# Contributing to Core `foreignthon-core` is the transpiler engine, CLI, and pack loader. Contributions that improve correctness, performance, or usability are welcome. --- ## Repository [https://git.keshavanand.net/foreign-thon/foreignthon-core](https://git.keshavanand.net/foreign-thon/foreignthon-core) --- ## Dev setup ```bash git clone https://git.keshavanand.net/foreign-thon/foreignthon-core cd foreignthon-core python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -e ".[dev]" # installs foreignthon + pytest + ruff ``` Verify the install: ```bash fpy --version pytest ``` --- ## Running tests ```bash pytest # all tests pytest -v # verbose pytest -k postfix # filter by name ``` Tests live in `tests/test_engine.py`. They use a local `test_pack.json` fixture (a copy of the Spanish pack) so no installed language pack is needed. --- ## Code style ForeignThon uses [Ruff](https://docs.astral.sh/ruff/) for linting and formatting: ```bash ruff check src/ # lint ruff format src/ # format ``` The CI gate runs both. A PR that fails either will not be merged. Line length is 88. Import order follows the `I` rule set (isort-compatible). --- ## Project layout ``` foreignthon-core/ ├── src/ │ └── foreignthon/ │ ├── __init__.py # version │ ├── cli.py # click commands (fpy) │ ├── errors.py # bilingual error hook │ ├── pack.py # pack discovery and validation │ ├── template.json # canonical list of all pack keys │ └── transpiler.py # tokenizer-based engine └── tests/ ├── test_engine.py └── test_pack.json # Spanish fixture (no install needed) ``` --- ## Adding new keywords or builtins `template.json` is the **single source of truth** for the full set of keywords, builtins, exceptions, and stdlib names that all language packs must cover. To add a new entry (e.g. a new builtin): 1. Add it to `template.json` with the English value as the default. 2. Add a matching entry to `test_pack.json` (Spanish values). 3. Update `_build_mapping()` in `transpiler.py` if a new section is needed. 4. Bump `foreignthon-core` version. 5. Announce to language pack maintainers so they can update their packs. Do not add entries to `template.json` that are specific to one language pack. --- ## Adding a new CLI command All commands are defined in `cli.py` using [Click](https://click.palletsprojects.com/). - Add your command as a function decorated with `@main.command()`. - Include a docstring — Click uses it as the `--help` text. - Add `CONTEXT_SETTINGS` to every command for consistent `-h` support. - Write tests in `tests/test_engine.py` or a new test file. --- ## Submitting a PR 1. Fork the repository on Gitea. 2. Create a branch: `git checkout -b feature/my-change`. 3. Make your change, add or update tests, run `pytest` and `ruff check`. 4. Open a PR with a clear description of the problem and the fix. For large changes (new features, engine behaviour changes), open an issue first to discuss before writing code. --- ## What not to change - **`template.json`** keys should only grow, never shrink — removing a key is a breaking change for all existing language packs. - The tokenizer-based approach in `transpiler.py` is intentional. Do not replace it with a regex or AST-based approach without a very strong reason — the tokenizer correctly handles strings, comments, and f-strings without any special casing. - The bilingual error format (`[XX] ForeignName: msg` / `[EN] EnglishName: msg`) is part of the public interface. Do not change the format without a major version bump.