{"id":50467853,"url":"https://github.com/dhruvasagar/lattice","last_synced_at":"2026-06-01T08:30:50.709Z","repository":{"id":355415199,"uuid":"1227231339","full_name":"dhruvasagar/lattice","owner":"dhruvasagar","description":"Yet another text editor that tries to bring together the best of vim \u0026 emacs","archived":false,"fork":false,"pushed_at":"2026-05-31T10:53:31.000Z","size":18150,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-31T12:19:49.732Z","etag":null,"topics":["emacs","rust","text-editor","vim"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dhruvasagar.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-02T11:50:45.000Z","updated_at":"2026-05-31T10:53:44.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/dhruvasagar/lattice","commit_stats":null,"previous_names":["dhruvasagar/lattice"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dhruvasagar/lattice","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhruvasagar%2Flattice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhruvasagar%2Flattice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhruvasagar%2Flattice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhruvasagar%2Flattice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dhruvasagar","download_url":"https://codeload.github.com/dhruvasagar/lattice/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhruvasagar%2Flattice/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33767434,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["emacs","rust","text-editor","vim"],"created_at":"2026-06-01T08:30:49.627Z","updated_at":"2026-06-01T08:30:50.687Z","avatar_url":"https://github.com/dhruvasagar.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\t\u003cimg src=\"./assets/readme-banner.svg\" alt=\"Lattice - a modal, GPU-accelerated, plugin-first text editor in Rust\" width=\"720\" /\u003e\n\u003c/p\u003e\n\nA modal, GPU-accelerated, plugin-first text editor written in Rust. Combines\n**vim's modal editing power** with **emacs's extensibility model** on a\nnon-blocking, multi-threaded core where the UI thread does no I/O, no parsing,\nand no shaping.\n\n\u003e **Status:** Pre-1.0 / heavy development. Phases 0–4 of the design roadmap\n\u003e are landed (foundation, modal engine, terminal UI, tree-sitter, LSP);\n\u003e **Phase 5 (GPU rendering + architectural asynchrony enforcement) is structurally complete** —\n\u003e the Editor now runs on its own dedicated thread, the `\u0026mut Editor` type\n\u003e cannot escape that thread in production builds (compile-time enforced\n\u003e via the `EditorActorHandle` swap, slice `3c.final.E.swap`), and both\n\u003e TUI and GPUI peers are editable against a live LSP backend\n\u003e (rust-analyzer tested). Outstanding Phase 5 work is perf-driven: queued\n\u003e RenderState lifts in\n\u003e [`docs/dev/operations/3c-final-b-extension.md`](docs/dev/operations/3c-final-b-extension.md).\n\u003e The WASM plugin host arrives in Phase 7. See\n\u003e [`docs/dev/operations/implementation.md`](docs/dev/operations/implementation.md)\n\u003e for the per-feature ledger.\n\n---\n\n## Why another editor?\n\nThree editors dominate today: Vim/Neovim (best modal editing, single-threaded\ncore, vimscript-only first-class config), Emacs (best extensibility, single-\nthreaded core, elisp-only first-class config), and VS Code (best plugin\necosystem, web stack, latency dominated by Electron).\n\nLattice picks the strongest property from each and rebuilds them on a modern\nfoundation:\n\n- **Strict vim grammar.** Counts, registers, operators, motions, text\n  objects, ex-ranges, dot-repeat, marks, macros — semantics preserved\n  exactly. The grammar is the public command API; the default keymap is a\n  config file.\n- **Emacs-class extensibility through WebAssembly.** Plugins are sandboxed\n  WASM components: cross-language, capability-gated, fuel-limited,\n  crash-isolated. A misbehaving plugin cannot freeze the editor.\n- **Sub-frame input latency.** Keystroke → glyph in \u003c8 ms at 120 Hz. The UI\n  thread never blocks. Multi-threaded by construction (one tokio task per\n  document, snapshot-based render reads, bounded-mailbox dispatch).\n- **GPU-accelerated rendering.** Sub-pixel-precise text, smooth scroll,\n  layered paint paths optimized per content type (code vs. rich text vs.\n  inline media). TUI is a first-class peer — not a throwaway.\n\nThe full design is in [`docs/dev/architecture/design.md`](docs/dev/architecture/design.md) (v0.4, ~2300 lines).\n\n---\n\n## Paramount goals\n\nIn priority order when they conflict:\n\n1. **Performance.** Sub-frame input latency. Per-call WASM overhead\n   budgeted in CI (typed call \u003c 500 ns p99; grammar-extension round-trip \u003c\n   5 µs p99).\n2. **Extensibility.** WebAssembly Component Model plugin host from day one.\n   WIT is the canonical API. Plugins ship in any language with\n   component-model toolchain support (Rust, Zig, Go, AssemblyScript, …).\n3. **Extensible vim modal editing.** Strict vim semantics. The grammar\n   (operators, motions, text objects, registers, ranges, counts) IS the\n   public command API. Adding new motions / text objects / operators is\n   first-class — including future tree-sitter-driven variants.\n4. **Asynchronicity.** Three-layer architecture (UI / Core / Plugins)\n   communicating via typed message passing. Multi-threaded by construction.\n   Each plugin instance owns its own `wasmtime::Store` and runs as a tokio\n   task; many plugins execute in parallel across cores.\n\nThree deliberate deviations from vim and emacs:\n\n- **Unified command / grammar dispatch.** Vim's `:` ex-command world and\n  the functional / plugin world are merged into one `CommandRegistry` with\n  one dispatcher. The `:` line stays vim DSL (no function-call / palette\n  syntax — explicit non-goal); plugins / `init.rs` / Rust callers\n  construct `CommandInvocation` directly via the WIT host. Two input\n  surfaces, one substrate. Every command is reachable from `:` via the\n  kind-prefix form (`:motion goto-first-line`, `:operator delete word-\n  forward`). (DESIGN.md §2.2 + §5.2.1.)\n- **Everything is a buffer.** File tree, outline, diagnostics, search\n  results, terminal, REPL — all are buffers placed by the user into panes\n  via splits. The unified `BufferRegistry` already holds documents and\n  file trees today; `:bn` / `:bp` / `:ls` / `:bd` work across kinds. No\n  fixed sidebar or bottom-panel concept. (§5.9.)\n- **One extension substrate, two config layers.** `options.toml` for static\n  data; `init.rs` (compiled to WASM, auto-built on first boot, cached) for\n  programmable config. `init.rs` is a plugin with `boot` capability — the\n  same WIT, same toolchain, same host as third-party plugins. No vimscript,\n  no elisp, no Lua, no embedded scripting language. See DESIGN.md §5.12.\n\n---\n\n## Architecture\n\nThree layers, communicating only via typed messages and wait-free snapshot\nloads:\n\n```mermaid\nflowchart TD\n\tUI[\"\u003cb\u003eUI Layer\u003c/b\u003e\u003cbr/\u003e\u003ccode\u003elattice-ui-tui\u003c/code\u003e \u0026nbsp;(future GPU renderer)\u003cbr/\u003e• Renders snapshots; never blocks; never holds locks\u003cbr/\u003e• Translates input → CommandInvocation\"]\n\n\tCore[\"\u003cb\u003eCore Layer\u003c/b\u003e\u003cbr/\u003e\u003ccode\u003elattice-runtime\u003c/code\u003e + \u003ccode\u003elattice-core\u003c/code\u003e + \u003ccode\u003elattice-grammar\u003c/code\u003e\u003cbr/\u003e• One DocumentActor per open document (tokio task)\u003cbr/\u003e• Owns the writable Document; bounded mpsc mailbox\u003cbr/\u003e• Publishes immutable snapshots via arc-swap\u003cbr/\u003e• Grammar dispatcher: motions, operators, text objects,\u003cbr/\u003e\u0026nbsp;\u0026nbsp;ex-commands, plugin contributions — peers, not\u003cbr/\u003e\u0026nbsp;\u0026nbsp;separated worlds\"]\n\n\tPlugin[\"\u003cb\u003ePlugin Layer\u003c/b\u003e \u0026nbsp;\u003ci\u003e(planned)\u003c/i\u003e\u003cbr/\u003e\u003ccode\u003elattice-plugin-host\u003c/code\u003e\u003cbr/\u003e• wasmtime + Component Model + WASI\u003cbr/\u003e• One Store per plugin instance, runs as a tokio task\u003cbr/\u003e• Capability-gated, fuel-limited, crash-isolated\"]\n\n\tUI --\u003e|\"\u003cb\u003eDocumentHandle\u003c/b\u003e (cheap clone)\u003cbr/\u003e• snapshot() — wait-free Arc load\u003cbr/\u003e• dispatch_with_cancel() — Pending\u0026lt;Effect\u0026gt;\u003cbr/\u003e• apply_edit() — Pending\u0026lt;AppliedEdit\u0026gt;\"| Core\n\tCore -.-\u003e|\"WIT-defined ABI\u003cbr/\u003e\u003ci\u003e(planned)\u003c/i\u003e\"| Plugin\n\n\tclassDef done fill:#1f4d2c,stroke:#2ea043,color:#e6edf3\n\tclassDef planned fill:#3d2a1a,stroke:#bf8700,color:#e6edf3,stroke-dasharray:5 5\n\tclass UI,Core done\n\tclass Plugin planned\n```\n\n### Crate map\n\n| Crate                  | Purpose                                                                                                  | Status      |\n|------------------------|----------------------------------------------------------------------------------------------------------|-------------|\n| `lattice-protocol`     | Bottom-layer types: `Position`, `Range`, `Edit`, `Selection`, `CancellationToken`, `Event`, ID newtypes. | ✅ stable   |\n| `lattice-core`         | `Buffer` (ropey-backed), `Document` with batched undo, file I/O, regex search (fancy-regex w/ backrefs). | ✅ stable   |\n| `lattice-grammar`      | Vim modal state machine, `CommandRegistry`, dispatcher, built-in motions/operators/text objects/ex-cmds. | ✅ stable   |\n| `lattice-runtime`      | `DocumentActor` + `DocumentHandle` (tokio task per doc), arc-swap snapshots, `Pending\u003cT\u003e`, event bus.    | ✅ stable   |\n| `lattice-syntax`       | Tree-sitter integration (Rust / Python / JavaScript / Markdown bundled), incremental parse, highlights.  | ✅ stable   |\n| `lattice-completion`   | Pluggable completion pipeline: generators, matchers, rankers, annotators.                                | ✅ stable   |\n| `lattice-config`       | Typed-options registry (`OptionType` + `ArcSwap`-backed cells), `:set` parser, `gen:options` source.     | ✅ stable   |\n| `lattice-mode`         | Major / minor mode trait surface, lifecycle events, mode registry, mode-async epoch.                     | ✅ stable   |\n| `lattice-help`         | `HelpContent` + `HelpBuffer` + per-line markdown highlight cache; backing for `:help` and `:describe-*`. | ✅ stable   |\n| `lattice-picker`       | Picker primitive: source registry, candidate batches, live-query subsystem, MRU frecency.                | ✅ stable   |\n| `lattice-snippet`      | Snippet parser + registry; lazy expansion against `editor.snippet_registry` (ArcSwap).                   | ✅ stable   |\n| `lattice-file-tree`    | File-tree buffer kind + per-buffer state types.                                                          | ✅ stable   |\n| `lattice-oil`          | Oil-style directory buffer kind + state types.                                                           | ✅ stable   |\n| `lattice-lsp`          | LSP client: actor pool, capability fingerprinting, diagnostics layer, supervisor, watcher subscriptions. | ✅ stable   |\n| `lattice-host`         | Renderer-agnostic substrate. Owns `Editor`, dispatch, mode lifecycle, options cascade, `RenderState`, `PerBufferCache`, LSP watcher task. | ✅ stable   |\n| `lattice-ui-tui`       | Terminal UI peer: crossterm + ratatui, modal cursor, gutter, hlsearch, command line, popups, picker UI.  | ✅ stable   |\n| `lattice-ui-gpui`      | GPU UI peer (feature `window`): GPUI + blade rendering, symmetric capability with the TUI peer.          | 🚧 partial parity |\n| `lattice-cli`          | Binary entry-point. `--tui` / `--gui` flag routes to either peer; tokio multi-thread main.               | ✅ stable   |\n| `lattice-config-macros`| Proc-macro for typed-option / `OptionGroup` registration via `linkme` distributed slices.                | ✅ stable   |\n| `lattice-plugin-host`  | WASM Component Model host. **Planned (Phase 7).**                                                        | ⛔ planned  |\n\n---\n\n## Quick start\n\n**Requirements**\n\n- Rust 1.94+ (edition 2024)\n- A POSIX terminal that handles 256 colors and bracketed paste\n\n**Build \u0026 run (TUI — default)**\n\n```sh\ncargo build --release\ncargo run --release -- README.md\n```\n\nThe CLI opens the file in the TUI. Editing is full vim modal.\n\n**Build \u0026 run (GPUI — GPU renderer)**\n\n```sh\ncargo run --release --features gui -- --gui README.md\n```\n\nPass `--gui` to route to the GPUI peer. `--tui` explicitly forces the terminal\nrenderer. The two flags are mutually exclusive; the default stays TUI for direct\ninvocations.\n\n**macOS app bundle**\n\n```sh\n# Install once:\ncargo install cargo-bundle\n\n# Build the .app (must cd into the binary crate — cargo-bundle has no -p flag):\ncd crates/lattice-cli\ncargo bundle --release --features gui\n\n# Open:\nopen ../../target/release/bundle/osx/Lattice.app\n```\n\nThe bundle auto-routes to the GPUI renderer (no `--gui` flag needed) via\nbundle-context detection: when the binary runs inside `…/Contents/MacOS/`, it\ndetects the `Contents` path component and selects GUI automatically. Pass\n`--tui` to override. The icon comes from `assets/lattice.icns` (10 sizes,\n16–512 px + @2x), configured in `[package.metadata.bundle]` in\n`crates/lattice-cli/Cargo.toml`.\n\n**Linux desktop entry**\n\n```sh\nsudo cp assets/linux/com.lattice-editor.lattice.desktop \\\n         /usr/share/applications/\nsudo cp assets/favicon-64.png \\\n         /usr/share/icons/hicolor/64x64/apps/com.lattice-editor.lattice.png\ngtk-update-icon-cache -f /usr/share/icons/hicolor/\n```\n\n**Run tests**\n\n```sh\ncargo test --workspace        # ~1784 tests, sub-second\ncargo clippy --workspace      # workspace lints (deny unsafe outside opt-in)\n```\n\n**Run benchmarks**\n\n```sh\ncargo bench --workspace\n```\n\nNumbers are tracked in [`docs/dev/operations/benchmarks.md`](docs/dev/operations/benchmarks.md).\n\n**Editor sanity tour**\n\nIn the running editor:\n\n- `i a o O` — Insert / append / open below / open above\n- `h j k l w b e gg G` — motions\n- `dd 2dd dw daw diw` — delete with operators / counts / text objects\n- `yy 2yy p P` — yank / paste\n- `u \u003cC-r\u003e` — undo / redo (every operator lands as one undo unit)\n- `Ctrl-V` then `Ij\u003cEsc\u003e` — block-visual insert; `\u003e` indents block lines\n- `/foo\u003cCR\u003e n N` — incremental search (regex with backrefs)\n- `:%s/foo/bar/g` — substitute (`$1`, `${name}` template syntax)\n- `:describe-command write` — every primitive carries help metadata\n- `:motion goto-first-line` — invoke any motion / operator / text-object by name (chord grammar still preferred for typing)\n- `:operator delete word-forward` — operator + bare target (motion / text-object resolved implicitly)\n- `\u003cC-w\u003ev` then `\u003cC-w\u003el` — split vertically and focus the right pane\n- `:Tree .` (or `:e some-folder`) — open a folder as a file-tree buffer; `\u003cCR\u003e` toggles directories or opens files\n- `:bn` / `:bp` / `:ls` / `:bd` — cycle, list, or close any open buffer (document or tree)\n- `:set foldmethod=indent` — auto-fold indented blocks; `zo` / `zc` to open / close\n- `:set ui.dim_inactive=off` — turn off the inactive-pane DIM overlay\n- `:help` — open the topic index; `:help folding` / `:help buffers` for deep-dive docs (`\u003cTab\u003e` completes)\n\n---\n\n## What distinguishes Lattice\n\nAmong modern editors built on Rust + GPU + tree-sitter + LSP + WASM (the only stack that hits sub-frame latency without compromising extensibility, and one Lattice shares with Zed deliberately), the differentiators are:\n\n- **Vim grammar is the public command API**, not a key mapping over a non-modal core. One dispatcher; ex-commands, chords, and plugin contributions all flow through `CommandInvocation`. Adding a motion *is* extending the grammar.\n- **Everything is a buffer, enforced**. File tree, diagnostics list, terminal, `*messages*`, scratch — all are buffers placed by the user into panes via splits. There is no sidebar / bottom-panel concept. Every text operation works on every buffer kind through one code path.\n- **WIT is the canonical plugin API today** (not aspirationally). Any Component-Model language speaks the same protocol — Rust, Zig, Go, AssemblyScript. CI-gated overhead budgets (typed-call \u003c 500 ns p99, grammar-extension round-trip \u003c 5 µs p99).\n- **Asynchrony is architectural, not disciplinary**. Other editors keep the UI thread free by convention — contributors know which calls might block. Lattice (DESIGN.md §5.7) chooses primitives that make UI-thread blocking *physically impossible* in the steady state: `RenderState` for reads, `Arc\u003cArcSwapOption\u003cT\u003e\u003e` / `PerBufferCache\u003cT\u003e` for writes, dedicated subsystem tasks for everything else. The architecture stays uniform under feature pressure.\n\nThe detailed framing — what Lattice converges with Zed on, where it diverges deliberately, what we evaluated (Zed's `cx.notify()` reactive paint — assessed and deferred; the savings curve doesn't transfer to Lattice's cursor-coupled UI), and what we explicitly don't borrow (imposed layouts, custom rope, single-language extensions) — is in [DESIGN.md Appendix C](docs/dev/architecture/design.md).\n\n---\n\n## Performance commitments\n\nTracked against [DESIGN.md §8.2](docs/dev/architecture/design.md). Latest measured numbers in\n[`docs/dev/operations/benchmarks.md`](docs/dev/operations/benchmarks.md):\n\n| Commitment                   | Target (p99) | Status                                               |\n|------------------------------|--------------|------------------------------------------------------|\n| Keystroke → buffer mutation  | \u003c 100 µs     | ✅ ~83 µs constant across buffer sizes               |\n| Reflex motion / operator     | \u003c 2 ms       | ✅ all under budget on 50k-line buffers              |\n| Search (literal pattern)     | \u003c 2 ms       | ✅ all variants under 2 ms on 200k-line buffers      |\n| Snapshot load (renderer)     | \u003c 5 ns       | ⚠️ ~17 ns (`load_full` Arc bump — known headroom)    |\n| WASM typed call (planned)    | \u003c 500 ns     | ⛔ Phase 7                                           |\n\nThe architectural rule: **the UI thread does no I/O, no parsing, no\nshaping.** Document mutations route through the actor; renderers read\nwait-free snapshots; cancellation is cooperative (Reflex commands observe a\nflipped `CancellationToken` within ~100 µs).\n\n---\n\n## Roadmap\n\n11 phases. The detailed status ledger is in\n[`docs/dev/operations/implementation.md`](docs/dev/operations/implementation.md); the phase-level summary:\n\n| Phase | Title                                  | Status      |\n|-------|----------------------------------------|-------------|\n| 0     | Foundation                             | ✅ done     |\n| 1     | Modal Editing                          | ✅ done     |\n| 2     | Terminal UI Bootstrap                  | ✅ done     |\n| 3     | Tree-sitter (Rust / Python / JS / MD)  | ✅ done     |\n| 4     | LSP                                    | ✅ done     |\n| 5     | GPU Rendering + architectural async    | ✅ structurally complete (Editor on its own thread via `EditorActorHandle`; goal #4 compile-time enforced). Perf B-extension lifts queued. |\n| 6     | Document Renderer + UI Components      | ⛔ planned  |\n| 7     | Plugin Host (WASM Component Model)     | ⛔ planned  |\n| 8     | Major / Minor Modes + Reference Plugins| ⛔ planned  |\n| 9     | Rich Buffer Rendering                  | ⛔ planned  |\n| 10    | Polish + v1.0                          | ⛔ planned  |\n\n### Detailed feature checklist\n\nThe granular pre-Phase-4 polish plan, plus the upcoming Phase 4 work:\n\n**Async runtime + cancellation** (DESIGN.md §5.2, §5.6.8, §5.7)\n\n- [x] `DocumentActor` + bounded-mailbox dispatch (one tokio task per doc)\n- [x] `arc-swap` snapshot publish-before-reply contract\n- [x] `Pending\u003cT\u003e` typed handles for every mutating call\n- [x] Cooperative `CancellationToken` (grammar + actor + search loops)\n- [x] Actor stress tests (mailbox saturation, concurrent senders, snapshot ordering)\n- [ ] Per-`LatencyClass` deadline timers (Reflex \u003c 2 ms, Display \u003c 10 ms)\n- [ ] Plugin async-task host primitive (Phase 7)\n\n**Vim modal editing** (DESIGN.md §5.2)\n\n- [x] Modal state machine: Normal / Insert / Visual / Op-pending / Command / Search / Replace\n- [x] Strict vim grammar: counts, registers, operators, motions, text objects, ex-ranges\n- [x] Built-in motion / operator / text-object catalog\n- [x] Macros (recorded as `CommandInvocation` sequences, not keystrokes)\n- [x] Marks, dot-repeat with insert-replay, position-history ring (§5.1.1)\n- [x] Search + hlsearch with `fancy-regex` (RE2 + bounded NFA for backrefs)\n- [x] Substitute (`:s` / `:%s`) with `$1` / `${name}` template syntax\n- [x] Block-visual `d` / `y` / `c` / `I` / `A` / `\u003e` / `\u003c` (per-row dispatch + replicate-on-Esc + single undo unit)\n- [x] Manual folds (`zf` / `zo` / `zc` / `za` / `zR` / `zM` / `zd`)\n- [x] Counts on linewise ops (`2dd`, `2\u003e\u003e`) collapse to one undo unit\n- [x] Substitute live preview (matches highlighted while typing `:s/pat/repl/...`)\n- [x] Computed folds — indent fallback (`:set foldmethod=indent`); tree-sitter folds queued\n\n**Unified command / grammar dispatch** (DESIGN.md §5.2.1)\n\n- [x] One `CommandRegistry` for ex-commands, motions, operators, text objects\n- [x] `:` line is a parser front-end producing typed `CommandInvocation`s\n- [x] Every command is reachable from `:` via the kind-prefix form (`:motion goto-first-line`, `:operator delete word-forward`, `:text-object inner-word`); ex-commands keep their bare alias surface; chord grammar stays the natural compact-typing path\n- [x] `:g/pat/body` and `:v/pat/body` parse `body` up front (no per-match re-parse)\n- [x] `Range::Selection` resolves to active visual selection\n- [x] Interactive arg-prompts via `args_schema` (any required arg arms a prompt; Chord kind auto-submits on next chord)\n\n**Event system + hooks** (DESIGN.md §5.10)\n\n- [x] Typed `Event` catalog in `lattice-protocol`\n- [x] `EventBus`: `subscribe(filter, target)`, `unsubscribe`, `publish` (kind-indexed dispatch)\n- [x] `SubscriptionTarget::Channel` (mpsc) and `SubscriptionTarget::Invocation`\n- [ ] Actor publishes events on edit / save / mode-change\n- [ ] `Before*`-event mutation / veto seam (formatters can rewrite content; `BeforeQuit` can abort)\n- [ ] `:autocmd` and `add-hook` parser front-ends desugar to `subscribe`\n\n**Self-documenting help** (DESIGN.md §5.11)\n\n- [x] Every command / option / mode / keybinding carries metadata at registration time\n- [x] `:describe-command`, `:describe-buffer`, `:describe-key`, `:keymap`, `:apropos`\n- [x] `:describe-option`, `:options` (typed options registry)\n- [x] `:help [topic]` -- free-form topic surface with `\u003cTab\u003e` completion; built-ins embedded via `include_str!` from `docs/user/*.md`; `Dynamic` body variant is the seam for LSP / plugin-supplied topics; `:describe-*` views emit \"See also\" topic cross-links\n- [ ] `:describe-event`, `:describe-mode` (each lands when its registry does)\n\n**Configuration** (DESIGN.md §5.12)\n\n- [x] **Renderer-agnostic typed-options crate** (`lattice-config`): `OptionType` trait with primitive impls (`bool`, `i64`, `String`); `Option\u003cT\u003e` with `ArcSwap\u003cT\u003e` value cell for wait-free reads; `OptionHandle\u003cT\u003e` for zero-overhead typed access; `ErasedOption` + `ConfigRegistry` for by-name lookups; `:set` parser; `gen:options` completion source — every consumer (App, plugins, future renderers) registers options through the same API\n- [x] `register_core_options(\u0026registry) → CoreOptions` for the nine renderer-agnostic options (`number`, `relativenumber`, `wrap`, `ignorecase`, `tabstop`, `foldenable`, `foldmethod`, `scrolloff`, `completion.auto_insert_single`)\n- [x] Renderer-specific options register via the same API: `lattice-ui-tui::register_tui_options(\u0026registry) → TuiOptions` covers `ui.dim_inactive`, `ui.separator`, `ui.separator_color`, `ui.statusline_active_fg`, `ui.statusline_inactive_fg`. Future GUI / web renderers register their own\n- [x] `:set name=value`, `:set name`, `:set noname`, `:set name?` parser front-end (drives `ConfigRegistry::parse_and_set_command`)\n- [x] `:describe-option \u003cname\u003e` (reads the erased view: name, aliases, type label, default, current value, enumerated values, doc)\n- [ ] `options.toml` deserializer (static settings layer)\n- [ ] `init.rs` plugin loader (Rust → WASM, auto-built on first boot, cached) — depends on Phase 7 plugin host\n- [ ] Customize-as-buffer-view writes back to `options.toml`\n- [ ] `lattice config build` diagnostic CLI subcommand\n- [ ] Project-local `.lattice/options.toml` (project-local `init.rs` deferred behind a per-directory trust prompt)\n\n**Rendering** (DESIGN.md §5.6)\n\n- [x] TUI renderer (crossterm + ratatui) — first-class peer for headless / SSH\n- [x] Display-width-aware cursor placement (CJK / Latin / emoji)\n- [x] Tree-sitter highlight emission (Rust / Python / JS / Markdown bundled)\n- [x] Markdown grammar with fenced-code injections (` ```rust``` ` blocks highlight as rust)\n- [x] Markup `Style` variants for headings (1-6), bold / italic, links, raw — themable from day one\n- [ ] GPU compositor (GPUI preferred, wgpu fallback) — Phase 5\n- [ ] `EditorRenderer` + `DocumentRenderer` + `TuiRenderer` trait split — Phase 5/6\n- [ ] Sprite atlas for icons (file-type, severity, gutter, picker, status) — §5.6.7\n- [ ] Rich-buffer rendering (variable fonts within a single buffer) — Phase 9\n\n**LSP** (DESIGN.md §5.4) — Phase 4\n\n- [ ] Diagnostics, completion, hover, go-to-definition, references\n- [ ] Cancellation (uses the cancellation-token plumbing already in place)\n- [ ] Per-server compatibility shims\n\n**Plugin host** (DESIGN.md §5.5, §9) — Phase 7\n\n- [ ] `wasmtime` + Component Model + WIT bindings\n- [ ] AOT module cache; lazy instantiation; capability manifests; fuel limits\n- [ ] Per-call overhead bench gates in CI (typed call \u003c 500 ns p99; round-trip \u003c 5 µs p99)\n- [ ] Reference plugin: `fuzzy-finder` (validates picker primitive end-to-end)\n\n**Multi-buffer + UI components** (DESIGN.md §5.9) — Phase 6\n\n- [x] **B.1.a** Buffer abstraction + active-buffer routing (help is a regular buffer; `\u003cC-o\u003e` / `\u003cC-i\u003e` walk across buffers)\n- [x] **B.1.b** Pane tree + `\u003cC-w\u003e{s,v,c,h,j,k,l,w,W}` window-management chord grammar (incl. `\u003cC-w\u003e\u003cC-l\u003e` form)\n- [x] **B.1.c** Multiple Document buffers + `:bn` / `:bp` / `:ls` / `:bd` / `:b N`\n- [x] **B.1.d** File-tree buffer (`:Tree path`); multiple roots coexist; `:e folder` defers to `:Tree folder`\n- [x] Unified `BufferRegistry`: documents and trees in one keyspace; per-buffer `BufferFlags { listed, hidden }` skeleton\n- [x] Vim-style pane visuals: per-pane status line (active reverse-videoed, inactive dim), `│` separator between vertical splits, inactive panes keep syntax highlighting with `DIM` overlay; all customizable via `:set ui.*`\n- [x] Hover popup scaffolding (`:hover [text]` / `:HoverClose`); LSP-driven hover wiring queues with Phase 4\n- [x] Inline completion popup (vertico-style, wired)\n- [ ] Picker primitive (file picker as first user)\n- [ ] Buffer-backed views: outline, diagnostics-list, scratch, messages, compilation (file-tree shipped)\n\n**CI / engineering** (DESIGN.md §8)\n\n- [x] Workspace lint policy (`unsafe_code = \"deny\"`, opt-in per module)\n- [x] Criterion benches for runtime, motions, operators, search\n- [x] Cross-platform CI matrix (Linux / macOS / Windows) + fmt + doc gates\n- [x] Bench compile-check (catches bench-code rot per platform)\n- [x] Bench baseline artifact recorded on every push to main\n- [ ] Bench regression gate (needs stable runner; shared CI variance dwarfs signal)\n- [ ] Allocation-discipline checks on the render hot path (dhat-based)\n\n---\n\n## Documentation\n\n| Doc                                       | Purpose                                                  |\n|-------------------------------------------|----------------------------------------------------------|\n| [`docs/dev/architecture/design.md`](docs/dev/architecture/design.md)        | The design spec (v0.4, authoritative for what to build). |\n| [`docs/dev/operations/implementation.md`](docs/dev/operations/implementation.md) | Per-feature status ledger; updated per session.   |\n| [`docs/dev/operations/benchmarks.md`](docs/dev/operations/benchmarks.md)| Latest measured numbers vs. §8.2 commitments.            |\n| [`docs/dev/operations/verify.md`](docs/dev/operations/verify.md)        | Manual-verification checklist for recently shipped features. |\n| [`docs/dev/architecture/lsp-architecture.md`](docs/dev/architecture/lsp-architecture.md) | LSP developer reference (companion to DESIGN.md §5.4). |\n| [`docs/dev/notes/lsp-features.md`](docs/dev/notes/lsp-features.md) | Every LSP 3.17 capability + implementation status.  |\n| [`docs/user/`](docs/user/)                | User-facing reference (the `:help`-style topic docs).    |\n| [`CLAUDE.md`](CLAUDE.md)                  | Conventions for AI-assisted contributions.               |\n\nWhen something disagrees, **DESIGN.md and IMPLEMENTATION.md are the\nauthoritative sources** for what should exist and what currently does.\n\n---\n\n## Contributing\n\nThe project is open to contributions, but please note the development model:\n\n1. **The design doc is load-bearing.** Significant features need to land in\n   `docs/dev/architecture/design.md` first (or be a refinement of an existing section). Open\n   an issue describing the design rationale before sending a PR for\n   non-trivial work.\n2. **The four paramount goals override stylistic preferences when they\n   conflict.** Performance, extensibility, vim semantics, asynchronicity —\n   in that order.\n3. **Commit history is the moving record.** Each commit is a complete unit\n   (one feature / one fix / one refactor). Tests for new behavior land in\n   the same commit.\n4. **No backwards-compatibility shims for vim or emacs configs.** Explicit\n   non-goal.\n5. **Specific edge cases may be deferred for v1.** The semantics aren't\n   altered, but rare register quirks or obscure block-visual behaviors can\n   land post-1.0 with explicit tests documenting the gap.\n\n### Good first issues\n\n- Documenting a vim grammar primitive that's missing from\n  `docs/dev/operations/implementation.md`'s catalog table.\n- Adding a built-in motion / text object behind the existing\n  `register_motion` / `register_text_object` API.\n- Adding a tree-sitter grammar (look at how `lattice-syntax` wires Rust /\n  Python / JS).\n- Closing a §15 open question with a small design proposal.\n\n### Development workflow\n\n```sh\n# Format + lint + test before pushing.\ncargo fmt --all\ncargo clippy --workspace --all-targets -- -D warnings\ncargo test --workspace\n```\n\nThe lint policy is workspace-wide: `unsafe_code = \"deny\"`. The search\nmodule opts in via `#![allow(unsafe_code)]` for one specific\n`from_utf8_unchecked` call on a streaming window — every other use must\ndocument its invariant.\n\n---\n\n## License\n\nLicensed under the [MIT License](LICENSE).\n\nUnless you explicitly state otherwise, any contribution intentionally\nsubmitted for inclusion in the work by you shall be licensed as above,\nwithout any additional terms or conditions.\n\n---\n\n## Acknowledgements\n\nThe design draws on three editors that got things right:\n\n- **Vim / Neovim** — the modal grammar (counts × operators × motions × text\n  objects) is one of the great ideas in editor design. We adopt it\n  wholesale.\n- **Emacs** — the everything-is-a-buffer principle, the self-documenting\n  help system, and the customize-as-buffer-view model are all here.\n- **Zed** — the GPUI rendering stack is the same one Lattice uses, and the\n  modern-Rust editor playbook (GPU rendering, tree-sitter, native LSP,\n  WASM extensions) is shared on purpose. Where Lattice diverges\n  deliberately — modal grammar as the public API, everything-is-a-buffer\n  enforced, WIT as the canonical plugin interface, *architectural* (not\n  disciplinary) async — is laid out in\n  [DESIGN.md Appendix C](docs/dev/architecture/design.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdhruvasagar%2Flattice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdhruvasagar%2Flattice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdhruvasagar%2Flattice/lists"}