Files
microhx/SPECIFICATION.md
T

25 KiB
Raw Blame History

MicroHX - Modern Modal Text Editor Specification

1. Overview

MicroHX is a modern, high-performance modal text editor written in Rust, featuring:

  • Modal editing with Kakoune/Helix-style object-verb keybindings
  • Lua scripting for configuration and plugins
  • Three UI modes: GUI (egui), Terminal (TUI), and CLI (headless)
  • Built-in LSP + Tree-sitter for language intelligence and syntax highlighting
  • User-definable modes for custom editing workflows
  • Static compilation for maximum portability (old Linux/glibc compatibility)
  • Extensible architecture with a focus on performance and simplicity

2. Core Architecture

2.1 Technology Stack

Component Technology
Language Rust (edition 2024+)
UI Framework egui + eframe
Terminal Backend egui_term / ratatui
CLI Mode crossterm + direct rendering
Scripting Lua 5.4 (via mlua)
Text Buffer Rope data structure (via ropey)
Async Runtime tokio
Syntax Highlighting tree-sitter (built-in)
LSP Client lsp-types + tower-lsp (built-in)
Static Linking musl-libc, zig build

2.2 Architecture Layers

┌─────────────────────────────────────────────────────────┐
│                    UI Layer (Pluggable)                  │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐  │
│  │  GUI Mode   │  │ Terminal    │  │      CLI        │  │
│  │  (eframe)   │  │ (ratatui)   │  │   (headless)    │  │
│  └─────────────┘  └─────────────┘  └─────────────────┘  │
├─────────────────────────────────────────────────────────┤
│                  Editor Core Layer                       │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐  │
│  │   Buffer    │  │   View/     │  │    Command      │  │
│  │   Manager   │  │   Window    │  │    System       │  │
│  └─────────────┘  └─────────────┘  └─────────────────┘  │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐  │
│  │    Mode     │  │   Keymap    │  │    Clipboard    │  │
│  │   System    │  │   Engine    │  │    Manager      │  │
│  └─────────────┘  └─────────────┘  └─────────────────┘  │
├─────────────────────────────────────────────────────────┤
│                  Plugin Layer (Lua)                      │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐  │
│  │   Plugin    │  │   Config    │  │      API        │  │
│  │   Loader    │  │   Parser    │  │    Bindings     │  │
│  └─────────────┘  └─────────────┘  └─────────────────┘  │
├─────────────────────────────────────────────────────────┤
│                  Services Layer (Built-in)               │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐  │
│  │     LSP     │  │   Tree-     │  │    File         │  │
│  │   Client    │  │   sitter    │  │    Watcher      │  │
│  └─────────────┘  └─────────────┘  └─────────────────┘  │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────┐  │
│  │   Search/   │  │    Undo/    │  │     Theme       │  │
│  │   Replace   │  │    Redo     │  │     Engine      │  │
│  └─────────────┘  └─────────────┘  └─────────────────┘  │
└─────────────────────────────────────────────────────────┘

3. Modal System

3.1 Editor Modes

Mode Name Description Default Key
Normal Normal Navigation and commands <Esc>
Insert Insert Text insertion i
Visual Visual Text selection (selections shown) v
VisualLine Visual Line Line-wise selection V
VisualBlock Visual Block Block-wise selection <C-v>
Command Command Command palette/input :
Search Search Search forward /
SearchBack Search Backward Search backward ?
Replace Replace Single char replace r
OperatorPending Operator Pending Awaiting motion d, c, y, etc.
User1-5 User Defined Custom user modes configurable

3.2 User-Definable Modes

Users can define custom modes via Lua with:

  • Custom keybindings
  • Custom status bar indicators
  • Mode-specific behaviors
  • Inheritance from base modes
-- Example: Define a custom "presentation" mode
modes = {
  presentation = {
    base = "normal",  -- inherits from normal mode
    indicator = "PRESENT",
    keys = {
      ["n"] = "next_slide",
      ["p"] = "prev_slide",
      ["q"] = "exit_presentation",
    },
    settings = {
      line_numbers = false,
      cursor_line = false,
      read_only = true,
    },
  },
}

3.3 Mode State Machine

pub enum EditorMode {
    Normal,
    Insert,
    Visual(VisualMode),
    Command,
    Search(SearchDirection),
    Replace,
    OperatorPending(Operator),
    UserDefined(String),  // Custom user modes
}

