-
Notifications
You must be signed in to change notification settings - Fork 190
Feature: Helix mode #960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Feature: Helix mode #960
Conversation
Reduces duplication across 5 mode-switching patterns (i/a/I/A/c)
Eliminates repetitive ReedlineRawEvent::try_from boilerplate across all 26 tests
Reduces duplication in keybinding registration for motion commands
Merges HelixModePrompt and SimplePrompt into single HelixPrompt with simple flag
Adds uppercase word motions that move by whitespace-delimited WORDs: - W: move to next WORD start (with selection) - B: move to previous WORD start (with selection) - E: move to next WORD end (with selection) Uses existing MoveBigWordRightStart, MoveBigWordLeft, and MoveBigWordRightEnd commands.
Implements character search motions: - f{char}: find next occurrence (inclusive, extends selection) - t{char}: till next occurrence (exclusive, extends selection) - F{char}: find previous occurrence (inclusive, extends selection) - T{char}: till previous occurrence (exclusive, extends selection) Uses two-key sequence: press f/t/F/T, then the character to search for. Cancels pending search if non-character key pressed. Maps to existing MoveRightUntil/MoveRightBefore/MoveLeftUntil/MoveLeftBefore commands.
- Add PendingCharSearch::to_command() method - Extract handle_pending_char_search() helper - Extract start_char_search() helper Reduces duplication and improves clarity of f/t/F/T implementation.
whoa. helix mode sounds cool. thanks. this will be interesting to play around with. |
the ci needs to be green to proceed. i think these are just formatting |
The manual test sequence is helpful for those who don't use helix. However, on my mac, it doesn't work precisely as you've laid out in those bullets. I'm not sure if they're just wrong or if it's a bug. |
I'll check it out! I've def been testing on windows layout so it's likely something I missed. That documentation there also might have gotten out of sequence in editing too. Good reminder to make sure the keyboard layout is consistent either way |
…lect mode keybindings This commit implements Helix's selection-first editing model correctly: Core Changes: - Split motion bindings into Normal and Select mode variants - Normal mode: motions collapse selection (reset anchor before movement) - Select mode: motions extend selection (anchor stays fixed) - Add separate keybinding function for each mode behavior Selection Model: - Add 'v' key to toggle between Normal and Select modes - Implement ';' to collapse selection to cursor - Implement Alt+';' to swap cursor and anchor - Add 'x' to select entire line New Features: - Add undo/redo support (u/U keys) - Add find/till character motions (f/t/F/T) - Implement proper anchor/cursor/head selection mechanism Bug Fixes: - Fix SHIFT+f and SHIFT+t being interpreted as 'F' and 'T' - Fix duplicate keybinding definitions - Properly separate Normal and Select mode dispatch This brings Reedline's Helix mode in line with actual Helix behavior, where selections are first-class and motions behave differently based on the current mode.
Add two new interactive examples to help users learn Helix mode: 1. hx_mode_tutorial.rs: - Step-by-step guided tutorial - Covers all major features with live demonstrations - Explains Normal vs Select mode behavior - Shows selection model with anchor/cursor - Interactive exercises for key features 2. hx_mode_sandbox.rs: - Minimal example for experimentation - Clean starting point for testing features - Shows basic setup and usage These examples complement the existing test suite by providing hands-on learning experiences for users new to Helix keybindings.
…model Add 27 integration tests that verify Helix mode behavior against the actual Helix editor implementation. Tests were designed based on research of Helix's codebase using DeepWiki. Test Coverage: - Manual workflow sequences (basic editing, mode transitions) - Motion keybindings (h/l, w/b/e, W/B/E, 0/$, f/t/F/T) - Selection model tests (Normal vs Select mode behaviors) - Selection operations (x, ;, Alt+;, v) - Editing operations (d, c, y, p, P) - Special behaviors (Esc cursor movement, Ctrl+C/D) - Complete workflows with multiple edits Selection Model Tests: These tests verify Helix's unique anchor/cursor/head mechanism: - Normal mode: motions collapse selection (move both anchor and head) - Select mode: motions extend selection (anchor fixed, head moves) - Proper interaction between modes - Selection collapse and swap operations All 27 tests pass, providing confidence that the implementation matches Helix's actual behavior for single-line editing contexts. The test file also serves as executable documentation, showing exactly how each feature should work. Removed: examples/HELIX_MODE.md (outdated documentation)
@fdncred if you want to kick off CI again, i was able to fix a few bugs and think it's working pretty smoothly, ran cargo test and cargo fmt --all locally, hopefully it will pass this time, not sure how the spell checker works though |
Updated the pre-submission checklist to match CI requirements more closely: - Added --check flag to cargo fmt to verify formatting without modifying files - Added -D warnings flag to cargo clippy to treat warnings as errors - Added --all flag to cargo test to run tests across all workspace members - Added lockfile check command (cargo check --locked) - Included note about CI testing with multiple feature combinations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Remove the MoveLeft command when transitioning from insert to normal mode with Esc. This aligns the behavior with standard Helix/Vim conventions where the cursor position is maintained without moving left. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
When exiting insert mode with Esc, the cursor should move left one position to ensure it's positioned ON a character rather than AFTER it. This matches standard Helix editor behavior and ensures that subsequent movements in normal mode properly synchronize the cursor position with the selection. The fix ensures that: - After typing in insert mode and pressing Esc, the cursor moves left - Normal mode movements (h/l/w/b/etc.) properly select the character under the cursor - The selection range and cursor position remain synchronized through mode transitions Added comprehensive tests to verify cursor/selection synchronization after insert mode exits and through multiple mode transitions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
…nd modes This commit fixes cursor positioning when exiting insert mode to match actual Helix editor behavior. The cursor should only move left on Escape when exiting from append mode (a/A), not insert mode (i/I). Changes: - Add restore_cursor field to Helix struct to track entry mode - Update enter_insert_mode() to accept restore_cursor parameter - Set restore_cursor=true for append operations (a/A) - Set restore_cursor=false for insert operations (i/I/c) - Conditionally move cursor left on Esc only when restore_cursor=true - Update tests to verify both behaviors (i→Esc and a→Esc) This matches the behavior verified via DeepWiki against the main Helix repository where doc.restore_cursor controls this conditional movement. All 42 Helix tests pass, full test suite (773 tests) passes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
…justment Replace boolean flag with Option<EditCommand> to store the actual exit behavior rather than a proxy state. This is more idiomatic Rust: - Stores exactly what needs to happen (the command) vs. why it happens - Self-documenting at call sites: Some(MoveLeft) vs. true - Eliminates unnecessary state-to-behavior translation - No dependency injection where behavior is inherent to the transition 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
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 endCharacter motions (extend selection):
h/l
- Move left/right with selectionWord motions (extend selection):
w
- Next word startb
- Previous word starte
- Word endW
- Next WORD start (whitespace-delimited)B
- Previous WORD startE
- WORD endLine motions (extend selection):
0
- Line start$
- Line endFind/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 cursorOther:
Enter
- Accept/submit lineCtrl+C/Ctrl+D
- Exit/abortSelect Mode
v
orEsc
- Exit select mode (clear selection)i/a/I/A
- Exit select and enter insert moded/c/y/p
- Edit commands work the sameInsert Mode
Esc
- Return to normal mode (cursor moves left, vi-style)Backspace
- Delete previous characterEnter
- Accept/submit lineCtrl+C/Ctrl+D
- Exit/abortMotivation
Impact on Codebase
Architectural Integration
The implementation follows Reedline's established patterns:
EditMode
trait as Vi and Emacs, ensuring consistent integration with the line editor enginesrc/edit_mode/vi/
organization with separate keybindings and mode logicKeybindings
infrastructure for customizationPromptViMode
enum withSelect
variant for proper mode displayCode Organization
No changes to:
src/core_editor/
)src/engine.rs
)src/painting/
)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 displayUsage pattern matches existing modes:
Compatibility Notes
For Application Developers
If you're currently using Reedline:
PromptViMode::Select
AI Assistance Disclosure
This PR was developed with assistance from OpenCode using Claude Sonnet 4.5. The AI helped with:
All code has been reviewed and validated by the human contributor.