<p align="center">
<img src="./assets/image.png" alt="Lattice logo" style="zoom:25%" />
</p>

# Lattice

Lattice is a hard fork of [another Liger fork](https://github.com/nobodywasishere/liger). It is an editor-agnostic language server for the Crystal programming language, exposing a full Language Server Protocol implementation with significant architectural improvements, a persistent symbol index, a PSI layer, an integrated linter, and a full CLI. Zed, Neovim, and Helix are all first-class clients.

---

## Table of Contents

- [Architecture](#architecture)
- [Features](#features)
- [Building from Source](#building-from-source)
- [Ameba](#ameba)
- [Installation](#installation)
  - [Linux](#linux)
  - [macOS](#macos)
  - [Windows](#windows)
- [Staying Up to Date](#staying-up-to-date)
- [Configuration](#configuration)
- [Editor Support](#editor-support)
- [CLI Commands](#cli-commands)
- [Authors](#authors)
- [License](#license)

---

## Architecture

Lattice is designed in layers. Intelligence flows downward; editor integration flows upward. No layer may import from a layer above it.

```txt
Layer 1 — Core Engine       src/crystal/
  PSI, type inference, symbol resolution, indexing, diagnostics logic.
  Pure library. No LSP, no editors, no JSON-RPC.
  Subdirectories:
    psi/          — PSI element and file wrappers
    index/        — FileIndex, workspace Index, IndexingManager
    completion/   — completion provider and per-context provider modules
    inspections/  — PSI-native inspections (unused var/param, shadowed var,
                    missing return, redundant require, unnecessary not_nil!,
                    constant in interpolation, empty rescue, Ameba shell-out)

Layer 2 — LSP Adapter       src/lsp/
  Translates LSP <-> core engine. Stateless. No business logic.
  If it's not in the LSP spec, it doesn't belong here.
  Subdirectories:
    server/       — handler groups split by concern:
                    code_actions.cr, code_lens.cr, formatting.cr, navigation.cr

Layer 3 — CLI               src/cli/
  Entry point and sub-commands (check, doctor, init, clear-cache, check-update).

Layer 4 — Editor Extensions (separate repositories)
  crystal-enhanced  — Zed extension; launches LSP, registers language, Zed UI affordances.
  Neovim            — standard LSP client configuration.
  Helix             — languages.toml configuration.
```

---

## Features

Text Synchronization and Transport, Diagnostics (push and pull models), Code Completion, Go-to-Definition, Type Definition, Implementation, Hover Documentation, Signature Help, Find References, Symbol Rename, Semantic Tokens, Inlay Hints, Inspections (unused variable/parameter, shadowed variable, missing return, Ameba integration, and more), Code Actions, Code Lens, Color Presentation, Formatting, On-Type Formatting, Document Highlight, Folding Ranges, Selection Range, Linked Editing Range, Document Links, Call Hierarchy, Type Hierarchy, Document Symbols, Workspace Symbols, and a Persistent Symbol Index.

See [docs/general/extendedREADME.md](docs/general/extendedREADME.md) for detailed feature documentation.

Not all features are available in every editor. See the [Feature Availability by Editor](docs/general/LatticeFeatureMatrix.md#feature-availability-by-editor) table for a full breakdown.

---

## Building from Source

### Prerequisites

- Crystal compiler >= 1.20.0
- Git

### Tree-sitter Submodule

Lattice embeds [tree-sitter-crystal](https://codeberg.org/DaZhi-the-Revelator/tree-sitter-crystal) as a Git submodule at `tree_sitter_crystal/`. It is not a shard dependency and must be checked out via Git.

```txt
git clone --recurse-submodules https://codeberg.org/DaZhi-the-Revelator/lattice.git
cd lattice
shards install
shards build --release
```

If you already cloned without `--recurse-submodules`, run this inside the `lattice` directory:

```txt
git submodule update --init --recursive
```

The compiled binary is placed at `bin/lattice` (`bin/lattice.exe` on Windows).

---

## Ameba

Lattice shells out to the `ameba` binary for lint diagnostics. **Ameba is not installed by the Lattice build** — install it separately and ensure the `ameba` binary is on your `PATH`.

For full install instructions, see: <https://github.com/crystal-ameba/ameba#installation>

To build from source:

```txt
git clone https://github.com/crystal-ameba/ameba.git
cd ameba
make install
```

If `ameba` is not on your system `PATH`, point Lattice at it directly via `.lattice.yml`:

```txt
ameba_path: "/path/to/ameba"
```

Run `lattice doctor` to confirm detection.

---

## Installation

### Linux

Copy the binary to a directory on your `PATH`:

```txt
cp bin/lattice ~/.local/bin/lattice
```

Verify the installation:

```txt
lattice --version
# v0.8.x
```

### macOS

No pre-built macOS binary is currently distributed. See [docs/general/macOS.md](docs/general/macOS.md) for a full step-by-step build and install guide.

### Windows

Copy the binary to a directory on your `PATH` using PowerShell (run from the `lattice` directory):

```txt
Copy-Item .\bin\lattice.exe "$env:USERPROFILE\.local\bin\lattice.exe"
# Add that directory to your PATH if it is not already there
```

Verify the installation:

```txt
lattice --version
# v0.8.x
```

---

## Staying Up to Date

Pull the latest fixes and rebuild:

```txt
git pull
shards build --release
# copy the new binary to PATH as above
```

To check whether you are on the latest release without rebuilding:

```txt
lattice check-update
```

---

## Configuration

Run `lattice init` to scaffold a `.lattice.yml` config file in the current directory:

```txt
lattice init
```

Key settings:

```txt
# .lattice.yml

# Path(s) to Crystal source roots (relative to this file).
source_dirs:
  - src

# Path to the ameba binary used for linting (leave blank to auto-detect).
ameba_path: ""

# Enable strict type-checking mode.
strict_mode: false

# Cache directory for the persistent symbol index.
cache_dir: .lattice-cache

# Logging level: debug | info | warn | error
log_level: warn
```

Initialization options can also be supplied at runtime via the LSP `initializationOptions` field and take precedence over the config file. See [docs/general/extendedREADME.md](docs/general/extendedREADME.md#configuration) for the full list of feature toggles.

---

## Editor Support

| Editor | Status | Docs |
|---|---|---|
| Zed | First-class | [docs/Zed/README.md](docs/Zed/README.md) |
| Neovim | First-class | [docs/Neovim/README.md](docs/Neovim/README.md) |
| Helix | First-class | [docs/Helix/README.md](docs/Helix/README.md) |

---

## CLI Commands

| Command | Description |
|---|---|
| `lattice check <path>` | Run offline Crystal syntax diagnostics on files or directories |
| `lattice doctor` | Check environment prerequisites (Crystal, ameba, shards) |
| `lattice fmt [path]` | Format Crystal source via `crystal tool format`; CI-safe exit codes |
| `lattice init [dir]` | Scaffold a `.lattice.yml` config file |
| `lattice clear-cache` | Delete the `.lattice-cache/` persistent index directory |
| `lattice check-update` | Check whether a newer release is available on Codeberg |
| `lattice stats [path]` | Print symbol-kind counts for the workspace index |
| `lattice list-symbols [opts] [path]` | Dump all indexed symbols as JSON or plain text |

---

## Authors

- Maintained by [DaZhi-the-Revelator](https://codeberg.org/DaZhi-the-Revelator)
- Original Liger by [navid-m](https://github.com/navid-m/liger)

---

## License

MIT — see [LICENSE](LICENSE).
