mirror of
https://github.com/openai/codex.git
synced 2026-10-22 17:58:46 +00:00
Stable name colkumn widths
This commit is contained in:
@@ -25,11 +25,7 @@ use super::popup_consts::MAX_POPUP_ROWS;
|
||||
use super::scroll_state::ScrollState;
|
||||
pub(crate) use super::selection_popup_common::ColumnWidthMode;
|
||||
use super::selection_popup_common::GenericDisplayRow;
|
||||
use super::selection_popup_common::measure_rows_height;
|
||||
use super::selection_popup_common::measure_rows_height_stable_col_widths;
|
||||
use super::selection_popup_common::measure_rows_height_with_col_width_mode;
|
||||
use super::selection_popup_common::render_rows;
|
||||
use super::selection_popup_common::render_rows_stable_col_widths;
|
||||
use super::selection_popup_common::render_rows_with_col_width_mode;
|
||||
use super::selection_tabs::SelectionTab;
|
||||
use super::selection_tabs::render_tab_bar;
|
||||
@@ -150,6 +146,8 @@ pub(crate) struct SelectionViewParams {
|
||||
pub is_searchable: bool,
|
||||
pub search_placeholder: Option<String>,
|
||||
pub col_width_mode: ColumnWidthMode,
|
||||
/// Rendered left-column width to use for auto-sized rows.
|
||||
pub name_column_width: Option<usize>,
|
||||
pub header: Box<dyn Renderable>,
|
||||
pub initial_selected_idx: Option<usize>,
|
||||
|
||||
@@ -194,6 +192,7 @@ impl Default for SelectionViewParams {
|
||||
is_searchable: false,
|
||||
search_placeholder: None,
|
||||
col_width_mode: ColumnWidthMode::AutoVisible,
|
||||
name_column_width: None,
|
||||
header: Box::new(()),
|
||||
initial_selected_idx: None,
|
||||
side_content: Box::new(()),
|
||||
@@ -226,6 +225,7 @@ pub(crate) struct ListSelectionView {
|
||||
search_query: String,
|
||||
search_placeholder: Option<String>,
|
||||
col_width_mode: ColumnWidthMode,
|
||||
name_column_width: Option<usize>,
|
||||
filtered_indices: Vec<usize>,
|
||||
last_selected_actual_idx: Option<usize>,
|
||||
header: Box<dyn Renderable>,
|
||||
@@ -291,6 +291,7 @@ impl ListSelectionView {
|
||||
None
|
||||
},
|
||||
col_width_mode: params.col_width_mode,
|
||||
name_column_width: params.name_column_width,
|
||||
filtered_indices: Vec::new(),
|
||||
last_selected_actual_idx: None,
|
||||
header,
|
||||
@@ -805,27 +806,14 @@ impl Renderable for ListSelectionView {
|
||||
|
||||
// Measure wrapped height for up to MAX_POPUP_ROWS items.
|
||||
let rows = self.build_rows();
|
||||
let rows_height = match self.col_width_mode {
|
||||
ColumnWidthMode::AutoVisible => measure_rows_height(
|
||||
&rows,
|
||||
&self.state,
|
||||
MAX_POPUP_ROWS,
|
||||
effective_rows_width.saturating_add(1),
|
||||
),
|
||||
ColumnWidthMode::AutoAllRows => measure_rows_height_stable_col_widths(
|
||||
&rows,
|
||||
&self.state,
|
||||
MAX_POPUP_ROWS,
|
||||
effective_rows_width.saturating_add(1),
|
||||
),
|
||||
ColumnWidthMode::Fixed => measure_rows_height_with_col_width_mode(
|
||||
&rows,
|
||||
&self.state,
|
||||
MAX_POPUP_ROWS,
|
||||
effective_rows_width.saturating_add(1),
|
||||
ColumnWidthMode::Fixed,
|
||||
),
|
||||
};
|
||||
let rows_height = measure_rows_height_with_col_width_mode(
|
||||
&rows,
|
||||
&self.state,
|
||||
MAX_POPUP_ROWS,
|
||||
effective_rows_width.saturating_add(1),
|
||||
self.col_width_mode,
|
||||
self.name_column_width,
|
||||
);
|
||||
|
||||
let header = self.active_header();
|
||||
let tab_height = tab_bar_height(&self.tabs, self.active_tab_idx.unwrap_or(0), inner_width);
|
||||
@@ -893,27 +881,14 @@ impl Renderable for ListSelectionView {
|
||||
let header_height = header.desired_height(inner_width);
|
||||
let tab_height = tab_bar_height(&self.tabs, self.active_tab_idx.unwrap_or(0), inner_width);
|
||||
let rows = self.build_rows();
|
||||
let rows_height = match self.col_width_mode {
|
||||
ColumnWidthMode::AutoVisible => measure_rows_height(
|
||||
&rows,
|
||||
&self.state,
|
||||
MAX_POPUP_ROWS,
|
||||
effective_rows_width.saturating_add(1),
|
||||
),
|
||||
ColumnWidthMode::AutoAllRows => measure_rows_height_stable_col_widths(
|
||||
&rows,
|
||||
&self.state,
|
||||
MAX_POPUP_ROWS,
|
||||
effective_rows_width.saturating_add(1),
|
||||
),
|
||||
ColumnWidthMode::Fixed => measure_rows_height_with_col_width_mode(
|
||||
&rows,
|
||||
&self.state,
|
||||
MAX_POPUP_ROWS,
|
||||
effective_rows_width.saturating_add(1),
|
||||
ColumnWidthMode::Fixed,
|
||||
),
|
||||
};
|
||||
let rows_height = measure_rows_height_with_col_width_mode(
|
||||
&rows,
|
||||
&self.state,
|
||||
MAX_POPUP_ROWS,
|
||||
effective_rows_width.saturating_add(1),
|
||||
self.col_width_mode,
|
||||
self.name_column_width,
|
||||
);
|
||||
|
||||
// Stacked (fallback) side content height — only used when not side-by-side.
|
||||
let stacked_side_h = if side_w.is_none() {
|
||||
@@ -984,33 +959,16 @@ impl Renderable for ListSelectionView {
|
||||
width: effective_rows_width.max(1),
|
||||
height: list_area.height,
|
||||
};
|
||||
match self.col_width_mode {
|
||||
ColumnWidthMode::AutoVisible => render_rows(
|
||||
render_area,
|
||||
buf,
|
||||
&rows,
|
||||
&self.state,
|
||||
render_area.height as usize,
|
||||
"no matches",
|
||||
),
|
||||
ColumnWidthMode::AutoAllRows => render_rows_stable_col_widths(
|
||||
render_area,
|
||||
buf,
|
||||
&rows,
|
||||
&self.state,
|
||||
render_area.height as usize,
|
||||
"no matches",
|
||||
),
|
||||
ColumnWidthMode::Fixed => render_rows_with_col_width_mode(
|
||||
render_area,
|
||||
buf,
|
||||
&rows,
|
||||
&self.state,
|
||||
render_area.height as usize,
|
||||
"no matches",
|
||||
ColumnWidthMode::Fixed,
|
||||
),
|
||||
};
|
||||
render_rows_with_col_width_mode(
|
||||
render_area,
|
||||
buf,
|
||||
&rows,
|
||||
&self.state,
|
||||
render_area.height as usize,
|
||||
"no matches",
|
||||
self.col_width_mode,
|
||||
self.name_column_width,
|
||||
);
|
||||
}
|
||||
|
||||
// -- Side content (preview panel) --
|
||||
|
||||
@@ -127,6 +127,7 @@ fn compute_desc_col(
|
||||
visible_items: usize,
|
||||
content_width: u16,
|
||||
col_width_mode: ColumnWidthMode,
|
||||
name_column_width: Option<usize>,
|
||||
) -> usize {
|
||||
if content_width <= 1 {
|
||||
return 0;
|
||||
@@ -177,7 +178,10 @@ fn compute_desc_col(
|
||||
ColumnWidthMode::Fixed => 0,
|
||||
};
|
||||
|
||||
max_name_width.saturating_add(2).min(max_auto_desc_col)
|
||||
name_column_width
|
||||
.unwrap_or(max_name_width)
|
||||
.saturating_add(2)
|
||||
.min(max_auto_desc_col)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -374,6 +378,7 @@ fn adjust_start_for_wrapped_selection_visibility(
|
||||
width: u16,
|
||||
viewport_height: u16,
|
||||
col_width_mode: ColumnWidthMode,
|
||||
name_column_width: Option<usize>,
|
||||
) -> usize {
|
||||
let mut start_idx = compute_item_window_start(rows_all, state, max_items);
|
||||
let Some(sel) = state.selected_idx else {
|
||||
@@ -392,6 +397,7 @@ fn adjust_start_for_wrapped_selection_visibility(
|
||||
desc_measure_items,
|
||||
width,
|
||||
col_width_mode,
|
||||
name_column_width,
|
||||
);
|
||||
if is_selected_visible_in_wrapped_viewport(
|
||||
rows_all,
|
||||
@@ -507,6 +513,7 @@ fn render_rows_inner(
|
||||
max_results: usize,
|
||||
empty_message: &str,
|
||||
col_width_mode: ColumnWidthMode,
|
||||
name_column_width: Option<usize>,
|
||||
) -> u16 {
|
||||
if rows_all.is_empty() {
|
||||
if area.height > 0 {
|
||||
@@ -532,6 +539,7 @@ fn render_rows_inner(
|
||||
area.width,
|
||||
area.height,
|
||||
col_width_mode,
|
||||
name_column_width,
|
||||
);
|
||||
|
||||
let desc_col = compute_desc_col(
|
||||
@@ -540,6 +548,7 @@ fn render_rows_inner(
|
||||
desc_measure_items,
|
||||
area.width,
|
||||
col_width_mode,
|
||||
name_column_width,
|
||||
);
|
||||
|
||||
// Render items, wrapping descriptions and aligning wrapped lines under the
|
||||
@@ -604,6 +613,7 @@ pub(crate) fn render_rows(
|
||||
max_results,
|
||||
empty_message,
|
||||
ColumnWidthMode::AutoVisible,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -632,6 +642,7 @@ pub(crate) fn render_rows_stable_col_widths(
|
||||
max_results,
|
||||
empty_message,
|
||||
ColumnWidthMode::AutoAllRows,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -649,6 +660,7 @@ pub(crate) fn render_rows_with_col_width_mode(
|
||||
max_results: usize,
|
||||
empty_message: &str,
|
||||
col_width_mode: ColumnWidthMode,
|
||||
name_column_width: Option<usize>,
|
||||
) -> u16 {
|
||||
render_rows_inner(
|
||||
area,
|
||||
@@ -658,6 +670,7 @@ pub(crate) fn render_rows_with_col_width_mode(
|
||||
max_results,
|
||||
empty_message,
|
||||
col_width_mode,
|
||||
name_column_width,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -704,6 +717,7 @@ pub(crate) fn render_rows_single_line(
|
||||
visible_items,
|
||||
area.width,
|
||||
ColumnWidthMode::AutoVisible,
|
||||
None,
|
||||
);
|
||||
|
||||
let mut cur_y = area.y;
|
||||
@@ -767,6 +781,7 @@ pub(crate) fn measure_rows_height(
|
||||
max_results,
|
||||
width,
|
||||
ColumnWidthMode::AutoVisible,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -785,6 +800,7 @@ pub(crate) fn measure_rows_height_stable_col_widths(
|
||||
max_results,
|
||||
width,
|
||||
ColumnWidthMode::AutoAllRows,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -797,8 +813,16 @@ pub(crate) fn measure_rows_height_with_col_width_mode(
|
||||
max_results: usize,
|
||||
width: u16,
|
||||
col_width_mode: ColumnWidthMode,
|
||||
name_column_width: Option<usize>,
|
||||
) -> u16 {
|
||||
measure_rows_height_inner(rows_all, state, max_results, width, col_width_mode)
|
||||
measure_rows_height_inner(
|
||||
rows_all,
|
||||
state,
|
||||
max_results,
|
||||
width,
|
||||
col_width_mode,
|
||||
name_column_width,
|
||||
)
|
||||
}
|
||||
|
||||
fn measure_rows_height_inner(
|
||||
@@ -807,6 +831,7 @@ fn measure_rows_height_inner(
|
||||
max_results: usize,
|
||||
width: u16,
|
||||
col_width_mode: ColumnWidthMode,
|
||||
name_column_width: Option<usize>,
|
||||
) -> u16 {
|
||||
if rows_all.is_empty() {
|
||||
return 1; // placeholder "no matches" line
|
||||
@@ -833,6 +858,7 @@ fn measure_rows_height_inner(
|
||||
visible_items,
|
||||
content_width,
|
||||
col_width_mode,
|
||||
name_column_width,
|
||||
);
|
||||
|
||||
let mut total: u16 = 0;
|
||||
|
||||
@@ -33,11 +33,13 @@ use ratatui::text::Line;
|
||||
use ratatui::widgets::Paragraph;
|
||||
use ratatui::widgets::WidgetRef;
|
||||
use ratatui::widgets::Wrap;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
const PLUGINS_SELECTION_VIEW_ID: &str = "plugins-selection";
|
||||
const ALL_PLUGINS_TAB_ID: &str = "all-plugins";
|
||||
const INSTALLED_PLUGINS_TAB_ID: &str = "installed-plugins";
|
||||
const OPENAI_CURATED_TAB_ID: &str = "marketplace:openai-curated";
|
||||
const PLUGIN_MENU_ROW_PREFIX_WIDTH: usize = 2;
|
||||
const LOADING_ANIMATION_DELAY: Duration = Duration::from_secs(1);
|
||||
const LOADING_ANIMATION_INTERVAL: Duration = Duration::from_millis(100);
|
||||
|
||||
@@ -738,6 +740,12 @@ impl ChatWidget {
|
||||
.count();
|
||||
|
||||
let all_entries = plugin_entries_for_marketplaces(marketplaces.iter().copied());
|
||||
let name_column_width = all_entries
|
||||
.iter()
|
||||
.map(|(_, _, display_name)| {
|
||||
PLUGIN_MENU_ROW_PREFIX_WIDTH + UnicodeWidthStr::width(display_name.as_str())
|
||||
})
|
||||
.max();
|
||||
let installed_entries = all_entries
|
||||
.iter()
|
||||
.filter(|(_, plugin, _)| plugin.installed)
|
||||
@@ -859,6 +867,7 @@ impl ChatWidget {
|
||||
is_searchable: true,
|
||||
search_placeholder: Some("Type to search plugins".to_string()),
|
||||
col_width_mode: ColumnWidthMode::AutoAllRows,
|
||||
name_column_width,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user