diff options
| author | Alec Goncharow <alec@goncharow.dev> | 2026-07-10 12:41:25 -0400 |
|---|---|---|
| committer | Alec Goncharow <alec@goncharow.dev> | 2026-07-10 12:41:25 -0400 |
| commit | f1a2a3499a35a045ca5ae89aa91f848837b6ab72 (patch) | |
| tree | b3084cff15c1388719d982aaaa71d6db7afb3333 /jai_neovim_setup.md | |
| parent | 356465b85ba7e16eaaec68cbc22cd5e84a0a2a44 (diff) | |
Diffstat (limited to 'jai_neovim_setup.md')
| -rw-r--r-- | jai_neovim_setup.md | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/jai_neovim_setup.md b/jai_neovim_setup.md new file mode 100644 index 0000000..1ab0ea6 --- /dev/null +++ b/jai_neovim_setup.md @@ -0,0 +1,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`). |
