Koa - A Modal Code Editor #
An experimental fully extensible modal code editor for the terminal. The Rust codebase provides a minimal bootstrap layer while Janet handles all editor logic, enabling maximum extensibility and live customization.
Key Features:
- Janet-based Core: Editor logic written in Janet for ultimate flexibility
- Live Reconfiguration: Hot-swap key bindings, behaviors, and plugins
- Rust Bootstrap: Minimal, efficient native layer for TUI and system integration
- Tree-sitter Integration: Syntax highlighting, indentation and more via native bindings
- Unlimited Extensibility: Complete editor customization without recompilation
Current Status #
Bootstrap Foundation:
Editor Core:
Architecture #
Rust-Janet Hybrid Design:
┌─────────────────────────────────────────────────────────────┐
│ Janet Layer (Editor Logic) │
├─────────────────────────────────────────────────────────────┤
│ • Modal system & state management │
│ • Text operations & buffer management │
│ • Key bindings & command system │
│ • Plugin system & user configuration │
│ • File I/O coordination │
└─────────────────────────────────────────────────────────────┘
↕ High-Level Bridge
┌─────────────────────────────────────────────────────────────┐
│ Rust Layer (UI & System Core) │
├─────────────────────────────────────────────────────────────┤
│ • Complete UI rendering │
│ • TUI operations & terminal management │
│ • File I/O and system calls │
│ • Tree-sitter integration │
│ • Performance-critical operations │
└─────────────────────────────────────────────────────────────┘
Current Structure:
.
├── src/ # Rust source code
│ ├── main.rs # Bootstrap: Janet init + event loop
│ ├── app.rs # Application state and main loop
│ ├── event.rs # Event handling system
│ ├── ui.rs # UI rendering
│ └── janet/ # Rust-Janet bridge modules
│ ├── mod.rs # Module definitions
│ ├── keymap.rs # Key handling bridge
│ └── state.rs # State management bridge
└── runtime/ # Janet runtime source code
└── koa/ # Koa Janet modules
├── koa.janet # Main entrypoint
├── keymap.janet # Keybindings (minimal)
└── stubs.janet # Placeholder functions
Roadmap #
Phase 1: Strategic Hybrid Foundation #
Phase 2: Advanced Editor Operations (Janet-Driven) #
Phase 3: Language Support & Syntax Highlighting #
Phase 4: Advanced Editor Features #
Phase 5: Ultimate Extensibility & Community #
Architecture Philosophy #
Rust-Janet Hybrid Approach: This architecture balances flexibility with performance:
Rust Layer (Performance Core): Handles operations where performance matters:
- Complete UI rendering using ratatui
- TUI operations with proper terminal management
- File I/O and system calls
- Tree-sitter integration for syntax highlighting
- Memory-intensive operations
Janet Layer (Logic Core): Provides maximum extensibility:
- All editor logic and behavior
- Complete customization and extensibility
- Hot-swappable configurations and key bindings
- Plugin system and user extensions
- Domain-specific languages for configuration
High-Level Bridge: Clean interface between layers:
- Janet computes editor state and decisions
- Rust renders state efficiently using native ratatui features
- Minimal bridge calls with semantic operations
- Clear separation of concerns
This approach maximizes both flexibility and performance, avoiding the overhead of primitive bridge operations while maintaining the extensibility benefits of Janet scripting.
Building and Running #
# Build the editor (add --release for production build)
cargo build
# Run with a file
cargo run -- demo.rs
# Run without arguments for empty buffer
cargo run
cargo build and cargo run now automatically compile runtime/koa/koa.janet
into runtime.jimage via build.rs before Rust compilation starts. Ensure the
janet executable is available in PATH.
Testing #
cargo test
Key Bindings #
Note: Most key bindings are not yet implemented. Current functionality is limited to basic character input.
Normal Mode #
hjklor arrow keys - Movement (undo current selections)^orHome- Beginning of line$orEnd- End of linei- Enter insert modev- Enter select mode (preserves current selections):- Enter command modew- Move to next wordb- Move to previous wordPageUp- Move to topPageDown- Move to bottomo- Create line below and enter insert modeO- Create line above and enter insert modex- Select whole line or next line if the current one is already fully selectedd- Delete character under cursor or the current selection if one existsD- Duplicate selected lineDelete- Delete character under cursorBackspace- Delete character before cursor
Insert Mode #
- arrow keys - Movement
Escape- Return to normal modeBackspace- Delete character before cursorDelete- Delete character under cursorEnter- Insert newlineTab- Insert 4 spacesHome- Beginning of lineEnd- End of line
Select Mode #
hjklor arrow keys - Movement (extends selection)^orHome- Beginning of line$orEnd- End of linedorDelete- Delete selectioni- Delete selection and enter insert modex- Select whole line or next line if the current one is already fully selectedw- Expand selection to next wordb- Shorten selection to previous wordEscape,v- Return to normal mode
Command Mode #
Escape- Return to normal modew- Save fileq- Quit editor (does not handle unsaved changes confirmation yet!)
Contributing #
This is a learning project exploring modal editor design with Rust and Janet. Contributions and suggestions are welcome!
License #
GPLv2 License - Feel free to use this code for learning and experimentation.