# Supporting a new language

This section is to help developers implement support for a new language in `mehen`.

To implement a new language, two steps are required:

1. Generate the grammar
2. Add the grammar to `mehen`

A number of [metrics are supported](../metrics.md) and help to implement those are covered elsewhere in the documentation.

## Generating the grammar

As a **prerequisite** for adding a new grammar, there needs to exist a [tree-sitter](https://github.com/tree-sitter) crate for the desired language, and it must be compatible with the `tree-sitter` version used by this repository.

The grammars are generated by the local `enums` project in this repository.

1. Add the language-specific dependency to `enums/Cargo.toml`.
For example:

```toml
tree-sitter-rust = "=0.24.0"
```

2. Register the language in `enums/src/languages.rs` by adding a tuple to `mk_langs!`:

```rust
(Rust, tree_sitter_rust)
```

3. Update the `mk_get_language` match in `enums/src/macros.rs` with the corresponding `Lang::<YourLang>` arm.
For most grammars this is `<crate>::LANGUAGE.into()`, but some grammars (for example TypeScript/TSX) use specific constants.

4. Regenerate language enums:

```bash
./recreate-grammars.sh
```

At this point you should have a generated enum file in `src/languages/` (for example `src/languages/language_rust.rs`).

## Adding the new grammar to mehen

1. Add the same language-specific `tree-sitter` dependency to the root `Cargo.toml`, pinned consistently with `enums/Cargo.toml`.

2. Export the generated language module in `src/languages/mod.rs`:

```rust
pub(crate) mod language_rust;
pub(crate) use language_rust::*;
```

3. Add the language definition to `mk_langs!` in `src/langs.rs`.

```rust
// 1) Name for enum
// 2) Language description
// 3) Display name
// 4) Empty struct name to implement
// 5) Parser name
// 6) tree-sitter function to call to get a Language
// 7) file extensions
// 8) emacs modes
(
    Rust,
    "The `Rust` language",
    "rust",
    RustCode,
    RustParser,
    tree_sitter_rust,
    [rs],
    ["rust"]
)
```

4. Ensure the `get_language!` macro in `src/macros.rs` supports the new tree-sitter crate name/constant layout (special handling is needed for some crates, as with TypeScript/TSX).

5. Implement language behavior:

- `src/checker.rs`: syntax/semantic classifiers (`is_func_space`, `is_func`, `is_call`, etc.).
- `src/getter.rs`: function-space naming and `SpaceKind`.
- `src/metrics/*.rs`: metric-specific rules if default implementations are not sufficient.

## Validation

After wiring the new language, run:

```bash
cargo check
cargo test --all-targets --locked
cargo clippy --all-targets --all-features --locked
```
