Skip to content

Commit

Permalink
DynamicPicker: Recalculate column widths for new options (#6004)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
the-mikedavis authored Mar 8, 2023
1 parent 6dc017b commit 0c6d25a
Showing 1 changed file with 37 additions and 25 deletions.
62 changes: 37 additions & 25 deletions helix-term/src/ui/picker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -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();

Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 0c6d25a

Please sign in to comment.