25 KiB
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
- Global - Always active (e.g.,
<C-q>quit) - Mode-specific - Active only in specific modes
- Buffer-local - Per-filetype overrides
- 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
- Performance First - Every operation should be fast and memory-efficient
- Modal by Default - Object-verb workflow (Kakoune/Helix style)
- Lua Everything - Configuration and plugins use Lua exclusively
- Built-in Intelligence - LSP + Tree-sitter included, no external deps
- Three Modes - CLI, TUI, and GUI with shared core
- Static Friendly - Compile once, run anywhere (musl, old glibc)
- User Modes - Extensible modal system for custom workflows
- Sensible Defaults - Works out of the box, customizable when needed
- 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