aboutsummaryrefslogtreecommitdiff
path: root/jai_neovim_setup.md
blob: 1ab0ea6c5dfd6e7bc5d4a2da083dbdfdcd38205c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# Jai + Neovim: Environment & Tooling Overview

This document provides a high-level summary of the custom Neovim and `ctags` pipeline engineered for Jai development. Because Jai does not yet have a mature, universally standard Language Server Protocol (LSP) that handles all edge cases perfectly, this setup relies on a heavily customized, robust `ctags` and fuzzy-finding (`fzf-lua`) integration.

## 1. The Core Philosophy

Instead of fighting with incomplete LSPs, we built a **data-driven tag indexer** (`ctags`) paired with a **smart fuzzy finder** (`fzf-lua`) and **custom Neovim Lua parsers**. This setup guarantees instant jumps to definitions and references, even when dealing with Jai's unique syntax quirks.

## 2. Jai Syntax Quirks & The Backslash Problem

Jai has a unique syntax feature: a backslash (`\`) followed by whitespace inside an identifier is completely ignored by the compiler. This allows developers to split long variable names across lines or format them visually.

*Example:* `free_site_trace` and `free\ _site_trace` are evaluated identically by the Jai compiler.

### The Challenge
Standard text editors and indexers fail completely here:
- **Neovim** sees them as separate words because `\` and spaces break standard keyword boundaries.
- **ctags** natively index strings literally, so it would index `free\ _site_trace` with the slash included, making it unsearchable.
- **grep** cannot find references if they are visually split.

### The Solution: A Custom Pipeline
We engineered a 3-part pipeline to solve this globally:

1. **Custom `~/.ctags.d/jai.ctags`:** We extended the regular expressions to aggressively capture any identifier containing letters, numbers, underscores, backslashes, and tabs/spaces (`[a-zA-Z0-9_\\\ \t]+`).
2. **Perl Post-Processing:** Every time a `.jai` file is saved, a background job runs `ctags`, followed immediately by a highly optimized Perl script (`perl -i -F'\t' -lane ...`). This script intercepts the newly generated `tags` file and scrubs all backslashes and whitespace out of the tag names. The result? A pristine, normalized tag index.
3. **Custom Lua Parser:** We bypassed Neovim's native `<cword>` (current word) extraction. Instead, `~/.config/nvim/lua/jai_ctags.lua` contains a custom parser that reads the current line, walks left and right from the cursor, skips over `\` and whitespace, and perfectly extracts the underlying normalized identifier.

## 3. Keybindings & Navigation

The custom Lua parser feeds directly into the following heavily optimized keybindings:

### `<leader>b` : Build & Quickfix
- **Action:** Compiles the project using `jai build.jai - src/main.jai`.
- **How it works:** Hooks natively into Neovim's `makeprg`. We wrote a custom `errorformat` (`%f:%l\,%c:\ %m,%f:%l:\ %m`) that teaches Neovim exactly how to parse Jai compiler errors.
- **Result:** If the build fails, a Quickfix window pops up at the bottom of the screen. Pressing `Enter` on any error jumps you exactly to the file, line, and column.

### `gd` and `<space>D` : Instant Goto Definition
- **Action:** Jumps instantly to the definition of the symbol under your cursor.
- **How it works:** Uses the custom Lua parser to grab the normalized word, then triggers native Vim `:tag` jumping (which behaves exactly like `<C-]>`).

### `<leader>d` : Interactive Goto Definition
- **Action:** Opens an `fzf-lua` fuzzy-finder menu pre-filled with definitions.
- **When to use:** Use this when a variable name (like `data`) is shadowed or heavily overloaded across multiple files. It lets you visually pick the exact scope you want to jump into.

### `gr` : Goto References
- **Action:** Finds all occurrences/usages of the symbol under your cursor across the entire codebase.
- **How it works:** Grabs the normalized word and dynamically constructs a PCRE regular expression (e.g., `f[ \t\\]*r[ \t\\]*e...`) that interleaves optional backslash and whitespace matchers between every character. It passes this regex to `fzf-lua grep`.
- **Result:** It flawlessly finds all references to a variable, even if the reference is split with a `\` in the source code!

## 4. Configuration Locations

- **`~/.ctags.d/jai.ctags`**: The regex engine rules for universal-ctags to parse Jai syntax.
- **`~/.config/nvim/lua/jai_ctags.lua`**: The brains of the operation. Contains the autocmds, the custom Lua identifier parser, the background tag generation pipeline, and the `fzf-lua` keybindings.
- **Tag Exclusions**: The `ctags` command explicitly excludes `maze-rs/` and `how_to/` directories to prevent tutorial/sandbox files from polluting the global index and causing definition collisions (e.g., `array_add`).