fix alignment in slash command popup (#3937)
This commit is contained in:
@@ -95,32 +95,10 @@ impl CommandPopup {
|
|||||||
/// Determine the preferred height of the popup for a given width.
|
/// Determine the preferred height of the popup for a given width.
|
||||||
/// Accounts for wrapped descriptions so that long tooltips don't overflow.
|
/// Accounts for wrapped descriptions so that long tooltips don't overflow.
|
||||||
pub(crate) fn calculate_required_height(&self, width: u16) -> u16 {
|
pub(crate) fn calculate_required_height(&self, width: u16) -> u16 {
|
||||||
use super::selection_popup_common::GenericDisplayRow;
|
|
||||||
use super::selection_popup_common::measure_rows_height;
|
use super::selection_popup_common::measure_rows_height;
|
||||||
let matches = self.filtered();
|
let rows = self.rows_from_matches(self.filtered());
|
||||||
let rows_all: Vec<GenericDisplayRow> = if matches.is_empty() {
|
|
||||||
Vec::new()
|
|
||||||
} else {
|
|
||||||
matches
|
|
||||||
.into_iter()
|
|
||||||
.map(|(item, indices, _)| match item {
|
|
||||||
CommandItem::Builtin(cmd) => GenericDisplayRow {
|
|
||||||
name: format!("/{}", cmd.command()),
|
|
||||||
match_indices: indices.map(|v| v.into_iter().map(|i| i + 1).collect()),
|
|
||||||
is_current: false,
|
|
||||||
description: Some(cmd.description().to_string()),
|
|
||||||
},
|
|
||||||
CommandItem::UserPrompt(i) => GenericDisplayRow {
|
|
||||||
name: format!("/{}", self.prompts[i].name),
|
|
||||||
match_indices: indices.map(|v| v.into_iter().map(|i| i + 1).collect()),
|
|
||||||
is_current: false,
|
|
||||||
description: Some("send saved prompt".to_string()),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
};
|
|
||||||
|
|
||||||
measure_rows_height(&rows_all, &self.state, MAX_POPUP_ROWS, width)
|
measure_rows_height(&rows, &self.state, MAX_POPUP_ROWS, width)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute fuzzy-filtered matches over built-in commands and user prompts,
|
/// Compute fuzzy-filtered matches over built-in commands and user prompts,
|
||||||
@@ -172,6 +150,32 @@ impl CommandPopup {
|
|||||||
self.filtered().into_iter().map(|(c, _, _)| c).collect()
|
self.filtered().into_iter().map(|(c, _, _)| c).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rows_from_matches(
|
||||||
|
&self,
|
||||||
|
matches: Vec<(CommandItem, Option<Vec<usize>>, i32)>,
|
||||||
|
) -> Vec<GenericDisplayRow> {
|
||||||
|
matches
|
||||||
|
.into_iter()
|
||||||
|
.map(|(item, indices, _)| {
|
||||||
|
let (name, description) = match item {
|
||||||
|
CommandItem::Builtin(cmd) => {
|
||||||
|
(format!("/{}", cmd.command()), cmd.description().to_string())
|
||||||
|
}
|
||||||
|
CommandItem::UserPrompt(i) => (
|
||||||
|
format!("/{}", self.prompts[i].name),
|
||||||
|
"send saved prompt".to_string(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
GenericDisplayRow {
|
||||||
|
name,
|
||||||
|
match_indices: indices.map(|v| v.into_iter().map(|i| i + 1).collect()),
|
||||||
|
is_current: false,
|
||||||
|
description: Some(description),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
/// Move the selection cursor one step up.
|
/// Move the selection cursor one step up.
|
||||||
pub(crate) fn move_up(&mut self) {
|
pub(crate) fn move_up(&mut self) {
|
||||||
let len = self.filtered_items().len();
|
let len = self.filtered_items().len();
|
||||||
@@ -198,32 +202,11 @@ impl CommandPopup {
|
|||||||
|
|
||||||
impl WidgetRef for CommandPopup {
|
impl WidgetRef for CommandPopup {
|
||||||
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
|
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
|
||||||
let matches = self.filtered();
|
let rows = self.rows_from_matches(self.filtered());
|
||||||
let rows_all: Vec<GenericDisplayRow> = if matches.is_empty() {
|
|
||||||
Vec::new()
|
|
||||||
} else {
|
|
||||||
matches
|
|
||||||
.into_iter()
|
|
||||||
.map(|(item, indices, _)| match item {
|
|
||||||
CommandItem::Builtin(cmd) => GenericDisplayRow {
|
|
||||||
name: format!("/{}", cmd.command()),
|
|
||||||
match_indices: indices.map(|v| v.into_iter().map(|i| i + 1).collect()),
|
|
||||||
is_current: false,
|
|
||||||
description: Some(cmd.description().to_string()),
|
|
||||||
},
|
|
||||||
CommandItem::UserPrompt(i) => GenericDisplayRow {
|
|
||||||
name: format!("/{}", self.prompts[i].name),
|
|
||||||
match_indices: indices.map(|v| v.into_iter().map(|i| i + 1).collect()),
|
|
||||||
is_current: false,
|
|
||||||
description: Some("send saved prompt".to_string()),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
};
|
|
||||||
render_rows(
|
render_rows(
|
||||||
area,
|
area,
|
||||||
buf,
|
buf,
|
||||||
&rows_all,
|
&rows,
|
||||||
&self.state,
|
&self.state,
|
||||||
MAX_POPUP_ROWS,
|
MAX_POPUP_ROWS,
|
||||||
false,
|
false,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ use ratatui::widgets::Paragraph;
|
|||||||
use ratatui::widgets::Widget;
|
use ratatui::widgets::Widget;
|
||||||
|
|
||||||
use super::scroll_state::ScrollState;
|
use super::scroll_state::ScrollState;
|
||||||
|
use crate::ui_consts::LIVE_PREFIX_COLS;
|
||||||
|
|
||||||
/// A generic representation of a display row for selection popups.
|
/// A generic representation of a display row for selection popups.
|
||||||
pub(crate) struct GenericDisplayRow {
|
pub(crate) struct GenericDisplayRow {
|
||||||
@@ -99,14 +100,34 @@ pub(crate) fn render_rows(
|
|||||||
.border_style(Style::default().add_modifier(Modifier::DIM));
|
.border_style(Style::default().add_modifier(Modifier::DIM));
|
||||||
block.render(area, buf);
|
block.render(area, buf);
|
||||||
|
|
||||||
// Content renders to the right of the border.
|
// Content renders to the right of the border with the same live prefix
|
||||||
|
// padding used by the composer so the popup aligns with the input text.
|
||||||
|
let prefix_cols = LIVE_PREFIX_COLS;
|
||||||
let content_area = Rect {
|
let content_area = Rect {
|
||||||
x: area.x.saturating_add(1),
|
x: area.x.saturating_add(prefix_cols),
|
||||||
y: area.y,
|
y: area.y,
|
||||||
width: area.width.saturating_sub(1),
|
width: area.width.saturating_sub(prefix_cols),
|
||||||
height: area.height,
|
height: area.height,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Clear the padding column(s) so stale characters never peek between the
|
||||||
|
// border and the popup contents.
|
||||||
|
let padding_cols = prefix_cols.saturating_sub(1);
|
||||||
|
if padding_cols > 0 {
|
||||||
|
let pad_start = area.x.saturating_add(1);
|
||||||
|
let pad_end = pad_start
|
||||||
|
.saturating_add(padding_cols)
|
||||||
|
.min(area.x.saturating_add(area.width));
|
||||||
|
let pad_bottom = area.y.saturating_add(area.height);
|
||||||
|
for x in pad_start..pad_end {
|
||||||
|
for y in area.y..pad_bottom {
|
||||||
|
if let Some(cell) = buf.cell_mut((x, y)) {
|
||||||
|
cell.set_symbol(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if rows_all.is_empty() {
|
if rows_all.is_empty() {
|
||||||
if content_area.height > 0 {
|
if content_area.height > 0 {
|
||||||
let para = Paragraph::new(Line::from(empty_message.dim().italic()));
|
let para = Paragraph::new(Line::from(empty_message.dim().italic()));
|
||||||
|
|||||||
@@ -4,5 +4,5 @@ expression: terminal.backend()
|
|||||||
---
|
---
|
||||||
"▌ /mo "
|
"▌ /mo "
|
||||||
"▌ "
|
"▌ "
|
||||||
"▌/model choose what model and reasoning effort to use "
|
"▌ /model choose what model and reasoning effort to use "
|
||||||
"▌/mention mention a file "
|
"▌ /mention mention a file "
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ expression: render_lines(&view)
|
|||||||
▌ Select Approval Mode
|
▌ Select Approval Mode
|
||||||
▌ Switch between Codex approval presets
|
▌ Switch between Codex approval presets
|
||||||
▌
|
▌
|
||||||
▌> 1. Read Only (current) Codex can read files
|
▌ > 1. Read Only (current) Codex can read files
|
||||||
▌ 2. Full Access Codex can edit files
|
▌ 2. Full Access Codex can edit files
|
||||||
|
|
||||||
Press Enter to confirm or Esc to go back
|
Press Enter to confirm or Esc to go back
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ expression: render_lines(&view)
|
|||||||
---
|
---
|
||||||
▌ Select Approval Mode
|
▌ Select Approval Mode
|
||||||
▌
|
▌
|
||||||
▌> 1. Read Only (current) Codex can read files
|
▌ > 1. Read Only (current) Codex can read files
|
||||||
▌ 2. Full Access Codex can edit files
|
▌ 2. Full Access Codex can edit files
|
||||||
|
|
||||||
Press Enter to confirm or Esc to go back
|
Press Enter to confirm or Esc to go back
|
||||||
|
|||||||
Reference in New Issue
Block a user