mirror of
https://github.com/hanzoai/dev.git
synced 2026-10-25 03:23:33 +00:00
feat(tui/input): support macOS Cmd shortcuts in composer
- Cmd+Left/Right jump to beginning/end of line - Cmd+Backspace deletes the entire current line contents (preserves newline) - Treat Shift+Left/Right as normal cursor moves (no selection mode) - Keep Option+Delete (Alt+Backspace) and Option+Arrow word‑wise behavior as before for parity with common macOS editors This aligns the TUI composer with expected macOS editing shortcuts and mirrors Codex behavior. Closes #54.
This commit is contained in:
@@ -285,6 +285,33 @@ impl TextArea {
|
||||
} => {
|
||||
self.delete_backward_word();
|
||||
}
|
||||
// macOS-like shortcuts (when terminals report the Command key as SUPER):
|
||||
// Cmd+Left -> move to beginning of line
|
||||
// Cmd+Right -> move to end of line
|
||||
// Cmd+Backspace -> delete entire current line contents
|
||||
#[allow(unreachable_patterns)]
|
||||
KeyEvent { code: KeyCode::Left, modifiers, .. }
|
||||
if modifiers.bits() & (KeyModifiers::ALT | KeyModifiers::CONTROL).bits() == 0
|
||||
&& { #[allow(deprecated)] { modifiers.bits() & (crossterm::event::KeyModifiers::from_bits_truncate(0b0000_1000).bits()) } } != 0 =>
|
||||
{
|
||||
// Treat unknown extra modifier bit (commonly SUPER/Cmd) as line home.
|
||||
self.move_cursor_to_beginning_of_line(false);
|
||||
}
|
||||
#[allow(unreachable_patterns)]
|
||||
KeyEvent { code: KeyCode::Right, modifiers, .. }
|
||||
if modifiers.bits() & (KeyModifiers::ALT | KeyModifiers::CONTROL).bits() == 0
|
||||
&& { #[allow(deprecated)] { modifiers.bits() & (crossterm::event::KeyModifiers::from_bits_truncate(0b0000_1000).bits()) } } != 0 =>
|
||||
{
|
||||
// Treat unknown extra modifier bit (commonly SUPER/Cmd) as line end.
|
||||
self.move_cursor_to_end_of_line(false);
|
||||
}
|
||||
#[allow(unreachable_patterns)]
|
||||
KeyEvent { code: KeyCode::Backspace, modifiers, .. }
|
||||
if { #[allow(deprecated)] { modifiers.bits() & (crossterm::event::KeyModifiers::from_bits_truncate(0b0000_1000).bits()) } } != 0 =>
|
||||
{
|
||||
// Treat Cmd+Backspace as delete entire line contents.
|
||||
self.delete_entire_line();
|
||||
}
|
||||
// Meta-b -> move to beginning of previous word
|
||||
// Meta-f -> move to end of next word
|
||||
// Many terminals map Option (macOS) to Alt. Some send Alt|Shift, so match contains(ALT).
|
||||
@@ -318,18 +345,14 @@ impl TextArea {
|
||||
}
|
||||
|
||||
// Cursor movement
|
||||
KeyEvent {
|
||||
code: KeyCode::Left,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
..
|
||||
} => {
|
||||
KeyEvent { code: KeyCode::Left, modifiers, .. }
|
||||
if modifiers == KeyModifiers::NONE || modifiers == KeyModifiers::SHIFT =>
|
||||
{
|
||||
self.move_cursor_left();
|
||||
}
|
||||
KeyEvent {
|
||||
code: KeyCode::Right,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
..
|
||||
} => {
|
||||
KeyEvent { code: KeyCode::Right, modifiers, .. }
|
||||
if modifiers == KeyModifiers::NONE || modifiers == KeyModifiers::SHIFT =>
|
||||
{
|
||||
self.move_cursor_right();
|
||||
}
|
||||
KeyEvent {
|
||||
@@ -473,6 +496,17 @@ impl TextArea {
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete the entire contents of the current logical line, preserving the newline.
|
||||
/// Leaves the cursor at the beginning of the line.
|
||||
pub fn delete_entire_line(&mut self) {
|
||||
let bol = self.beginning_of_current_line();
|
||||
let eol = self.end_of_current_line();
|
||||
if bol < eol {
|
||||
self.replace_range(bol..eol, "");
|
||||
}
|
||||
self.set_cursor(bol);
|
||||
}
|
||||
|
||||
/// Move the cursor left by a single grapheme cluster.
|
||||
pub fn move_cursor_left(&mut self) {
|
||||
self.cursor_pos = self.prev_atomic_boundary(self.cursor_pos);
|
||||
|
||||
Reference in New Issue
Block a user