|
|
@ -8,6 +8,7 @@ use fuzzy_matcher::skim::SkimMatcherV2 as Matcher;
|
|
|
|
use fuzzy_matcher::FuzzyMatcher;
|
|
|
|
use fuzzy_matcher::FuzzyMatcher;
|
|
|
|
|
|
|
|
|
|
|
|
use helix_view::{graphics::Rect, Editor};
|
|
|
|
use helix_view::{graphics::Rect, Editor};
|
|
|
|
|
|
|
|
use tui::layout::Constraint;
|
|
|
|
|
|
|
|
|
|
|
|
pub trait Item {
|
|
|
|
pub trait Item {
|
|
|
|
// TODO: sort_text
|
|
|
|
// TODO: sort_text
|
|
|
@ -26,6 +27,8 @@ pub struct Menu<T: Item> {
|
|
|
|
/// (index, score)
|
|
|
|
/// (index, score)
|
|
|
|
matches: Vec<(usize, i64)>,
|
|
|
|
matches: Vec<(usize, i64)>,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
widths: Vec<Constraint>,
|
|
|
|
|
|
|
|
|
|
|
|
callback_fn: Box<dyn Fn(&mut Editor, Option<&T>, MenuEvent)>,
|
|
|
|
callback_fn: Box<dyn Fn(&mut Editor, Option<&T>, MenuEvent)>,
|
|
|
|
|
|
|
|
|
|
|
|
scroll: usize,
|
|
|
|
scroll: usize,
|
|
|
@ -44,6 +47,7 @@ impl<T: Item> Menu<T> {
|
|
|
|
matcher: Box::new(Matcher::default()),
|
|
|
|
matcher: Box::new(Matcher::default()),
|
|
|
|
matches: Vec::new(),
|
|
|
|
matches: Vec::new(),
|
|
|
|
cursor: None,
|
|
|
|
cursor: None,
|
|
|
|
|
|
|
|
widths: Vec::new(),
|
|
|
|
callback_fn: Box::new(callback_fn),
|
|
|
|
callback_fn: Box::new(callback_fn),
|
|
|
|
scroll: 0,
|
|
|
|
scroll: 0,
|
|
|
|
size: (0, 0),
|
|
|
|
size: (0, 0),
|
|
|
@ -218,8 +222,33 @@ impl<T: Item + 'static> Component for Menu<T> {
|
|
|
|
EventResult::Ignored
|
|
|
|
EventResult::Ignored
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: completion sorting
|
|
|
|
|
|
|
|
|
|
|
|
fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> {
|
|
|
|
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::<usize>()) + 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;
|
|
|
|
const MAX: usize = 10;
|
|
|
|
let height = std::cmp::min(self.options.len(), MAX);
|
|
|
|
let height = std::cmp::min(self.options.len(), MAX);
|
|
|
@ -263,13 +292,12 @@ impl<T: Item + 'static> Component for Menu<T> {
|
|
|
|
let scroll_line = (win_height - scroll_height) * scroll
|
|
|
|
let scroll_line = (win_height - scroll_height) * scroll
|
|
|
|
/ std::cmp::max(1, len.saturating_sub(win_height));
|
|
|
|
/ std::cmp::max(1, len.saturating_sub(win_height));
|
|
|
|
|
|
|
|
|
|
|
|
use tui::layout::Constraint;
|
|
|
|
|
|
|
|
let rows = options.iter().map(|option| option.row());
|
|
|
|
let rows = options.iter().map(|option| option.row());
|
|
|
|
let table = Table::new(rows)
|
|
|
|
let table = Table::new(rows)
|
|
|
|
.style(style)
|
|
|
|
.style(style)
|
|
|
|
.highlight_style(selected)
|
|
|
|
.highlight_style(selected)
|
|
|
|
.column_spacing(1)
|
|
|
|
.column_spacing(1)
|
|
|
|
.widths(&[Constraint::Percentage(50), Constraint::Percentage(50)]);
|
|
|
|
.widths(&self.widths);
|
|
|
|
|
|
|
|
|
|
|
|
use tui::widgets::TableState;
|
|
|
|
use tui::widgets::TableState;
|
|
|
|
|
|
|
|
|
|
|
|