From 5292fe0f7df9f1a420744007aa9dd67e7a5a6610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bla=C5=BE=20Hrastnik?= Date: Mon, 19 Jul 2021 11:28:29 +0900 Subject: [PATCH] Calculate completion popup sizing Fixes #220 --- helix-term/src/ui/menu.rs | 34 +++++++++++++++++++++++++++++++--- helix-tui/src/widgets/table.rs | 4 ++-- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/helix-term/src/ui/menu.rs b/helix-term/src/ui/menu.rs index 226c1135d..8681e5b1c 100644 --- a/helix-term/src/ui/menu.rs +++ b/helix-term/src/ui/menu.rs @@ -8,6 +8,7 @@ use fuzzy_matcher::skim::SkimMatcherV2 as Matcher; use fuzzy_matcher::FuzzyMatcher; use helix_view::{graphics::Rect, Editor}; +use tui::layout::Constraint; pub trait Item { // TODO: sort_text @@ -26,6 +27,8 @@ pub struct Menu { /// (index, score) matches: Vec<(usize, i64)>, + widths: Vec, + callback_fn: Box, MenuEvent)>, scroll: usize, @@ -44,6 +47,7 @@ impl Menu { matcher: Box::new(Matcher::default()), matches: Vec::new(), cursor: None, + widths: Vec::new(), callback_fn: Box::new(callback_fn), scroll: 0, size: (0, 0), @@ -218,8 +222,33 @@ impl Component for Menu { EventResult::Ignored } + // TODO: completion sorting + fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> { - let width = std::cmp::min(30, viewport.0); + let n = self + .options + .first() + .map(|option| option.row().cells.len()) + .unwrap_or_default(); + let max_lens = self.options.iter().fold(vec![0; n], |mut acc, option| { + let row = option.row(); + // maintain max for each column + for (i, cell) in row.cells.iter().enumerate() { + let width = cell.content.width(); + if width > acc[i] { + acc[i] = width; + } + } + + acc + }); + let len = (max_lens.iter().sum::()) + n + 1; // +1: reserve some space for scrollbar + let width = len.min(viewport.0 as usize); + + self.widths = max_lens + .into_iter() + .map(|len| Constraint::Length(len as u16)) + .collect(); const MAX: usize = 10; let height = std::cmp::min(self.options.len(), MAX); @@ -263,13 +292,12 @@ impl Component for Menu { let scroll_line = (win_height - scroll_height) * scroll / std::cmp::max(1, len.saturating_sub(win_height)); - use tui::layout::Constraint; let rows = options.iter().map(|option| option.row()); let table = Table::new(rows) .style(style) .highlight_style(selected) .column_spacing(1) - .widths(&[Constraint::Percentage(50), Constraint::Percentage(50)]); + .widths(&self.widths); use tui::widgets::TableState; diff --git a/helix-tui/src/widgets/table.rs b/helix-tui/src/widgets/table.rs index 1ee4286a8..d7caa0b0a 100644 --- a/helix-tui/src/widgets/table.rs +++ b/helix-tui/src/widgets/table.rs @@ -36,7 +36,7 @@ use std::collections::HashMap; /// capabilities of [`Text`]. #[derive(Debug, Clone, PartialEq, Default)] pub struct Cell<'a> { - content: Text<'a>, + pub content: Text<'a>, style: Style, } @@ -81,7 +81,7 @@ where /// By default, a row has a height of 1 but you can change this using [`Row::height`]. #[derive(Debug, Clone, PartialEq, Default)] pub struct Row<'a> { - cells: Vec>, + pub cells: Vec>, height: u16, style: Style, bottom_margin: u16,