DynamicPicker: Recalculate column widths for new options (#6004)

This fixes blank row text in a DynamicPicker which is initially given
no options. This can happen for language servers which respond to
the workspace symbol request for an empty query with an empty list
of symbols, and that behavior is somewhat common since returning all
symbols as the spec suggests is very expensive.

For empty options, `Picker::new` calculated the widths of each column
as 0. We can recalculate the column widths when the new options are
set to fix this. This refactor is also a good opportunity to formalize
setting new options on a picker: besides setting the new options and
calculating column widths we also want to reset the cursor and rescore
the options.
pull/5465/merge
Michael Davis 2 years ago committed by GitHub
parent 6dc017b9e2
commit 0c6d25acae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -435,26 +435,6 @@ impl<T: Item> Picker<T> {
|_editor: &mut Context, _pattern: &str, _event: PromptEvent| {},
);
let n = options
.first()
.map(|option| option.format(&editor_data).cells.len())
.unwrap_or_default();
let max_lens = options.iter().fold(vec![0; n], |mut acc, option| {
let row = option.format(&editor_data);
// maintain max for each column
for (acc, cell) in acc.iter_mut().zip(row.cells.iter()) {
let width = cell.content.width();
if width > *acc {
*acc = width;
}
}
acc
});
let widths = max_lens
.into_iter()
.map(|len| Constraint::Length(len as u16))
.collect();
let mut picker = Self {
options,
editor_data,
@ -467,10 +447,12 @@ impl<T: Item> Picker<T> {
show_preview: true,
callback_fn: Box::new(callback_fn),
completion_height: 0,
widths,
widths: Vec::new(),
};
// scoring on empty input:
picker.calculate_column_widths();
// scoring on empty input
// TODO: just reuse score()
picker
.matches
@ -486,6 +468,38 @@ impl<T: Item> Picker<T> {
picker
}
pub fn set_options(&mut self, new_options: Vec<T>) {
self.options = new_options;
self.cursor = 0;
self.force_score();
self.calculate_column_widths();
}
/// Calculate the width constraints using the maximum widths of each column
/// for the current options.
fn calculate_column_widths(&mut self) {
let n = self
.options
.first()
.map(|option| option.format(&self.editor_data).cells.len())
.unwrap_or_default();
let max_lens = self.options.iter().fold(vec![0; n], |mut acc, option| {
let row = option.format(&self.editor_data);
// maintain max for each column
for (acc, cell) in acc.iter_mut().zip(row.cells.iter()) {
let width = cell.content.width();
if width > *acc {
*acc = width;
}
}
acc
});
self.widths = max_lens
.into_iter()
.map(|len| Constraint::Length(len as u16))
.collect();
}
pub fn score(&mut self) {
let pattern = self.prompt.line();
@ -931,9 +945,7 @@ impl<T: Item + Send + 'static> Component for DynamicPicker<T> {
Some(overlay) => &mut overlay.content.file_picker.picker,
None => return,
};
picker.options = new_options;
picker.cursor = 0;
picker.force_score();
picker.set_options(new_options);
editor.reset_idle_timer();
}));
anyhow::Ok(callback)

Loading…
Cancel
Save