pub enum VisualMode {
    Char,
    Line,
    Block,
}

pub enum SearchDirection {
    Forward,
    Backward,
}

pub enum Operator {
    Delete,
    Change,
    Yank,
    Put,
    Format,
    Indent,
    Outdent,
}

4. Keybinding System

4.1 Key Representation

pub struct KeyEvent {
    pub code: KeyCode,
    pub modifiers: Modifiers,
}

pub struct Modifiers {
    pub ctrl: bool,
    pub alt: bool,
    pub shift: bool,
    pub super_: bool,
}

4.2 Keybinding Layers

  1. Global - Always active (e.g., <C-q> quit)
  2. Mode-specific - Active only in specific modes
  3. Buffer-local - Per-filetype overrides
  4. Plugin - Plugin-defined bindings

4.3 Keybinding Philosophy: Object-Verb (Kakoune/Helix Style)

MicroHX uses object-verb keybinding style by default (like Kakoune/Helix), NOT verb-object (like Vim):

Style Example Meaning
Object-Verb dw Select word, then delete
Verb-Object dw Delete word

Benefits of Object-Verb:

  • Selection is always visible before action
  • More intuitive for multi-cursor editing
  • Consistent with "select then act" mental model
  • Better for preview/undo before commit

4.4 Default Keymaps (Normal Mode) - Helix Style

Motions (Object Selectors)

Key Action
h/j/k/l Left/Down/Up/Right
w/b Word forward/backward
e End of word
0/$ Line start/end
gg/G Document start/end
v Select mode (extend selection)
t/T Till char forward/backward
f/F Find char forward/backward
% Jump to matching bracket
m Open marks menu

Actions (Verbs)

Key Action
d Delete selection
y Yank (copy) selection
c Change (delete + insert)
p/P Paste after/before
r Replace with char
~ Toggle case
> / < Indent / Outdent
= Format selection
f Format via LSP
g Goto (definition, references, etc.)
s Select (sub-selections)
i Select inside object
a Select around object

Object Examples

Sequence Action
w Select word
ww Select next word
dw Delete word
cw Change word
yw Yank word
diw Delete inside word
daw Delete around word
cit Change inside tag
ci" Change inside quotes
ca" Change around quotes
dib Delete inside block ()
dab Delete around block ()

Goto Commands (g prefix)

Key Action
gd Goto definition
gr Goto references
gi Goto implementation
gt Goto type definition
gh Show hover docs
gk Show signature help
gf Open file under cursor
gg Goto line start
gG Goto line end

Selection Commands (s prefix)

Key Action
s Select current
S Split selection
sa Select all occurrences
sr Remove primary selection
sn Select next occurrence
sp Select previous occurrence

Other

Key Action
: Command palette
/ Search forward
? Search backward
* Select next match of selection
u / <C-r> Undo / Redo
i Insert mode
a Append mode
o / O Open line below/above
I / A Insert at line start/end
. Repeat last change
ZQ Quit without saving
ZZ Save and quit

5. Lua Plugin System

5.1 Configuration Structure

-- ~/.config/microhx/init.lua
return {
  -- Editor settings
  settings = {
    theme = "dracula",
    line_numbers = true,
    relative_numbers = true,
    cursor_line = true,
    tab_width = 4,
    auto_save = false,
  },
  
  -- Keybindings
  keys = {
    normal = {
      ["<leader>w"] = ":write",
      ["<leader>q"] = ":quit",
      ["<C-s>"] = ":write",
      ["<leader>f"] = ":telescope find_files",
    },
    insert = {
      ["jk"] = "<Esc>",
    },
  },
  
  -- Plugins to load
  plugins = {
    "telescope",
    "lsp",
    "treesitter",
  },
  
  -- Plugin configurations
  telescope = {
    theme = "dropdown",
  },
  
  lsp = {
    servers = { "rust_analyzer", "lua_ls" },
  },
}

5.2 Plugin API

-- Plugin structure
return {
  name = "my-plugin",
  version = "0.1.0",
  
  -- Called on plugin load
  setup = function(config)
    -- Initialize plugin
  end,
  
  -- Called on editor startup
  init = function()
    -- Register commands, keybindings, etc.
  end,
  
  -- Event handlers
  events = {
    on_file_open = function(buffer) end,
    on_file_save = function(buffer) end,
    on_cursor_move = function(buffer, pos) end,
    on_mode_change = function(old_mode, new_mode) end,
    on_key = function(key) end,
  },
  
  -- Commands
  commands = {
    my_command = function(args) end,
  },
}

