Skip to content
Merged
32 changes: 21 additions & 11 deletions src/menu/columnar_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ pub struct ColumnarMenu {
col_pos: u16,
/// row position in the menu. Starts from 0
row_pos: u16,
/// Number of values that are skipped when printing,
/// depending on selected value and terminal height
skip_values: u16,
/// Event sent to the menu
event: Option<MenuEvent>,
/// Longest suggestion found in the values
Expand All @@ -82,6 +85,7 @@ impl Default for ColumnarMenu {
values: Vec::new(),
col_pos: 0,
row_pos: 0,
skip_values: 0,
event: None,
longest_suggestion: 0,
input: None,
Expand Down Expand Up @@ -619,6 +623,21 @@ impl Menu for ColumnarMenu {
self.working_details.columns = possible_cols;
}
}

let available_lines = painter.remaining_lines().saturating_sub(1);

let first_visible_row = self.skip_values / self.get_cols();

self.skip_values = if self.row_pos <= first_visible_row {
// Selection is above the visible area, scroll up
self.row_pos * self.get_cols()
} else if self.row_pos >= first_visible_row + available_lines {
// Selection is below the visible area, scroll down
(self.row_pos.saturating_sub(available_lines) + 1) * self.get_cols()
} else {
// Selection is within the visible area
self.skip_values
};
}
}

Expand All @@ -645,27 +664,18 @@ impl Menu for ColumnarMenu {
if self.get_values().is_empty() {
self.no_records_msg(use_ansi_coloring)
} else {
// The skip values represent the number of lines that should be skipped
// while printing the menu
let skip_values = if self.row_pos >= available_lines {
let skip_lines = self.row_pos.saturating_sub(available_lines) + 1;
(skip_lines * self.get_cols()) as usize
} else {
0
};

// It seems that crossterm prefers to have a complete string ready to be printed
// rather than looping through the values and printing multiple things
// This reduces the flickering when printing the menu
let available_values = (available_lines * self.get_cols()) as usize;
self.get_values()
.iter()
.skip(skip_values)
.skip(self.skip_values as usize)
.take(available_values)
.enumerate()
.map(|(index, suggestion)| {
// Correcting the enumerate index based on the number of skipped values
let index = index + skip_values;
let index = index + self.skip_values as usize;
let column = index as u16 % self.get_cols();
let empty_space = self.get_width().saturating_sub(suggestion.value.width());

Expand Down
34 changes: 23 additions & 11 deletions src/menu/ide_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ pub struct IdeMenu {
values: Vec<Suggestion>,
/// Selected value. Starts at 0
selected: u16,
/// Number of values that are skipped when printing,
/// depending on selected value and terminal height
skip_values: u16,
/// Event sent to the menu
event: Option<MenuEvent>,
/// Longest suggestion found in the values
Expand All @@ -161,6 +164,7 @@ impl Default for IdeMenu {
working_details: IdeMenuDetails::default(),
values: Vec::new(),
selected: 0,
skip_values: 0,
event: None,
longest_suggestion: 0,
input: None,
Expand Down Expand Up @@ -807,6 +811,24 @@ impl Menu for IdeMenu {

self.working_details.space_left = space_left;
self.working_details.space_right = space_right;

let available_lines = painter
.remaining_lines()
.min(self.default_details.max_completion_height)
.saturating_sub(1);

let visible_items = available_lines.saturating_sub(border_width);

self.skip_values = if self.selected <= self.skip_values {
// Selection is above the visible area
self.selected
} else if self.selected >= self.skip_values + visible_items {
// Selection is below the visible area
self.selected.saturating_sub(visible_items) + 1
} else {
// Selection is within the visible area
self.skip_values
}
}
}

Expand Down Expand Up @@ -840,17 +862,7 @@ impl Menu for IdeMenu {
};

let available_lines = available_lines.min(self.default_details.max_completion_height);
// The skip values represent the number of lines that should be skipped
// while printing the menu
let skip_values = if self.selected >= available_lines.saturating_sub(border_width) {
let skip_lines = self
.selected
.saturating_sub(available_lines.saturating_sub(border_width))
+ 1;
skip_lines as usize
} else {
0
};
let skip_values = self.skip_values as usize;

let available_values = available_lines.saturating_sub(border_width) as usize;

Expand Down