diff --git a/docs/contributing/core.md b/docs/contributing/core.md index e8a4e40..fc020ab 100644 --- a/docs/contributing/core.md +++ b/docs/contributing/core.md @@ -1 +1,122 @@ # 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.