5.3 Core API Exposed to Lua

-- Buffer API
buffer = microhx.buffer
buffer.get_text() -> string
buffer.set_text(text: string)
buffer.get_cursor() -> row, col
buffer.set_cursor(row, col)
buffer.get_selection() -> start, end
buffer.insert(text: string)
buffer.delete(start, end)
buffer.line_count() -> number
buffer.get_line(n) -> string

-- Editor API
editor = microhx.editor
editor.mode() -> string
editor.command(cmd: string)
editor.notify(msg: string, level: "info"|"warn"|"error")
editor.open_file(path: string)
editor.save()
editor.quit()

-- UI API
ui = microhx.ui
ui.statusbar.set_text(text: string)
ui.statusbar.add_segment(text: string, highlight: string)
ui.input(prompt: string, callback: function)
ui.confirm(msg: string, callback: function)

-- Config API
config = microhx.config
config.get(path: string) -> any
config.set(path: string, value: any)

-- Event API
events = microhx.events
events.on(event: string, callback: function)
events.off(event: string, callback: function)
events.emit(event: string, ...)

6. UI Components (egui)

6.1 Layout Structure

┌──────────────────────────────────────────────────────────┐
│  Menu Bar (optional)  File Edit View Buffer Help        │
├──────────────────────────────────────────────────────────┤
│  Tab Bar  [file1.rs] [file2.rs] [+]                     │
├────────────┬─────────────────────────────────────────────┤
│            │                                             │
│  Line      │                                             │
│  Numbers   │           Text Buffer                       │
│            │                                             │
│            │                                             │
│            │                                             │
├────────────┴─────────────────────────────────────────────┤
│  Status Bar  NORMAL  |  rust  |  123:45  |  UTF-8  | 🚀  │
└──────────────────────────────────────────────────────────┘

6.2 UI Components

Component Description
EditorView Main text rendering area
LineNumbers Line number gutter
ScrollBar Scroll indicators
StatusBar Mode, position, file info
TabBar Open buffer tabs
CommandPalette Fuzzy-find commands
FilePicker File browser/telescope
DiagnosticPanel LSP errors/warnings
CompletionPopup Autocomplete suggestions
HoverPopup Documentation hover

6.3 UI Modes

MicroHX supports three distinct UI modes with the same core editor logic:

GUI Mode (Default)

  • Full egui/eframe native window
  • Mouse support
  • Native menus and dialogs
  • System clipboard integration
  • Multiple windows/tabs

Terminal Mode (TUI)

  • Full terminal UI with ratatui
  • 256 color / true color support
  • Mouse support (when terminal allows)
  • Feature flag: --features tui
  • Command: microhx-tui

CLI Mode (Headless)

  • No UI rendering - pure terminal I/O
  • Minimal dependencies
  • Ideal for remote/SSH usage
  • Static binary friendly
  • Feature flag: --features cli
  • Command: microhx-cli
  • Uses crossterm for direct terminal control
// Build matrix example
#[cfg(feature = "gui")]
fn main() { microhx::run_gui(); }

#[cfg(feature = "tui")]
fn main() { microhx::run_tui(); }

#[cfg(feature = "cli")]
fn main() { microhx::run_cli(); }

6.4 Static Compilation

For maximum portability (old Linux systems, embedded, containers):

# Cross-compile static binary with musl
cargo build --release --target x86_64-unknown-linux-musl --features cli

# Or use zig for even better compatibility
cargo zigbuild --release --target x86_64-unknown-linux-gnu.2.17 --features cli

# Result: single static binary, no glibc dependency
$ file target/x86_64-unknown-linux-musl/release/microhx
statically linked

Static Build Requirements:

  • LuaJIT statically linked (or use mlua with lua-src)
  • Tree-sitter grammars compiled into binary
  • No dynamic LSP dependencies (use rust-based lsp-client)
  • Fonts embedded or use terminal fonts only (CLI/TUI)

7. Text Buffer & Editing

7.1 Rope-based Buffer

use ropey::Rope;

pub struct Buffer {
    rope: Rope,
    undo_tree: UndoTree,
    marks: HashMap<char, Position>,
    path: Option<PathBuf>,
    language: Option<Language>,
    modified: bool,
}

