| .vscode | ||
| docs | ||
| runtime/koa | ||
| src | ||
| .envrc | ||
| .gitattributes | ||
| .gitignore | ||
| build-runtime.sh | ||
| Cargo.lock | ||
| Cargo.toml | ||
| flake.lock | ||
| flake.nix | ||
| LICENSE | ||
| README.md | ||
| runtime.jimage | ||
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:
- Janet Integration: janetrs library integrated for embedding Janet
- Basic TUI Interface: ratatui integration for terminal UI
- Janet-Rust Bridge System: File system, TUI, and syntax bridges (minimal implementation)
- Janet Event Loop Foundation: Event loop infrastructure in Janet (basic key forwarding only)
- File Operations: Bridge functions for file I/O (not implemented)
- Event Loop Handoff: Control handed from Rust to Janet main loop (partial)
Editor Core:
- Janet Editor State: Core state management in Janet
- Modal System Framework: Basic modal system structure in Janet
- Janet Event Handling: Input processing framework in Janet
- Complete Event Loop: Actual event processing
- Text Editing in Janet: Text operations in Janet
- High-Level UI Bridge: Rust renders editor state from Janet
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
-
Janet Integration & Bootstrap
- Integrate janetrs library for Janet embedding
- Set up Janet environment initialization in Rust
- Create minimal Rust bootstrap that hands control to Janet
- Design Janet API for editor state management
-
High-Level UI Bridge (Current Priority)
- Create semantic rendering bridge functions
- Maintain ratatui performance and features
- Bridge accepts editor state from Janet, renders in Rust
- Replace primitive ratatui calls with high-level operations
-
Editor State Migration to Janet
- Port current editor state management to Janet
- Implement modal system (Normal/Insert/Select/Command) in Janet
- Create Janet text operations (insert, delete, cursor movement)
- Implement Janet-based key binding system
Phase 2: Advanced Editor Operations (Janet-Driven)
-
Dynamic Configuration System
- Implement live configuration system foundation
- Create event-driven architecture for editor events
- Design plugin architecture foundation
-
Movement Commands
- Word navigation (w, b, e) with customizable word boundaries
- Paragraph navigation ({, })
- Go to line (G, gg) with jump lists
- Page scrolling (Ctrl-D, Ctrl-U) with smooth scrolling options
- Search and jump (/, ?, n, N) with regex support
-
Text Operations
- Delete operations (dd, D, dw, etc.) with custom operators
- Yank/Copy operations (yy, Y, yw, etc.) with multiple registers
- Paste operations (p, P) with register selection
- Undo/Redo (u, Ctrl-R) with branching undo tree
- Replace mode (R) with preview
-
Extensible Command System
- Command mode with Janet expression evaluation
- Custom command definitions in Janet
- Command history and completion
- Macro recording and playback
Phase 3: Language Support & Syntax Highlighting
-
Tree-sitter Integration (via Rust bridge)
- Integrate tree-sitter library
- Create Janet API for syntax highlighting
- Parse and highlight common languages:
- Rust, Zig, C/C++
- JavaScript/TypeScript
- Python, Go, Java
- Janet, Lua, Lisp dialects
- Markdown, JSON, YAML
-
Semantic Features (Janet-configurable)
- Bracket matching with custom rules
- Indentation awareness per language
- Comment toggling with language-specific styles
- Code folding with custom fold markers
Phase 4: Advanced Editor Features
-
Multiple Buffers & Windows
- Buffer management system in Janet
- Split windows with customizable layouts
- Tab interface with user-defined styling
- Buffer-local configurations and hooks
-
Language Server Protocol (LSP)
- LSP client implementation in Janet
- Code completion with customizable sources
- Go to definition and references
- Error diagnostics with user-defined handlers
- Custom LSP server configurations
Phase 5: Ultimate Extensibility & Community
-
Advanced Plugin System
- Plugin manager with dependency resolution
- API versioning and compatibility layer
- Sandboxed plugin execution
- Community plugin registry integration
-
Performance & Optimization
- Janet code JIT compilation exploration
- Lazy loading for large files
- Async operations for non-blocking UI
- Memory optimization for large codebases
-
Community & Ecosystem
- Plugin development documentation
- Example configurations and themes
- Migration tools from other editors
- Community contribution guidelines
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
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.