Open-Source Wikis

/

Helix

/

Helix

/

Architecture

helix-editor/helix

Architecture

Helix is a Cargo workspace split into focused crates. The core editing primitives are functional and frontend-agnostic; the terminal UI is one of (currently the only) frontend layered on top.

The layering deliberately reflects a long-term goal: make helix-core plus helix-view reusable from a non-terminal frontend (the project vision mentions exploring a wgpu renderer). In practice today, helix-view still has terminal-shaped assumptions, but the boundary between core data structures and rendering is enforced by the crate split.

Crate map

Crate Lines Description Source
helix-stdx ~2.2k Path, env, file-access, range, and rope helpers shared across crates. helix-stdx/src
helix-parsec ~0.6k A small parser-combinator library used by snippet parsing. helix-parsec/src/lib.rs
helix-event ~1.1k Synchronous hooks, async hooks, debouncing, and a global redraw lock. helix-event/src
helix-loader ~1.2k Locates config/runtime dirs, fetches and builds tree-sitter grammars. helix-loader/src
helix-core ~19.6k Rope, Selection, Transaction, Syntax, indent, movement, snippets. helix-core/src
helix-view ~14.5k Editor, Document, View, Tree, theme, registers, clipboard, gutter, input. helix-view/src
helix-tui ~5.9k TUI primitives forked from tui-rs (buffers, layouts, widgets, backends). helix-tui/src
helix-term ~30.6k Terminal frontend: application loop, commands, keymap, UI components. helix-term/src
helix-lsp ~4.0k LSP client transport, server registry, JSON-RPC. helix-lsp/src
helix-lsp-types ~9.9k LSP protocol type definitions (vendored). helix-lsp-types/src/lib.rs
helix-dap ~1.1k Debug Adapter Protocol client. helix-dap/src
helix-dap-types ~1.0k DAP protocol type definitions. helix-dap-types/src/lib.rs
helix-vcs ~1.3k Diff provider abstraction; git is the only backend today. helix-vcs/src
xtask Ad-hoc task runner: docgen, query-check, theme-check. xtask/src

Layered view

graph TD
    subgraph Frontend
        Term[helix-term<br/>commands, keymap, UI]
        Tui[helix-tui<br/>buffers, widgets, backends]
    end
    subgraph Editor State
        View[helix-view<br/>Editor, Document, View, Tree]
    end
    subgraph Core Primitives
        Core[helix-core<br/>Rope, Selection, Transaction, Syntax]
    end
    subgraph Integrations
        Lsp[helix-lsp]
        Dap[helix-dap]
        Vcs[helix-vcs]
    end
    subgraph Foundations
        Event[helix-event]
        Loader[helix-loader]
        Stdx[helix-stdx]
        Parsec[helix-parsec]
    end
    Term --> Tui
    Term --> View
    Term --> Lsp
    Term --> Dap
    View --> Core
    View --> Vcs
    View --> Event
    Lsp --> Core
    Lsp --> Stdx
    Core --> Stdx
    Core --> Loader
    Core --> Parsec
    Loader --> Stdx

How a keypress becomes an edit

The terminal frontend runs an async event loop in Application::run. Every iteration selects between terminal events, LSP responses, DAP messages, async jobs, redraw requests, and signals.

sequenceDiagram
    participant Term as Terminal
    participant App as Application
    participant Comp as Compositor
    participant Editor as EditorView
    participant Cmd as MappableCommand
    participant Doc as Document
    participant Rope
    Term->>App: KeyEvent
    App->>Comp: handle_event
    Comp->>Editor: dispatch (top layer)
    Editor->>Cmd: lookup via Keymaps
    Cmd->>Doc: build Transaction
    Doc->>Rope: apply Transaction
    Rope-->>Doc: new rope state
    Doc-->>Editor: emit DocumentDidChange event
    Editor-->>Comp: render request
    Comp-->>Term: draw frame

The commands themselves live in helix-term/src/commands.rs (the largest file in the codebase at ~7k lines). They are invoked through MappableCommand, which wraps either a Rust function or a typable :command defined in commands/typed.rs.

Keybindings are resolved by Keymaps walking a KeyTrie tree built from default.rs merged with user config.

Rendering

The TUI uses a layered compositor inspired by Cursive. Each layer is a Component (see compositor.rs). The bottom layer is the editor view; popups, pickers, prompts, completion menus, and overlays sit on top.

Drawing happens onto an off-screen Surface (tui::buffer::Buffer from helix-tui/src/buffer.rs). Backends (termina on Unix, crossterm on Windows, plus a TestBackend used during integration tests) diff the new buffer against the previous frame and emit minimal terminal updates. See helix-tui for the full backend model.

Data flow for a document

A Document (helix-view/src/document.rs) bundles:

  • The text Rope (from ropey)
  • A per-View Selection (each View has its own selection over the same document)
  • Optional Syntax (tree-sitter parse tree) and tree-house highlighter state
  • Document History for undo/redo
  • Diagnostics from language servers and other providers
  • A DiffHandle from helix-vcs for git gutter signs

Modifications go through Transaction::change or change_by_selection (helix-core/src/transaction.rs). Transactions are OT-style change sets that can be inverted (for undo), composed, and mapped (so positions in old text can be translated into new text).

Async and event handling

Long-running or debounced work uses AsyncHook from helix-event. Examples include LSP completion debouncing, document highlight requests, and DAP message processing. Synchronous reactions to editor state changes (e.g. closing the completion popup when the cursor moves) use synchronous hooks declared via the events! macro and registered with register_hook!.

The tokio runtime is single-threaded for the main loop but uses worker threads for I/O (see helix-term/Cargo.toml features rt, rt-multi-thread).

Cross-cutting concerns

For more on each subsystem, follow the links in the package, feature, and primitive sections.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Architecture – Helix wiki | Factory