7.2 Undo/Redo System

  • Tree-based undo history
  • Branch-aware (undo + new change = new branch)
  • Persistent undo sessions (optional)

7.3 Selection System

pub struct Selection {
    ranges: Vec<SelectionRange>,
    primary: usize,
}

pub struct SelectionRange {
    anchor: Position,
    head: Position,
    reversed: bool,
}
  • Multiple selections support
  • Cursor-style editing (Kakoune-inspired)

8. Syntax Highlighting (Built-in Tree-sitter)

MicroHX includes tree-sitter as a core component - no external dependencies required.

8.1 Tree-sitter Integration

pub struct Highlighter {
    parser: Parser,
    tree: Option<Tree>,
    highlights: Vec<HighlightRange>,
    theme: SyntaxTheme,
    // Grammars compiled into binary
    grammars: HashMap<Language, Grammar>,
}

Features:

  • Incremental parsing (only re-parse changed regions)
  • Threaded parsing for large files
  • Grammar hot-reloading
  • Query-based highlighting (like Neovim)
  • Local injections (markdown code blocks, etc.)

8.2 Language Support

Language Tree-sitter LSP
Rust
Lua
Python
JavaScript/TS
C/C++
Go
Zig
TOML
JSON
YAML
Markdown -
HTML -
CSS -

9. LSP Integration (Built-in)

MicroHX includes a native LSP client built on lsp-types and tower-lsp - no external server required for basic functionality. Language servers still need to be installed separately, but the client is built-in.

9.1 LSP Client Architecture

pub struct LspClient {
    server: LanguageServer,
    capabilities: ServerCapabilities,
    diagnostics: Vec<Diagnostic>,
    completion_items: Vec<CompletionItem>,
    // Built-in client, no external dependencies
    transport: JsonRpcTransport,
}

Features:

  • Async message handling (tokio)
  • Auto-restart on crash
  • Multiple server support (workspace folders)
  • Progress reporting
  • Dynamic capability registration

9.2 Supported Features

  • Diagnostics (errors, warnings)
  • Hover documentation
  • Go to definition
  • Find references
  • Symbol search
  • Code completion
  • Signature help
  • Formatting (range & document)
  • Code actions
  • Rename symbol
  • Document symbols
  • Inlay hints
  • Semantic tokens

10. Command System

10.1 Built-in Commands

Command Description
:write / :w Save file
:quit / :q Quit
:wq Save and quit
:q! Force quit
:open <path> Open file
:close Close buffer
:buffer <n> Switch buffer
:next / :prev Next/prev buffer
:split / :vsplit Horizontal/vertical split
:find <pattern> Find in buffer
:replace <from> <to> Replace in buffer
:set <option> Set option
:command Show commands
:help Open help
:terminal Open terminal
:lsp_restart Restart LSP
:lsp_status LSP status

10.2 Command Parser

pub struct Command {
    name: String,
    args: Vec<String>,
    bang: bool,  // ! modifier
    range: Option<LineRange>,  // e.g., :10,20delete
}

11. File Management

11.1 Features

  • Auto-save (configurable)
  • Backup files (optional)
  • File watching (notify crate)
  • Recent files list
  • Project root detection
  • Git integration (optional)

11.2 Buffer Management

pub struct BufferManager {
    buffers: HashMap<BufferId, Buffer>,
    active: BufferId,
    order: Vec<BufferId>,
    recent: Vec<BufferId>,
}

12. Configuration System

12.1 Config Locations

Platform Path
Linux ~/.config/microhx/
macOS ~/Library/Application Support/microhx/
Windows %APPDATA%/microhx/

12.2 Config Files

~/.config/microhx/
├── init.lua          # Main config
├── plugins/          # Plugin directory
├── themes/           # Custom themes
├── keys/             # Keymap presets
└── logs/             # Log files

12.3 Settings Schema

pub struct Settings {
    // Editor
    pub theme: String,
    pub line_numbers: bool,
    pub relative_numbers: bool,
    pub cursor_line: bool,
    pub color_column: Option<u32>,
    
    // Indentation
    pub tab_width: u32,
    pub insert_spaces: bool,
    pub auto_indent: bool,
    
    // Display
    pub font_size: f32,
    pub line_height: f32,
    pub wrap_lines: bool,
    pub smooth_scrolling: bool,
    
    // Behavior
    pub auto_save: bool,
    pub auto_save_delay: u64,
    pub restore_cursor: bool,
    pub confirm_quit: bool,
    
