aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Davis2023-03-08 01:51:52 +0000
committerGitHub2023-03-08 01:51:52 +0000
commit0c6d25acae86cf87356fd3b3b59a25904226e41b (patch)
tree8d7a9b4307b1c5dd516a6aadb63dafb90b9fb82b
parent6dc017b9e23be4f9331bfac8d10f39cdfa54e7bd (diff)
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.
-rw-r--r--helix-term/src/ui/picker.rs62
1 files changed, 37 insertions, 25 deletions
diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs
index 803e2d65..ec8b1c7f 100644
--- a/helix-term/src/ui/picker.rs
+++ b/helix-term/src/ui/picker.rs
@@ -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)