fix issue #2713: adding support for alt+ctrl+h to delete backward word (#2717)

This pr addresses the fix for
https://github.com/openai/codex/issues/2713

### Changes:
  - Added key handler for `Alt+Ctrl+H` → `delete_backward_word()`
- Added test coverage in `delete_backward_word_alt_keys()` that verifies
both:
    - Standard `Alt+Backspace` binding continues to work
- New `Alt+Ctrl+H` binding works correctly for backward word deletion

### Testing:
  The test ensures both key combinations produce identical behavior:
  - Delete the previous word from "hello world" → "hello "
  - Cursor positioned correctly after deletion

###  Backward Compatibility:
This change is backward compatible - existing `Alt+Backspace`
functionality remains unchanged while adding support for the
terminal-specific `Alt+Ctrl+H` variant
This commit is contained in:
vinaybantupalli
2025-08-27 05:07:46 +05:30
committed by GitHub
parent f2603a4e50
commit fb3f6456cf

View File

@@ -231,6 +231,13 @@ impl TextArea {
code: KeyCode::Enter,
..
} => self.insert_str("\n"),
KeyEvent {
code: KeyCode::Char('h'),
modifiers,
..
} if modifiers == (KeyModifiers::CONTROL | KeyModifiers::ALT) => {
self.delete_backward_word()
},
KeyEvent {
code: KeyCode::Backspace,
modifiers: KeyModifiers::ALT,
@@ -1138,10 +1145,6 @@ mod tests {
#[test]
fn control_b_and_f_move_cursor() {
use crossterm::event::KeyCode;
use crossterm::event::KeyEvent;
use crossterm::event::KeyModifiers;
let mut t = ta_with("abcd");
t.set_cursor(1);
@@ -1154,10 +1157,6 @@ mod tests {
#[test]
fn control_b_f_fallback_control_chars_move_cursor() {
use crossterm::event::KeyCode;
use crossterm::event::KeyEvent;
use crossterm::event::KeyModifiers;
let mut t = ta_with("abcd");
t.set_cursor(2);
@@ -1171,6 +1170,48 @@ mod tests {
assert_eq!(t.cursor(), 2);
}
#[test]
fn delete_backward_word_alt_keys() {
// Test the custom Alt+Ctrl+h binding
let mut t = ta_with("hello world");
t.set_cursor(t.text().len()); // cursor at the end
t.input(KeyEvent::new(
KeyCode::Char('h'),
KeyModifiers::CONTROL | KeyModifiers::ALT,
));
assert_eq!(t.text(), "hello ");
assert_eq!(t.cursor(), 6);
// Test the standard Alt+Backspace binding
let mut t = ta_with("hello world");
t.set_cursor(t.text().len()); // cursor at the end
t.input(KeyEvent::new(KeyCode::Backspace, KeyModifiers::ALT));
assert_eq!(t.text(), "hello ");
assert_eq!(t.cursor(), 6);
}
#[test]
fn control_h_backspace() {
// Test Ctrl+H as backspace
let mut t = ta_with("12345");
t.set_cursor(3); // cursor after '3'
t.input(KeyEvent::new(KeyCode::Char('h'), KeyModifiers::CONTROL));
assert_eq!(t.text(), "1245");
assert_eq!(t.cursor(), 2);
// Test Ctrl+H at beginning (should be no-op)
t.set_cursor(0);
t.input(KeyEvent::new(KeyCode::Char('h'), KeyModifiers::CONTROL));
assert_eq!(t.text(), "1245");
assert_eq!(t.cursor(), 0);
// Test Ctrl+H at end
t.set_cursor(t.text().len());
t.input(KeyEvent::new(KeyCode::Char('h'), KeyModifiers::CONTROL));
assert_eq!(t.text(), "124");
assert_eq!(t.cursor(), 3);
}
#[test]
fn cursor_vertical_movement_across_lines_and_bounds() {
let mut t = ta_with("short\nloooooooooong\nmid");