feat: Ctrl+J for newline in Rust TUI, default to one line of height (#926)
While the `TextArea` used in the Rust TUI is "multiline," it is not like an HTML `<textarea>` in that it does not wrap, so there was not much benefit to setting `MIN_TEXTAREA_ROWS` to `3`, so this PR changes it to `1`. Though there are now three ways to "increase" the height due to actual linebreaks: * paste in multiline content (this worked before this PR) * pressing `Ctrl+J` will insert a newline * if you have your terminal emulator set such that it is possible to press something that `crossterm` interprets as "Enter plus some modifier," then now that will also work Now things look a bit more compact on startup: <img width="745" alt="image" src="https://github.com/user-attachments/assets/86e2857f-f31c-46f5-a80b-1ab2120b266e" />
This commit is contained in:
@@ -29,7 +29,7 @@ use crate::user_approval_widget::ApprovalRequest;
|
|||||||
use crate::user_approval_widget::UserApprovalWidget;
|
use crate::user_approval_widget::UserApprovalWidget;
|
||||||
|
|
||||||
/// Minimum number of visible text rows inside the textarea.
|
/// Minimum number of visible text rows inside the textarea.
|
||||||
const MIN_TEXTAREA_ROWS: usize = 3;
|
const MIN_TEXTAREA_ROWS: usize = 1;
|
||||||
/// Number of terminal rows consumed by the textarea border (top + bottom).
|
/// Number of terminal rows consumed by the textarea border (top + bottom).
|
||||||
const TEXTAREA_BORDER_LINES: u16 = 2;
|
const TEXTAREA_BORDER_LINES: u16 = 2;
|
||||||
|
|
||||||
@@ -176,6 +176,24 @@ impl<'a> BottomPane<'a> {
|
|||||||
self.request_redraw()?;
|
self.request_redraw()?;
|
||||||
Ok(InputResult::Submitted(text))
|
Ok(InputResult::Submitted(text))
|
||||||
}
|
}
|
||||||
|
Input {
|
||||||
|
key: Key::Enter, ..
|
||||||
|
}
|
||||||
|
| Input {
|
||||||
|
key: Key::Char('j'),
|
||||||
|
ctrl: true,
|
||||||
|
alt: false,
|
||||||
|
shift: false,
|
||||||
|
} => {
|
||||||
|
// If the user has their terminal emulator configured so
|
||||||
|
// Enter+Shift (or any modifier) sends a different key
|
||||||
|
// event, we should let them insert a newline.
|
||||||
|
//
|
||||||
|
// We also allow Ctrl+J to insert a newline.
|
||||||
|
self.textarea.insert_newline();
|
||||||
|
self.request_redraw()?;
|
||||||
|
Ok(InputResult::None)
|
||||||
|
}
|
||||||
input => {
|
input => {
|
||||||
self.textarea.input(input);
|
self.textarea.input(input);
|
||||||
self.request_redraw()?;
|
self.request_redraw()?;
|
||||||
@@ -284,7 +302,6 @@ impl WidgetRef for &BottomPane<'_> {
|
|||||||
// for all variants of PaneState.
|
// for all variants of PaneState.
|
||||||
fn update_border_for_input_focus(textarea: &mut TextArea, state: &PaneState, has_focus: bool) {
|
fn update_border_for_input_focus(textarea: &mut TextArea, state: &PaneState, has_focus: bool) {
|
||||||
struct BlockState {
|
struct BlockState {
|
||||||
title: &'static str,
|
|
||||||
right_title: Line<'static>,
|
right_title: Line<'static>,
|
||||||
border_style: Style,
|
border_style: Style,
|
||||||
}
|
}
|
||||||
@@ -297,26 +314,23 @@ fn update_border_for_input_focus(textarea: &mut TextArea, state: &PaneState, has
|
|||||||
|
|
||||||
let block_state = if has_focus && accepting_input {
|
let block_state = if has_focus && accepting_input {
|
||||||
BlockState {
|
BlockState {
|
||||||
title: "use Enter to send for now (Ctrl-D to quit)",
|
right_title: Line::from("Enter to send | Ctrl+D to quit | Ctrl+J for newline")
|
||||||
right_title: Line::from("press enter to send").alignment(Alignment::Right),
|
.alignment(Alignment::Right),
|
||||||
border_style: Style::default(),
|
border_style: Style::default(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
BlockState {
|
BlockState {
|
||||||
title: "",
|
|
||||||
right_title: Line::from(""),
|
right_title: Line::from(""),
|
||||||
border_style: Style::default().dim(),
|
border_style: Style::default().dim(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let BlockState {
|
let BlockState {
|
||||||
title,
|
|
||||||
right_title,
|
right_title,
|
||||||
border_style,
|
border_style,
|
||||||
} = block_state;
|
} = block_state;
|
||||||
textarea.set_block(
|
textarea.set_block(
|
||||||
ratatui::widgets::Block::default()
|
ratatui::widgets::Block::default()
|
||||||
.title_bottom(title)
|
|
||||||
.title_bottom(right_title)
|
.title_bottom(right_title)
|
||||||
.borders(ratatui::widgets::Borders::ALL)
|
.borders(ratatui::widgets::Borders::ALL)
|
||||||
.border_type(BorderType::Rounded)
|
.border_type(BorderType::Rounded)
|
||||||
|
|||||||
Reference in New Issue
Block a user