    // Search
    pub inc_search: bool,
    pub hl_search: bool,
    
    // LSP
    pub lsp_enable: bool,
    pub lsp_completion: bool,
    pub lsp_diagnostics: bool,
}

13. Performance Goals

Metric Target
Startup time < 100ms (TUI), < 200ms (GUI)
Memory usage < 50MB (small files), < 200MB (large)
Input latency < 16ms (60 FPS)
File open (10k lines) < 50ms
Syntax highlight Incremental, < 5ms update
Search (100k lines) < 100ms

14. Project Structure

microhx/
├── Cargo.toml
├── Cargo.lock
├── README.md
├── SPECIFICATION.md
├── LICENSE
├── .github/
│   └── workflows/
├── src/
│   ├── main.rs
│   ├── lib.rs
│   ├── app.rs              # Main application state
│   ├── editor/
│   │   ├── mod.rs
│   │   ├── buffer.rs
│   │   ├── cursor.rs
│   │   ├── mode.rs
│   │   ├── keymap.rs
│   │   ├── selection.rs
│   │   └── undo.rs
│   ├── ui/
│   │   ├── mod.rs
│   │   ├── editor_view.rs
│   │   ├── statusbar.rs
│   │   ├── tabs.rs
│   │   ├── command_palette.rs
│   │   └── components/
│   ├── lua/
│   │   ├── mod.rs
│   │   ├── plugin.rs
│   │   ├── api.rs
│   │   └── config.rs
│   ├── lsp/
│   │   ├── mod.rs
│   │   ├── client.rs
│   │   └── messages.rs
│   ├── syntax/
│   │   ├── mod.rs
│   │   ├── highlight.rs
│   │   └── language.rs
│   ├── commands/
│   │   ├── mod.rs
│   │   ├── parser.rs
│   │   └── builtin.rs
│   └── config/
│       ├── mod.rs
│       └── settings.rs
├── plugins/
│   ├── telescope/
│   ├── lsp/
│   └── treesitter/
├── themes/
│   ├── dracula.toml
│   ├── nord.toml
│   └── gruvbox.toml
├── tests/
│   ├── unit/
│   ├── integration/
│   └── lua/
└── assets/
    └── icons/

15. Development Roadmap

Phase 1: Core Foundation (MVP)

  • Basic buffer management (ropey)
  • Modal system (Normal, Insert, Visual)
  • Object-verb keybindings (Helix-style)
  • Lua config loading (mlua)
  • CLI mode with crossterm
  • File open/save
  • Static build setup (musl)

Phase 2: Essential Features

  • Complete keybinding system
  • Undo/redo (tree-based)
  • Search/replace
  • Command system
  • Status bar
  • Line numbers
  • User-definable modes

Phase 3: Built-in LSP + Tree-sitter

  • Tree-sitter integration
  • Syntax highlighting engine
  • LSP client (tower-lsp)
  • Diagnostics display
  • Completions popup
  • Goto definition/hover

Phase 4: Advanced Editing

  • Multiple selections
  • Macros
  • Marks
  • Registers
  • Split windows
  • TUI mode (ratatui)

Phase 5: Polish & Plugins

  • Plugin system
  • Theme system
  • GUI mode (egui)
  • Performance optimization
  • Documentation
  • CI/CD with static builds

16. Design Principles

  1. Performance First - Every operation should be fast and memory-efficient
  2. Modal by Default - Object-verb workflow (Kakoune/Helix style)
  3. Lua Everything - Configuration and plugins use Lua exclusively
  4. Built-in Intelligence - LSP + Tree-sitter included, no external deps
  5. Three Modes - CLI, TUI, and GUI with shared core
  6. Static Friendly - Compile once, run anywhere (musl, old glibc)
  7. User Modes - Extensible modal system for custom workflows
  8. Sensible Defaults - Works out of the box, customizable when needed
  9. No Bloat - Features are opt-in, core stays lean

17. Naming

MicroHX = Micro (small, fast) + HX (Hex/Editor suffix, modern feel)

Pronunciation: /ˈmaɪ.kroʊ.heɪks/ (MY-kro-hayks)


18. License

MIT License - See LICENSE file


19. Contributing

See CONTRIBUTING.md for guidelines on:

  • Code style
  • Testing requirements
  • Pull request process
  • Reporting issues

Last updated: 2026-03-17