Skip to content

Commit c0ef753

Browse files
shnarazkShekhinah Memmel
authored andcommitted
fix: align view after jumplist_picker (helix-editor#3743)
* Add `View::ensure_cursor_in_view_center` to adjust view after searching and jumping Also `offset_coodrs_to_in_view` was refactored to reduce duplicated position calculations. * Fix a wrong offset calculation in `offset_coords_to_in_view_center` It ignored `scrolloff` if `centering` is false.
1 parent d90e8e2 commit c0ef753

File tree

2 files changed

+67
-37
lines changed

2 files changed

+67
-37
lines changed

helix-term/src/commands.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1670,12 +1670,7 @@ fn search_impl(
16701670
};
16711671

16721672
doc.set_selection(view.id, selection);
1673-
// TODO: is_cursor_in_view does the same calculation as ensure_cursor_in_view
1674-
if view.is_cursor_in_view(doc, 0) {
1675-
view.ensure_cursor_in_view(doc, scrolloff);
1676-
} else {
1677-
align_view(doc, view, Align::Center)
1678-
}
1673+
view.ensure_cursor_in_view_center(doc, scrolloff);
16791674
};
16801675
}
16811676

@@ -2474,8 +2469,10 @@ fn jumplist_picker(cx: &mut Context) {
24742469
(),
24752470
|cx, meta, action| {
24762471
cx.editor.switch(meta.id, action);
2472+
let config = cx.editor.config();
24772473
let (view, doc) = current!(cx.editor);
24782474
doc.set_selection(view.id, meta.selection.clone());
2475+
view.ensure_cursor_in_view_center(doc, config.scrolloff);
24792476
},
24802477
|editor, meta| {
24812478
let doc = &editor.documents.get(&meta.id)?;
@@ -4245,6 +4242,7 @@ fn match_brackets(cx: &mut Context) {
42454242

42464243
fn jump_forward(cx: &mut Context) {
42474244
let count = cx.count();
4245+
let config = cx.editor.config();
42484246
let view = view_mut!(cx.editor);
42494247
let doc_id = view.doc;
42504248

@@ -4258,12 +4256,13 @@ fn jump_forward(cx: &mut Context) {
42584256
}
42594257

42604258
doc.set_selection(view.id, selection);
4261-
align_view(doc, view, Align::Center);
4259+
view.ensure_cursor_in_view_center(doc, config.scrolloff);
42624260
};
42634261
}
42644262

42654263
fn jump_backward(cx: &mut Context) {
42664264
let count = cx.count();
4265+
let config = cx.editor.config();
42674266
let (view, doc) = current!(cx.editor);
42684267
let doc_id = doc.id();
42694268

@@ -4277,7 +4276,7 @@ fn jump_backward(cx: &mut Context) {
42774276
}
42784277

42794278
doc.set_selection(view.id, selection);
4280-
align_view(doc, view, Align::Center);
4279+
view.ensure_cursor_in_view_center(doc, config.scrolloff);
42814280
};
42824281
}
42834282

helix-view/src/view.rs

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{editor::GutterType, graphics::Rect, Document, DocumentId, ViewId};
1+
use crate::{align_view, editor::GutterType, graphics::Rect, Align, Document, DocumentId, ViewId};
22
use helix_core::{
33
pos_at_visual_coords, visual_coords_at_pos, Position, RopeSlice, Selection, Transaction,
44
};
@@ -169,6 +169,15 @@ impl View {
169169
&self,
170170
doc: &Document,
171171
scrolloff: usize,
172+
) -> Option<(usize, usize)> {
173+
self.offset_coords_to_in_view_center(doc, scrolloff, false)
174+
}
175+
176+
pub fn offset_coords_to_in_view_center(
177+
&self,
178+
doc: &Document,
179+
scrolloff: usize,
180+
centering: bool,
172181
) -> Option<(usize, usize)> {
173182
let cursor = doc
174183
.selection(self.id)
@@ -180,47 +189,69 @@ impl View {
180189

181190
let inner_area = self.inner_area(doc);
182191
let last_line = (self.offset.row + inner_area.height as usize).saturating_sub(1);
183-
184-
// - 1 so we have at least one gap in the middle.
185-
// a height of 6 with padding of 3 on each side will keep shifting the view back and forth
186-
// as we type
187-
let scrolloff = scrolloff.min(inner_area.height.saturating_sub(1) as usize / 2);
188-
189192
let last_col = self.offset.col + inner_area.width.saturating_sub(1) as usize;
190193

191-
let row = if line > last_line.saturating_sub(scrolloff) {
192-
// scroll down
193-
self.offset.row + line - (last_line.saturating_sub(scrolloff))
194-
} else if line < self.offset.row + scrolloff {
195-
// scroll up
196-
line.saturating_sub(scrolloff)
197-
} else {
198-
self.offset.row
194+
let new_offset = |scrolloff: usize| {
195+
// - 1 so we have at least one gap in the middle.
196+
// a height of 6 with padding of 3 on each side will keep shifting the view back and forth
197+
// as we type
198+
let scrolloff = scrolloff.min(inner_area.height.saturating_sub(1) as usize / 2);
199+
200+
let row = if line > last_line.saturating_sub(scrolloff) {
201+
// scroll down
202+
self.offset.row + line - (last_line.saturating_sub(scrolloff))
203+
} else if line < self.offset.row + scrolloff {
204+
// scroll up
205+
line.saturating_sub(scrolloff)
206+
} else {
207+
self.offset.row
208+
};
209+
210+
let col = if col > last_col.saturating_sub(scrolloff) {
211+
// scroll right
212+
self.offset.col + col - (last_col.saturating_sub(scrolloff))
213+
} else if col < self.offset.col + scrolloff {
214+
// scroll left
215+
col.saturating_sub(scrolloff)
216+
} else {
217+
self.offset.col
218+
};
219+
(row, col)
199220
};
200-
201-
let col = if col > last_col.saturating_sub(scrolloff) {
202-
// scroll right
203-
self.offset.col + col - (last_col.saturating_sub(scrolloff))
204-
} else if col < self.offset.col + scrolloff {
205-
// scroll left
206-
col.saturating_sub(scrolloff)
221+
let current_offset = (self.offset.row, self.offset.col);
222+
if centering {
223+
// return None if cursor is out of view
224+
let offset = new_offset(0);
225+
(offset == current_offset).then(|| {
226+
if scrolloff == 0 {
227+
offset
228+
} else {
229+
new_offset(scrolloff)
230+
}
231+
})
207232
} else {
208-
self.offset.col
209-
};
210-
if row == self.offset.row && col == self.offset.col {
211-
None
212-
} else {
213-
Some((row, col))
233+
// return None if cursor is in (view - scrolloff)
234+
let offset = new_offset(scrolloff);
235+
(offset != current_offset).then(|| offset) // TODO: use 'then_some' when 1.62 <= MSRV
214236
}
215237
}
216238

217239
pub fn ensure_cursor_in_view(&mut self, doc: &Document, scrolloff: usize) {
218-
if let Some((row, col)) = self.offset_coords_to_in_view(doc, scrolloff) {
240+
if let Some((row, col)) = self.offset_coords_to_in_view_center(doc, scrolloff, false) {
219241
self.offset.row = row;
220242
self.offset.col = col;
221243
}
222244
}
223245

246+
pub fn ensure_cursor_in_view_center(&mut self, doc: &Document, scrolloff: usize) {
247+
if let Some((row, col)) = self.offset_coords_to_in_view_center(doc, scrolloff, true) {
248+
self.offset.row = row;
249+
self.offset.col = col;
250+
} else {
251+
align_view(doc, self, Align::Center);
252+
}
253+
}
254+
224255
pub fn is_cursor_in_view(&mut self, doc: &Document, scrolloff: usize) -> bool {
225256
self.offset_coords_to_in_view(doc, scrolloff).is_none()
226257
}

0 commit comments

Comments
 (0)