feat(tui): support Shift+Enter to insert newline in composer (#801)
* feat(tui): support Shift+Enter to insert newline in composer Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(tui): cover shift-enter newline handling --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Hunter Bown <hmbown@gmail.com>
This commit is contained in:
@@ -145,7 +145,7 @@ pub const KEYBINDINGS: &[KeybindingEntry] = &[
|
||||
section: KeybindingSection::Editing,
|
||||
},
|
||||
KeybindingEntry {
|
||||
chord: "Ctrl+J / Alt+Enter",
|
||||
chord: "Ctrl+J / Alt+Enter / Shift+Enter",
|
||||
description_id: crate::localization::MessageId::KbInsertNewline,
|
||||
section: KeybindingSection::Editing,
|
||||
},
|
||||
|
||||
@@ -2370,10 +2370,7 @@ async fn run_event_loop(
|
||||
continue;
|
||||
}
|
||||
// Input handling
|
||||
KeyCode::Char('j') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||
app.insert_char('\n');
|
||||
}
|
||||
KeyCode::Enter if key.modifiers.contains(KeyModifiers::ALT) => {
|
||||
_ if is_composer_newline_key(key) => {
|
||||
app.insert_char('\n');
|
||||
}
|
||||
KeyCode::Enter
|
||||
@@ -3108,6 +3105,18 @@ fn next_escape_action(app: &App, slash_menu_open: bool) -> EscapeAction {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_composer_newline_key(key: KeyEvent) -> bool {
|
||||
match key.code {
|
||||
KeyCode::Char('j') => key.modifiers.contains(KeyModifiers::CONTROL),
|
||||
KeyCode::Enter => {
|
||||
key.modifiers.contains(KeyModifiers::ALT)
|
||||
|| (key.modifiers.contains(KeyModifiers::SHIFT)
|
||||
&& !key.modifiers.contains(KeyModifiers::CONTROL))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_history_search_key(app: &mut App, key: KeyEvent) {
|
||||
match key.code {
|
||||
KeyCode::Enter => {
|
||||
|
||||
@@ -16,6 +16,34 @@ use std::process::Command;
|
||||
use std::time::{Duration, Instant};
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[test]
|
||||
fn composer_newline_shortcuts_do_not_steal_ctrl_enter() {
|
||||
assert!(is_composer_newline_key(KeyEvent::new(
|
||||
KeyCode::Char('j'),
|
||||
KeyModifiers::CONTROL,
|
||||
)));
|
||||
assert!(is_composer_newline_key(KeyEvent::new(
|
||||
KeyCode::Enter,
|
||||
KeyModifiers::ALT,
|
||||
)));
|
||||
assert!(is_composer_newline_key(KeyEvent::new(
|
||||
KeyCode::Enter,
|
||||
KeyModifiers::SHIFT,
|
||||
)));
|
||||
assert!(!is_composer_newline_key(KeyEvent::new(
|
||||
KeyCode::Enter,
|
||||
KeyModifiers::NONE,
|
||||
)));
|
||||
assert!(!is_composer_newline_key(KeyEvent::new(
|
||||
KeyCode::Enter,
|
||||
KeyModifiers::CONTROL,
|
||||
)));
|
||||
assert!(!is_composer_newline_key(KeyEvent::new(
|
||||
KeyCode::Enter,
|
||||
KeyModifiers::CONTROL | KeyModifiers::SHIFT,
|
||||
)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn selection_point_from_position_ignores_top_padding() {
|
||||
let area = Rect {
|
||||
|
||||
Reference in New Issue
Block a user