Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Editor Architecture

hone-editor is the embeddable code editor component (@honeide/editor). It is used by hone-ide but can also be embedded independently. The editor has three layers: core (platform-independent logic), view-model (reactive state bridge), and native (Rust FFI rendering per platform).

core/ – Platform-Independent

All editor logic lives here. No platform dependencies, no FFI, no rendering.

Buffer (buffer/)

Text storage uses a piece table backed by a rope with a line index:

  • Piece table tracks original and add buffers with a sequence of pieces
  • Rope provides O(log n) random access and efficient insertions/deletions
  • Line index maintains a mapping from line numbers to buffer offsets
  • Supports large files without loading entire content into a flat string

Cursor (cursor/)

Multi-cursor management:

  • Multiple independent cursors with selection ranges
  • Word boundary detection for double-click selection and ctrl+arrow navigation
  • Cursor affinity (left/right) for ambiguous positions at line wraps
  • Selection operations: expand to word, line, bracket, all

History (history/)

Undo/redo with time-based coalescing:

  • Changes within a 500ms window are grouped into a single undo step
  • Maximum undo stack depth: 10,000 entries
  • Branching undo (redo stack preserved until a new edit diverges)

Viewport (viewport/)

Virtual scrolling for performance with large files:

  • Only renders visible lines plus a 10-line buffer zone above and below
  • Hidden line tracking for code folding integration
  • Smooth scrolling with pixel-level offset tracking
  • Viewport resize handling

Tokenizer (tokenizer/)

Incremental syntax highlighting via two engines:

  • Lezer parser integration – 8 language grammars: TypeScript, HTML, CSS, JSON, Markdown, Python, Rust, C++
  • Keyword-based fallback engine – for languages without a Lezer grammar
  • Incremental re-tokenization on edits (only re-parses changed regions)
  • Token types map to theme color scopes

Find and replace across the document:

  • Literal and regex search modes
  • Chunked search for large files (avoids blocking the main thread)
  • Incremental live search (results update as the user types)
  • Match highlighting with current-match distinction

Folding (folding/)

Two folding strategies:

  • Indent-based – folds regions where indentation increases
  • Syntax-based – uses Lezer parse tree to identify foldable nodes (functions, classes, blocks)
  • Nested folding with level tracking

Diff (diff/)

Myers diff algorithm implementation:

  • O(ND) complexity for computing minimal edit scripts
  • Hunk-based operations (apply hunk, revert hunk)
  • Inline character-level diff within changed lines
  • Used by the git diff view and AI review

Document (document/)

Wraps TextBuffer with document metadata:

  • URI, languageId, version counter
  • isDirty tracking
  • Encoding detection (UTF-8, UTF-16, etc.)
  • Line-ending detection and normalization (LF, CRLF)

Commands (commands/)

Command registry with 5 command modules:

  • Editing – insert, delete, indent, comment toggle, auto-close brackets
  • Navigation – go to line, go to definition, go to bracket
  • Selection – select all, expand selection, shrink selection
  • Clipboard – cut, copy, paste with multi-cursor support
  • Multi-cursor – add cursor above/below, add cursor at next occurrence

LSP Client (lsp/)

Language Server Protocol client implementation:

  • JSON-RPC 2.0 transport layer
  • Typed request/response methods:
    • textDocument/completion – autocomplete
    • textDocument/hover – hover information
    • textDocument/publishDiagnostics – errors and warnings
    • textDocument/codeAction – quick fixes and refactorings
    • textDocument/definition – go to definition
    • textDocument/references – find all references
    • textDocument/formatting – document formatting

DAP Client (dap/)

Debug Adapter Protocol client:

  • Session management: launch and attach configurations
  • Breakpoint management (line, conditional, logpoint)
  • Execution control: continue, step over, step into, step out, pause
  • Stack frame inspection
  • Variable inspection with scopes (local, closure, global)

Snippets (snippets/)

  • Template processing with tab stops and placeholders
  • Language-specific snippet registries
  • Variable expansion ($TM_FILENAME, $CLIPBOARD, etc.)

view-model/ – Reactive State Bridge

EditorViewModel orchestrates all core subsystems and exposes reactive state for rendering:

  • Cursor state – positions, selections, blink timer
  • Decorations – inline decorations, line decorations, overlay widgets
  • Diff view model – side-by-side and inline diff rendering state
  • Find widget – search state, match counts, replace mode
  • Ghost text – AI inline completion overlay
  • Gutter – line numbers, fold indicators, breakpoint markers, diagnostics
  • Line layout – computed line heights, wrapped line mapping
  • Minimap – scaled-down document overview with viewport indicator
  • Overlays – autocomplete popover, hover card, parameter hints
  • Theme – resolved token colors and editor colors

native/ – Rust FFI Per Platform

The editor uses a TS-authoritative model: TypeScript is the single source of truth for all document state. The Rust layer is a rendering cache that receives pre-computed line content and viewport state via FFI.

NativeEditorFFI Interface

93+ FFI functions organized by concern:

  • Document operations (set content, apply edit, get line)
  • Viewport management (scroll, resize, set visible range)
  • Cursor rendering (set positions, blink state)
  • Selection rendering (set selection ranges)
  • Decoration management (add/remove/update decorations)
  • Theme application (set colors, font metrics)
  • Input handling (key events, mouse events, IME)

Platform Crates

PlatformRenderingText Layout
macOSMetalCoreText
iOSUIKit / MetalCoreText
WindowsDirect2DDirectWrite
LinuxCairoPango
AndroidSkiaHarfBuzz
WebWASM + CanvasBrowser layout

Each platform crate implements the same NativeEditorFFI interface, so the TypeScript layer is entirely platform-agnostic.