tui: ^C in prompt area resets history navigation cursor (#5078)
^C resets the history navigation, similar to zsh/bash. Fixes #4834 ------ https://chatgpt.com/codex/tasks/task_i_68e9674b6ac8832c8212bff6cba75e87
This commit is contained in:
@@ -316,6 +316,11 @@ impl ChatComposer {
|
|||||||
self.sync_file_search_popup();
|
self.sync_file_search_popup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn clear_for_ctrl_c(&mut self) {
|
||||||
|
self.set_text_content(String::new());
|
||||||
|
self.history.reset_navigation();
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the current composer text.
|
/// Get the current composer text.
|
||||||
pub(crate) fn current_text(&self) -> String {
|
pub(crate) fn current_text(&self) -> String {
|
||||||
self.textarea.text().to_string()
|
self.textarea.text().to_string()
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ impl ChatComposerHistory {
|
|||||||
self.local_history.push(text.to_string());
|
self.local_history.push(text.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reset navigation tracking so the next Up key resumes from the latest entry.
|
||||||
|
pub fn reset_navigation(&mut self) {
|
||||||
|
self.history_cursor = None;
|
||||||
|
self.last_history_text = None;
|
||||||
|
}
|
||||||
|
|
||||||
/// Should Up/Down key presses be interpreted as history navigation given
|
/// Should Up/Down key presses be interpreted as history navigation given
|
||||||
/// the current content and cursor position of `textarea`?
|
/// the current content and cursor position of `textarea`?
|
||||||
pub fn should_handle_navigation(&self, text: &str, cursor: usize) -> bool {
|
pub fn should_handle_navigation(&self, text: &str, cursor: usize) -> bool {
|
||||||
@@ -271,4 +277,24 @@ mod tests {
|
|||||||
history.on_entry_response(1, 1, Some("older".into()))
|
history.on_entry_response(1, 1, Some("older".into()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reset_navigation_resets_cursor() {
|
||||||
|
let (tx, _rx) = unbounded_channel::<AppEvent>();
|
||||||
|
let tx = AppEventSender::new(tx);
|
||||||
|
|
||||||
|
let mut history = ChatComposerHistory::new();
|
||||||
|
history.set_metadata(1, 3);
|
||||||
|
history.fetched_history.insert(1, "command2".into());
|
||||||
|
history.fetched_history.insert(2, "command3".into());
|
||||||
|
|
||||||
|
assert_eq!(Some("command3".into()), history.navigate_up(&tx));
|
||||||
|
assert_eq!(Some("command2".into()), history.navigate_up(&tx));
|
||||||
|
|
||||||
|
history.reset_navigation();
|
||||||
|
assert!(history.history_cursor.is_none());
|
||||||
|
assert!(history.last_history_text.is_none());
|
||||||
|
|
||||||
|
assert_eq!(Some("command3".into()), history.navigate_up(&tx));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ impl BottomPane {
|
|||||||
CancellationEvent::NotHandled
|
CancellationEvent::NotHandled
|
||||||
} else {
|
} else {
|
||||||
self.view_stack.pop();
|
self.view_stack.pop();
|
||||||
self.set_composer_text(String::new());
|
self.clear_composer_for_ctrl_c();
|
||||||
self.show_ctrl_c_quit_hint();
|
self.show_ctrl_c_quit_hint();
|
||||||
CancellationEvent::Handled
|
CancellationEvent::Handled
|
||||||
}
|
}
|
||||||
@@ -270,6 +270,11 @@ impl BottomPane {
|
|||||||
self.request_redraw();
|
self.request_redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn clear_composer_for_ctrl_c(&mut self) {
|
||||||
|
self.composer.clear_for_ctrl_c();
|
||||||
|
self.request_redraw();
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the current composer text (for tests and programmatic checks).
|
/// Get the current composer text (for tests and programmatic checks).
|
||||||
pub(crate) fn composer_text(&self) -> String {
|
pub(crate) fn composer_text(&self) -> String {
|
||||||
self.composer.current_text()
|
self.composer.current_text()
|
||||||
|
|||||||
Reference in New Issue
Block a user