# `Minga.Language.TreeSitter`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga/language/tree_sitter.ex#L1)

Compiles and registers tree-sitter grammars at runtime.

Extensions ship grammar source files (`parser.c`, optional `scanner.c`)
and highlight queries (`.scm`). This module compiles the C sources into
a platform-appropriate shared library (`.dylib` on macOS, `.so` on Linux)
using the system C compiler, then loads the library into the parser Port
via the `load_grammar` protocol message.

Compiled libraries are cached at `~/.local/share/minga/grammars/` so
subsequent startups skip compilation.

## Example

    Minga.Language.TreeSitter.register_grammar(
      "org",
      "/path/to/tree-sitter-org/src",
      highlights: "/path/to/queries/org/highlights.scm",
      injections: "/path/to/queries/org/injections.scm",
      filetype_extensions: [".org"],
      filetype_atom: :org
    )

# `register_opt`

```elixir
@type register_opt() ::
  {:highlights, String.t()}
  | {:injections, String.t()}
  | {:filetype_extensions, [String.t()]}
  | {:filetype_filenames, [String.t()]}
  | {:filetype_atom, atom()}
  | {:compiler, {:ok, String.t()} | {:error, String.t()}}
```

Options for `register_grammar/3`.

# `compile_grammar`

```elixir
@spec compile_grammar(String.t(), String.t(), keyword()) ::
  {:ok, String.t()} | {:error, String.t()}
```

Compiles a tree-sitter grammar into a shared library.

Returns the path to the compiled library. If a cached library already
exists and is newer than the source files, returns the cached path
without recompiling.

## Options

- `:compiler` - override compiler resolution. Pass `{:ok, "/usr/bin/cc"}`
  to use a specific compiler, or `{:error, "reason"}` to simulate a
  missing compiler (useful for testing). Defaults to `find_compiler/0`.

# `find_compiler`

```elixir
@spec find_compiler() :: {:ok, String.t()} | {:error, String.t()}
```

Finds the system C compiler.

Checks `$CC` environment variable first, then tries `cc`, `gcc`, `clang`
in order. Returns `{:ok, path}` or `{:error, reason}`.

# `grammar_cache_dir`

```elixir
@spec grammar_cache_dir() :: String.t()
```

Returns the grammar cache directory path.

Uses `$XDG_DATA_HOME/minga/grammars` if set, otherwise
`~/.local/share/minga/grammars`. Resolved at runtime so the path
is correct regardless of the build environment.

# `grammar_lib_path`

```elixir
@spec grammar_lib_path(String.t()) :: String.t()
```

Returns the path to the cached shared library for a grammar.

# `include_path`

```elixir
@spec include_path() :: String.t()
```

Returns the path to the tree-sitter C header directory shipped with Minga.

This directory contains `tree_sitter/api.h` and `tree_sitter/parser.h`.
Extensions need these headers to compile grammars that do
`#include "tree_sitter/parser.h"` (most grammars ship their own copy
in `src/tree_sitter/`, but this serves as a fallback).

# `register_grammar`

```elixir
@spec register_grammar(String.t(), String.t(), [register_opt()]) ::
  :ok | {:error, String.t()}
```

Registers a tree-sitter grammar for runtime use.

Compiles the grammar sources into a shared library (if not cached),
loads it into the parser Port, sends the highlight query, and
registers filetype mappings.

`name` is the tree-sitter grammar name (e.g., `"org"`). The parser
expects the shared library to export a `tree_sitter_{name}` function.

`source_dir` is the path to the directory containing `parser.c` and
optionally `scanner.c`.

## Options

- `:highlights` - path to a `highlights.scm` query file
- `:injections` - path to an `injections.scm` query file
- `:filetype_extensions` - list of file extensions to map (e.g., `[".org"]`)
- `:filetype_filenames` - list of exact filenames to map (e.g., `["Orgfile"]`)
- `:filetype_atom` - the filetype atom (e.g., `:org`)

---

*Consult [api-reference.md](api-reference.md) for complete listing*
