on master help sign in
fix: align view after jumplist_picker (#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.

commit453a75a3739338348024b6c676231aef9ef6cb7b authorNarazaki Shuji <shujinarazaki@protonmail.com> dateTue 6 Dec 2022, 11:16 (4 years ago) parent952f292
2 files changed+67−37
helix-term/src/commands.rs+7−8 helix-view/src/view.rs+60−29
helix-term/src/commands.rs+7−8
@@ -1667,12 +1667,7 @@ fn search_impl(
16671667 };
16681668
16691669 doc.set_selection(view.id, selection);
1670− // TODO: is_cursor_in_view does the same calculation as ensure_cursor_in_view
1671− if view.is_cursor_in_view(doc, 0) {
1672− view.ensure_cursor_in_view(doc, scrolloff);
1673− } else {
1674− align_view(doc, view, Align::Center)
1675− }
1670+ view.ensure_cursor_in_view_center(doc, scrolloff);
16761671 };
16771672}
16781673
@@ -2434,8 +2429,10 @@ fn jumplist_picker(cx: &mut Context) {
24342429 (),
24352430 |cx, meta, action| {
24362431 cx.editor.switch(meta.id, action);
2432+ let config = cx.editor.config();
24372433 let (view, doc) = current!(cx.editor);
24382434 doc.set_selection(view.id, meta.selection.clone());
2435+ view.ensure_cursor_in_view_center(doc, config.scrolloff);
24392436 },
24402437 |editor, meta| {
24412438 let doc = &editor.documents.get(&meta.id)?;
@@ -4205,6 +4202,7 @@ fn match_brackets(cx: &mut Context) {
42054202
42064203fn jump_forward(cx: &mut Context) {
42074204 let count = cx.count();
4205+ let config = cx.editor.config();
42084206 let view = view_mut!(cx.editor);
42094207 let doc_id = view.doc;
42104208
@@ -4218,12 +4216,13 @@ fn jump_forward(cx: &mut Context) {
42184216 }
42194217
42204218 doc.set_selection(view.id, selection);
4221− align_view(doc, view, Align::Center);
4219+ view.ensure_cursor_in_view_center(doc, config.scrolloff);
42224220 };
42234221}
42244222
42254223fn jump_backward(cx: &mut Context) {
42264224 let count = cx.count();
4225+ let config = cx.editor.config();
42274226 let (view, doc) = current!(cx.editor);
42284227 let doc_id = doc.id();
42294228
@@ -4237,7 +4236,7 @@ fn jump_backward(cx: &mut Context) {
42374236 }
42384237
42394238 doc.set_selection(view.id, selection);
4240− align_view(doc, view, Align::Center);
4239+ view.ensure_cursor_in_view_center(doc, config.scrolloff);
42414240 };
42424241}
42434242
helix-view/src/view.rs+60−29
@@ -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};
22use 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 }