Feature: Helix mode
Add Helix keybinding mode
Summary
This PR adds a new Helix-style modal editing mode to Reedline, providing an alternative to the existing Vi and Emacs modes. Helix mode implements selection-extends-on-motion (Helix's signature feature) along with character/word/line motions, find/till motions, select mode toggle, and editing commands.
This is a purely additive change with zero impact on existing functionality. The implementation follows the same architectural patterns as Vi and Emacs modes, integrating cleanly into the existing EditMode trait system.
Features
Normal Mode (default starting mode)
Mode switching:
v- Toggle select modei/a/I/A- Enter insert at cursor/after/line start/line end
Character motions (extend selection):
h/l- Move left/right with selection
Word motions (extend selection):
w- Next word startb- Previous word starte- Word endW- Next WORD start (whitespace-delimited)B- Previous WORD startE- WORD end
Line motions (extend selection):
0- Line start$- Line end
Find/till motions (extend selection):
f{char}- Find next occurrence of charactert{char}- Till next occurrence (stop before)F{char}- Find previous occurrenceT{char}- Till previous occurrence (stop after)
Selection commands:
x- Select entire line;- Collapse selection to cursorAlt+;- Swap cursor and anchor (flip selection)
Edit commands:
d- Delete selectionc- Change selection (delete and enter insert)y- Yank/copy selectionp- Paste after cursorP- Paste before cursor
Other:
Enter- Accept/submit lineCtrl+C/Ctrl+D- Exit/abort
Select Mode
vorEsc- Exit select mode (clear selection)- All motion keys work the same as Normal mode
i/a/I/A- Exit select and enter insert moded/c/y/p- Edit commands work the same
Insert Mode
- All printable characters - Insert text
Esc- Return to normal mode (cursor moves left, vi-style)Backspace- Delete previous characterEnter- Accept/submit lineCtrl+C/Ctrl+D- Exit/abort
Motivation
- Provide Helix-style modal editing for users who prefer that workflow
- Demonstrate Helix's "selection-first" paradigm is viable in a line editor context
- Expand Reedline's modal editing options without disrupting existing modes
- Provide a foundation for future Helix features (multi-cursor, text objects, etc.)
Impact on Codebase
Architectural Integration
The implementation follows Reedline's established patterns:
- EditMode trait - Helix implements the same
EditModetrait as Vi and Emacs, ensuring consistent integration with the line editor engine - Module structure - Mirrors
src/edit_mode/vi/organization with separate keybindings and mode logic - Keybindings system - Uses existing
Keybindingsinfrastructure for customization - Prompt system - Extends
PromptViModeenum withSelectvariant for proper mode display
Code Organization
src/edit_mode/
├── helix/ # New module (self-contained)
│ ├── mod.rs # Main implementation (~786 lines)
│ └── helix_keybindings.rs # Default bindings (~190 lines)
├── vi/ # Unchanged
├── emacs/ # Unchanged
└── mod.rs # Updated to export helix module
src/prompt/
├── base.rs # Added PromptViMode::Select variant
└── default.rs # Added default select mode prompt indicator
src/lib.rs # Updated to export helix types
examples/helix_mode.rs # New example (~127 lines)
HELIX_MODE.md # Comprehensive documentation (~181 lines)
No changes to:
- Core editor (
src/core_editor/) - Engine (
src/engine.rs) - Painting/rendering (
src/painting/) - History, completion, validation, or menu systems
- Existing Vi or Emacs modes
API Surface
New public exports (non-breaking additions):
reedline::Helix- The edit mode structreedline::default_helix_normal_keybindings()- Default normal mode bindingsreedline::default_helix_insert_keybindings()- Default insert mode bindingsreedline::PromptViMode::Select- New variant for select mode display
Usage pattern matches existing modes:
// Same pattern as Vi/Emacs
let helix_mode = Box::new(Helix::default());
let editor = Reedline::create().with_edit_mode(helix_mode);
Compatibility Notes
For Application Developers
If you're currently using Reedline:
- No action required - your code continues to work exactly as before
- To adopt Helix mode - simply swap your EditMode:
// Before let editor = Reedline::create().with_edit_mode(Box::new(Vi::default())); // After let editor = Reedline::create().with_edit_mode(Box::new(Helix::default())); - If you implement custom Prompt - you may need to add a match arm for
PromptViMode::Select
AI Assistance Disclosure
This PR was developed with assistance from OpenCode using Claude Sonnet 4.5. The AI helped with:
- Initial implementation structure and architecture
- Iterative refactoring to improve code quality
- Test coverage and edge case identification
- Documentation and PR summary writing
All code has been reviewed and validated by the human contributor.