Allow close skill popup with esc. (#9165)

<img width="398" height="133" alt="image"
src="https://github.com/user-attachments/assets/3084e793-ce5b-4f92-ad60-4c73e65c21c5"
/>
<img width="242" height="86" alt="image"
src="https://github.com/user-attachments/assets/57dd5587-0aea-4a55-91b8-273702939cb2"
/>

You can now esc to quit the skill popup and submit the input as it is.
This commit is contained in:
xl-openai
2026-01-13 15:02:44 -08:00
committed by GitHub
parent 3c711f3d16
commit 89403c5e11
4 changed files with 78 additions and 22 deletions

View File

@@ -983,15 +983,7 @@ impl ChatComposer {
if self.handle_shortcut_overlay_key(&key_event) {
return (InputResult::None, true);
}
if key_event.code == KeyCode::Esc {
let next_mode = esc_hint_mode(self.footer_mode, self.is_task_running);
if next_mode != self.footer_mode {
self.footer_mode = next_mode;
return (InputResult::None, true);
}
} else {
self.footer_mode = reset_mode_after_activity(self.footer_mode);
}
self.footer_mode = reset_mode_after_activity(self.footer_mode);
let ActivePopup::Skill(popup) = &mut self.active_popup else {
unreachable!();

View File

@@ -1,11 +1,17 @@
use crossterm::event::KeyCode;
use ratatui::buffer::Buffer;
use ratatui::layout::Constraint;
use ratatui::layout::Layout;
use ratatui::layout::Rect;
use ratatui::text::Line;
use ratatui::widgets::Widget;
use ratatui::widgets::WidgetRef;
use super::popup_consts::MAX_POPUP_ROWS;
use super::scroll_state::ScrollState;
use super::selection_popup_common::GenericDisplayRow;
use super::selection_popup_common::render_rows_single_line;
use crate::key_hint;
use crate::render::Insets;
use crate::render::RectExt;
use codex_common::fuzzy_match::fuzzy_match;
@@ -41,7 +47,7 @@ impl SkillPopup {
pub(crate) fn calculate_required_height(&self, _width: u16) -> u16 {
let rows = self.rows_from_matches(self.filtered());
let visible = rows.len().clamp(1, MAX_POPUP_ROWS);
visible as u16
(visible as u16).saturating_add(2)
}
pub(crate) fn move_up(&mut self) {
@@ -130,14 +136,44 @@ impl SkillPopup {
impl WidgetRef for SkillPopup {
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
let (list_area, hint_area) = if area.height > 2 {
let [list_area, _spacer_area, hint_area] = Layout::vertical([
Constraint::Length(area.height - 2),
Constraint::Length(1),
Constraint::Length(1),
])
.areas(area);
(list_area, Some(hint_area))
} else {
(area, None)
};
let rows = self.rows_from_matches(self.filtered());
render_rows_single_line(
area.inset(Insets::tlbr(0, 2, 0, 0)),
list_area.inset(Insets::tlbr(0, 2, 0, 0)),
buf,
&rows,
&self.state,
MAX_POPUP_ROWS,
"no skills",
);
if let Some(hint_area) = hint_area {
let hint_area = Rect {
x: hint_area.x + 2,
y: hint_area.y,
width: hint_area.width.saturating_sub(2),
height: hint_area.height,
};
skill_popup_hint_line().render(hint_area, buf);
}
}
}
fn skill_popup_hint_line() -> Line<'static> {
Line::from(vec![
"Press ".into(),
key_hint::plain(KeyCode::Enter).into(),
" to select or ".into(),
key_hint::plain(KeyCode::Esc).into(),
" to close".into(),
])
}