rand/aesop
A modern modal text editor written in Zig with vim-like keybindings and a focus on performance.
refsrefsA modern modal text editor written in Zig with vim-like keybindings and a focus on performance.
Aesop is a terminal-based text editor that combines the modal editing paradigm of Vim with modern editor architecture. Built from scratch in Zig, it prioritizes performance through efficient data structures and aims to provide a familiar yet refined editing experience.
Status: Active development. Core editing features are functional, but this is not yet production-ready.
h/j/k/l, w/b/e, 0/$, gg/G, {/}iw/aw (word), ip/ap (paragraph), i(/a( and other pairsf/F/t/T{char} with ; and , repeatm{a-z} to set, `{mark} to jump, with cross-file support for uppercase marksq{register} to record, @{register} to play, with persistent storage/ with regex, case-sensitive/insensitive, whole-word matching, and search historyu and Ctrl-r. repeats last change:b and buffer list# Clone the repository
git clone https://github.com/rand/aesop.git
cd aesop
# Build the editor
zig build
# Run tests
zig build test
# Build optimized release
zig build -Doptimize=ReleaseSafe
The compiled binary will be in zig-out/bin/aesop.
Aesop uses tree-sitter for fast, accurate syntax highlighting. The tree-sitter core library is required:
macOS (Homebrew):
brew install tree-sitter
Linux (Debian/Ubuntu):
sudo apt-get install libtree-sitter-dev
Linux (Arch):
sudo pacman -S tree-sitter
From source:
git clone https://github.com/tree-sitter/tree-sitter.git
cd tree-sitter
make
sudo make install
For detailed setup including language-specific grammar installation, see docs/BUILDING_WITH_TREE_SITTER.md.
Aesop requires a Nerd Font for proper display of icons, file type indicators, and UI elements.
Recommended fonts:
Installation:
macOS (Homebrew):
brew tap homebrew/cask-fonts
brew install --cask font-jetbrains-mono-nerd-font
Linux:
# Download from https://www.nerdfonts.com/font-downloads
# Extract to ~/.local/share/fonts/
mkdir -p ~/.local/share/fonts
unzip JetBrainsMono.zip -d ~/.local/share/fonts/
fc-cache -fv
After installation, configure your terminal to use the Nerd Font. Without a Nerd Font installed, icons and UI elements may display incorrectly.
# Open empty buffer
./zig-out/bin/aesop
# Open a file
./zig-out/bin/aesop path/to/file.txt
# Run demo mode (shows "Hello, World!")
./zig-out/bin/aesop --demo
Aesop uses modal editing similar to Vim:
h/j/k/l - Move cursor left/down/up/right
w/b - Jump forward/backward by word
0/$ - Jump to start/end of line
gg/G - Jump to first/last line
{number}G - Jump to line number
i - Enter Insert mode (before cursor)
a - Enter Insert mode (after cursor)
v - Enter Select (visual) mode
Esc - Return to Normal mode
x - Delete character
dd - Delete line
yy - Yank (copy) line
p - Paste after cursor
u - Undo
Ctrl-r - Redo
. - Repeat last change
diw - Delete inside word
ci( - Change inside parentheses
ya" - Yank around double quotes
dap - Delete around paragraph
fx - Find next 'x' on line
Fx - Find previous 'x' on line
tx - Till next 'x' (cursor before 'x')
Tx - Till previous 'x'
; - Repeat last find/till
, - Reverse last find/till
ma - Set mark 'a' at cursor
`a - Jump to mark 'a'
qa - Start recording macro to register 'a'
q - Stop recording
@a - Play macro from register 'a'
/pattern - Search forward
?pattern - Search backward
n - Next match
N - Previous match
Aesop supports comprehensive configuration through a simple key=value config file:
$XDG_CONFIG_HOME/aesop/config.conf (if XDG_CONFIG_HOME is set)~/.config/aesop/config.conf (default)./aesop.conf (current directory)# Editor behavior
tab_width=4
expand_tabs=true
line_numbers=true
relative_line_numbers=false
# Visual settings
syntax_highlighting=true
highlight_current_line=true
# Search defaults
search_case_sensitive=false
search_wrap_around=true
# Auto-pairing
auto_pair_brackets=true
~/.config/aesop/config.confSee Configuration System documentation for complete details on all available settings.
Detailed documentation is available in the docs/ directory:
src/
├── buffer/ - Rope data structure for text storage
├── editor/ - Core editor logic
│ ├── command.zig - Command registry and implementations
│ ├── cursor.zig - Cursor and selection management
│ ├── editor.zig - Main editor state coordinator
│ ├── highlight.zig - Syntax highlighting tokenizer
│ ├── keymap.zig - Key binding system
│ ├── macros.zig - Macro recording/playback
│ ├── marks.zig - Mark/bookmark system
│ ├── motions.zig - Cursor motion implementations
│ ├── prompt.zig - Interactive prompt system
│ ├── registers.zig - Register management
│ ├── search.zig - Search functionality
│ ├── treesitter.zig - Tree-sitter parser wrapper
│ ├── undo.zig - Undo/redo with tree history
│ └── window.zig - Window management and splits
├── lsp/ - Language Server Protocol integration
│ ├── client.zig - LSP client implementation
│ ├── handlers.zig - LSP message handlers
│ ├── process.zig - LSP server process management
│ └── response_parser.zig - JSON-RPC response parsing
├── render/ - Terminal rendering pipeline
│ ├── buffer.zig - Buffer rendering with colors
│ ├── gutter.zig - Line numbers and diagnostics
│ └── markdown.zig - Markdown to plain text conversion
├── terminal/ - Terminal I/O and platform abstractions
├── treesitter/ - Tree-sitter C bindings
│ └── bindings.zig - Complete tree-sitter API bindings
└── main.zig - Entry point
tests/
├── e2e/ - End-to-end persona-based tests
├── integration/ - Integration tests
├── unit/ - Unit tests for core components
├── fixtures/ - Test fixture files
└── helpers.zig - Test utilities and mocks
queries/
├── zig/ - Zig syntax highlighting queries
├── rust/ - Rust syntax highlighting queries
├── go/ - Go syntax highlighting queries
├── python/ - Python syntax highlighting queries
└── c/ - C syntax highlighting queries
# Run all tests
zig build test
# Run with verbose output
zig build test --summary all
# Format all source files
zig fmt src/
# Check formatting (CI requirement)
zig fmt --check src/
Dependencies are managed through build.zig.zon and fetched automatically during build. Tree-sitter must be installed separately (see installation instructions above).
Text is stored in a balanced tree of 512-1024 byte chunks, enabling:
Interactive commands use a continuation-passing architecture:
This design avoids blocking and enables universal escape-key cancellation.
Input → Parse Key → Priority Dispatch:
1. Incremental search
2. Pending command
3. Normal command
↓
Render → Output
The priority system ensures search and interactive commands capture input before normal command processing.
Implemented:
In Progress:
Planned:
Aesop has a comprehensive test suite with 99 tests covering:
The e2e test suite simulates real user workflows:
# Run all tests
zig build test
# All tests should pass with comprehensive coverage
# Current coverage: ~55% overall, ~90% critical path
Contributions are welcome! When submitting changes:
zig fmt before committingzig build test passesBefore starting work on major features, consider opening an issue to discuss the approach.
MIT License - see LICENSE for details.
Copyright (c) 2025 Rand Arete