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();

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
33 changes: 22 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,23 @@ 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);

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 +861,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
7 changes: 6 additions & 1 deletion src/painting/painter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ pub struct Painter {
// Stdout
stdout: W,
prompt_start_row: u16,
// The number of lines that the prompt takes up
prompt_height: u16,
terminal_size: (u16, u16),
last_required_lines: u16,
large_buffer: bool,
Expand All @@ -103,6 +105,7 @@ impl Painter {
Painter {
stdout,
prompt_start_row: 0,
prompt_height: 0,
terminal_size: (0, 0),
last_required_lines: 0,
large_buffer: false,
Expand All @@ -123,7 +126,7 @@ impl Painter {

/// Returns the available lines from the prompt down
pub fn remaining_lines(&self) -> u16 {
self.screen_height().saturating_sub(self.prompt_start_row)
self.screen_height().saturating_sub(self.prompt_height)
}

/// Returns the state necessary before suspending the painter (to run a host command event).
Expand Down Expand Up @@ -199,6 +202,8 @@ impl Painter {
let screen_width = self.screen_width();
let screen_height = self.screen_height();

self.prompt_height = lines.prompt_lines_with_wrap(screen_width);

// Handle resize for multi line prompt
if self.just_resized {
self.prompt_start_row = self.prompt_start_row.saturating_sub(
Expand Down
4 changes: 3 additions & 1 deletion src/painting/prompt_lines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ impl<'prompt> PromptLines<'prompt> {
pub(crate) fn prompt_lines_with_wrap(&self, screen_width: u16) -> u16 {
let complete_prompt = self.prompt_str_left.to_string() + &self.prompt_indicator;
let lines = estimate_required_lines(&complete_prompt, screen_width);
lines.saturating_sub(1) as u16
// TODO: make sure this doesnt cause any problems in other places
// lines.saturating_sub(1) as u16
lines as u16
}

/// Estimated width of the line where right prompt will be rendered
Expand Down