@@ -8,7 +8,6 @@ use tui::{
10use std::borrow::Cow;
10use std::borrow::Cow;
13use helix_core::Position;
12use helix_core::Position;
14use helix_view::Editor;
13use helix_view::Editor;
@@ -24,7 +23,8 @@ pub struct Menu<T> {
24 format_fn: Box<dyn Fn(&T) -> Cow<str>>,
23 format_fn: Box<dyn Fn(&T) -> Cow<str>>,
25 callback_fn: Box<dyn Fn(&mut Editor, Option<&T>, MenuEvent)>,
24 callback_fn: Box<dyn Fn(&mut Editor, Option<&T>, MenuEvent)>,
27− scroll: Cell<usize>,
26+ scroll: usize,
30impl<T> Menu<T> {
30impl<T> Menu<T> {
@@ -40,7 +40,8 @@ impl<T> Menu<T> {
40 cursor: None,
40 cursor: None,
41 format_fn: Box::new(format_fn),
41 format_fn: Box::new(format_fn),
42 callback_fn: Box::new(callback_fn),
42 callback_fn: Box::new(callback_fn),
43− scroll: Cell::new(0),
43+ scroll: 0,
@@ -48,11 +49,28 @@ impl<T> Menu<T> {
48 // TODO: wrap around to end
49 // TODO: wrap around to end
49 let pos = self.cursor.map(|i| i.saturating_sub(1)).unwrap_or(0) % self.options.len();
50 let pos = self.cursor.map(|i| i.saturating_sub(1)).unwrap_or(0) % self.options.len();
50 self.cursor = Some(pos);
51 self.cursor = Some(pos);
52+ self.adjust_scroll();
53 pub fn move_down(&mut self) {
55 pub fn move_down(&mut self) {
54 let pos = self.cursor.map(|i| i + 1).unwrap_or(0) % self.options.len();
56 let pos = self.cursor.map(|i| i + 1).unwrap_or(0) % self.options.len();
55 self.cursor = Some(pos);
57 self.cursor = Some(pos);
58+ self.adjust_scroll();
61+ fn adjust_scroll(&mut self) {
62+ let win_height = self.size.1 as usize;
63+ if let Some(cursor) = self.cursor {
64+ let mut scroll = self.scroll;
65+ if cursor > (win_height + scroll).saturating_sub(1) {
67+ scroll += cursor - (win_height + scroll).saturating_sub(1)
68+ } else if cursor < scroll {
72+ self.scroll = scroll;
58 pub fn selection(&self) -> Option<&T> {
76 pub fn selection(&self) -> Option<&T> {
@@ -156,30 +174,23 @@ impl<T> Component for Menu<T> {
156 let height = std::cmp::min(self.options.len(), MAX);
174 let height = std::cmp::min(self.options.len(), MAX);
157 let height = std::cmp::min(height, viewport.1 as usize);
175 let height = std::cmp::min(height, viewport.1 as usize);
159− Some((width as u16, height as u16))
177+ self.size = (width as u16, height as u16);
179+ // adjust scroll offsets if size changed
180+ self.adjust_scroll();
162 fn render(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
185 fn render(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
163 let style = Style::default().fg(Color::Rgb(164, 160, 232)); // lavender
186 let style = Style::default().fg(Color::Rgb(164, 160, 232)); // lavender
164 let selected = Style::default().fg(Color::Rgb(255, 255, 255));
187 let selected = Style::default().fg(Color::Rgb(255, 255, 255));
166− // TODO: instead of a cell, all these numbers should be precomputed in handle_event + init
167− let mut scroll = self.scroll.get();
189+ let scroll = self.scroll;
168 let len = self.options.len();
190 let len = self.options.len();
170 let win_height = area.height as usize;
192 let win_height = area.height as usize;
172− if let Some(cursor) = self.cursor {
173− if cursor > (win_height + scroll).saturating_sub(1) {
175− scroll += cursor - (win_height + scroll).saturating_sub(1)
176− } else if cursor < scroll {
180− self.scroll.set(scroll);
183 fn div_ceil(a: usize, b: usize) -> usize {
194 fn div_ceil(a: usize, b: usize) -> usize {
184 (a + b - 1) / a
195 (a + b - 1) / a