giallo-kak 0.2.2

Kakoune syntax highlighter using TextMate grammars
# giallo.kak design

## Summary
Integrate the `giallo` TextMate highlighter into Kakoune by adding a small server that turns giallo token styling into Kakoune `ranges` highlighters. The design mirrors the session/FIFO approach used by `kak-tree-sitter` while keeping a simple Kakoune-side setup.

## Goals
- Provide TextMate-based syntax highlighting in Kakoune using `giallo`.
- Reuse giallo themes and grammars (builtin dump or user-provided).
- Use Kakoune `ranges` highlighter output, compatible with existing Kakoune runtime.
- Keep integration modular: a Kakoune script + a Rust server.
- Keep performance acceptable for typical file sizes.

## Non-goals
- Replace `kak-tree-sitter` or provide tree-sitter features (selections, indents, queries).
- Implement full incremental parsing in the first version.
- Rework Kakoune colorscheme logic; we use giallo themes directly.

## Key references
- `giallo` provides `Registry::builtin()` and `HighlightOptions` with `ThemeVariant` and a per-line token output (`HighlightedCode`).
- `kak-tree-sitter` already defines a working pattern for Kakoune integration: a server, FIFO updates, and `ranges` output.

## High-level architecture

### Components
1) **giallo-kak server (Rust binary)**
   - Owns a `giallo::Registry` and theme cache.
   - Receives buffer snapshots (full text) and language/theme choices.
   - Produces Kakoune `ranges` with face names and emits Kakoune commands.
   - Reuses the `ranges` update strategy from `kak-tree-sitter` (timestamped buffer option with ranges).

2) **Kakoune script (giallo.kak)**
   - Sets up highlighters and hooks for buffer updates.
   - Sends buffer content to the server (FIFO or similar IPC).
   - Holds buffer options like `giallo_lang`, `giallo_theme`, `giallo_hl_ranges`.

### Data flow
1) Kakoune detects a buffer that should be highlighted.
2) Kakoune script sends a snapshot (buffer content + filetype) to the server.
3) Server highlights via giallo and maps styles to Kakoune faces.
4) Server sends back Kakoune commands to:
   - define or update faces for the selected theme,
   - set buffer option `giallo_hl_ranges` with the encoded ranges.
5) Kakoune `ranges` highlighter displays the highlights.

## Kakoune integration details

### Highlighter setup
- A buffer-local ranges highlighter:
  - `add-highlighter -override buffer/giallo ranges giallo_hl_ranges`
- When a buffer is enabled, remove any default syntax highlighter if configured.

### Buffer options
- `giallo_lang` (string): giallo language id.
- `giallo_theme` (string): theme name.
- `giallo_hl_ranges` (string): the ranges highlighter payload.
- `giallo_buf_fifo_path` (string): FIFO path for buffer updates (if using FIFO).
- `giallo_buf_sentinel` (string): sentinel token for fifo framing (if needed).

### Hooks
- `BufOpen`/`BufReload`/`BufWritePost`/`InsertChar` (or `NormalIdle`) trigger updates.
- `BufSetOption filetype` maps Kakoune filetype to giallo language.
- `WinSetOption` to refresh on colorscheme change (optional).

## Server responsibilities

### Session and IPC
- Reuse `kak-tree-sitter`'s pattern: a per-buffer FIFO created by the server and injected into Kakoune.
- The client writes buffer snapshots to the FIFO; the server reads, highlights, and responds.

### Highlighting pipeline
1) Resolve language and theme.
2) `Registry::highlight(code, options)` returns `HighlightedCode` with per-line tokens.
3) Convert tokens into Kakoune `ranges`:
   - Track line and byte column offsets as tokens are concatenated.
   - Each token becomes a range with a face id.
   - Kakoune ranges are inclusive; the end column is `byte_end - 1`.

### Style to face mapping
- A giallo token is backed by a concrete `Style` (foreground, background, font style).
- Build a stable mapping: `Style -> face_name` for the active theme.
- Face names use a giallo prefix, for example `giallo_0001`.
- Generate Kakoune faces:
  - Foreground/background use `Style.foreground.as_hex()` and `Style.background.as_hex()`.
  - Font style maps to Kakoune attributes:
    - bold -> `+b`
    - italic -> `+i`
    - underline -> `+u`
    - strikethrough -> `+s`
  - Alpha from giallo colors is ignored (Kakoune has no alpha support).

### Face initialization
- On theme load, emit `set-face global` entries for every distinct style used by the theme.
- On theme switch, re-emit faces and re-highlight buffers.
- Cache per-theme face maps so a theme switch is O(1) after first use.

## Configuration

### Location
- `~/.config/giallo.kak/config.toml` (mirrors kak-tree-sitter convention).

### Suggested schema
- `theme = "catppuccin-frappe"`
- `language_map = { javascript = "javascript", typescript = "typescript", ... }`
- `dump_path = "..."` (optional)
- `prefer_builtin_dump = true` (default)
- `remove_default_highlighter = true`

## Compatibility with kak-tree-sitter
- This integration is independent of `kak-tree-sitter`, but follows its `ranges`-based approach.
- Users can enable either or both; the last-installed highlighter wins for a buffer.
- Face names use a distinct prefix to avoid collisions.

## Performance considerations
- Highlighting is full-buffer for v1; this is simplest and reliable.
- Use a debounce on updates (e.g., 50-100ms) to avoid work on rapid edits.
- Limit highlight to a maximum buffer size (configurable), fallback to no highlighting if exceeded.
- Cache `Registry` and compiled theme results across requests.

## Failure modes and fallbacks
- Unknown language: fallback to a plain grammar (`PLAIN_GRAMMAR_NAME` in giallo) or disable.
- Missing theme: fallback to a known default (configurable).
- IPC failure: log and disable highlights for the buffer.

## Milestones
1) **MVP**: giallo-kak server + Kakoune script, full-buffer highlights, built-in dump only.
2) **Config**: user config for theme/lang mapping and custom dump.
3) **Performance**: debounce, buffer size limit, caching.
4) **Quality**: diagnostics, sample themes, docs.