on master help sign in
search_impl will only align cursor center when it isn't in view (#959)
a69caffCossonLeo
helix-term/src/commands.rs+19−3
@@ -1175,6 +1175,7 @@ fn search_impl(
1175 regex: &Regex,
1175 regex: &Regex,
1176 movement: Movement,
1176 movement: Movement,
1177 direction: Direction,
1177 direction: Direction,
1178+ scrolloff: usize,
1178) {
1179) {
1179 let text = doc.text().slice(..);
1180 let text = doc.text().slice(..);
1180 let selection = doc.selection(view.id);
1181 let selection = doc.selection(view.id);
@@ -1233,7 +1234,11 @@ fn search_impl(
1233 };
1234 };
1234
1235
1235 doc.set_selection(view.id, selection);
1236 doc.set_selection(view.id, selection);
1237+ if view.is_cursor_in_view(doc, 0) {
1238+ view.ensure_cursor_in_view(doc, scrolloff);
1239+ } else {
1236− align_view(doc, view, Align::Center);
1240+ align_view(doc, view, Align::Center)
1241+ }
1237 };
1242 };
1238}
1243}
1239
1244
@@ -1257,6 +1262,8 @@ fn rsearch(cx: &mut Context) {
1257// TODO: use one function for search vs extend
1262// TODO: use one function for search vs extend
1258fn searcher(cx: &mut Context, direction: Direction) {
1263fn searcher(cx: &mut Context, direction: Direction) {
1259 let reg = cx.register.unwrap_or('/');
1264 let reg = cx.register.unwrap_or('/');
1265+ let scrolloff = cx.editor.config.scrolloff;
1266+
1260 let (_, doc) = current!(cx.editor);
1267 let (_, doc) = current!(cx.editor);
1261
1268
1262 // TODO: could probably share with select_on_matches?
1269 // TODO: could probably share with select_on_matches?
@@ -1281,7 +1288,15 @@ fn searcher(cx: &mut Context, direction: Direction) {
1281 if event != PromptEvent::Update {
1288 if event != PromptEvent::Update {
1282 return;
1289 return;
1283 }
1290 }
1284− search_impl(doc, view, &contents, &regex, Movement::Move, direction);
1291+ search_impl(
1292+ doc,
1293+ view,
1294+ &contents,
1295+ &regex,
1296+ Movement::Move,
1297+ direction,
1298+ scrolloff,
1299+ );
1285 },
1300 },
1286 );
1301 );
1287
1302
@@ -1289,6 +1304,7 @@ fn searcher(cx: &mut Context, direction: Direction) {
1289}
1304}
1290
1305
1291fn search_next_or_prev_impl(cx: &mut Context, movement: Movement, direction: Direction) {
1306fn search_next_or_prev_impl(cx: &mut Context, movement: Movement, direction: Direction) {
1307+ let scrolloff = cx.editor.config.scrolloff;
1292 let (view, doc) = current!(cx.editor);
1308 let (view, doc) = current!(cx.editor);
1293 let registers = &cx.editor.registers;
1309 let registers = &cx.editor.registers;
1294 if let Some(query) = registers.read('/') {
1310 if let Some(query) = registers.read('/') {
@@ -1303,7 +1319,7 @@ fn search_next_or_prev_impl(cx: &mut Context, movement: Movement, direction: Dir
1303 .case_insensitive(case_insensitive)
1319 .case_insensitive(case_insensitive)
1304 .build()
1320 .build()
1305 {
1321 {
1306− search_impl(doc, view, &contents, &regex, movement, direction);
1322+ search_impl(doc, view, &contents, &regex, movement, direction, scrolloff);
1307 } else {
1323 } else {
1308 // get around warning `mutable_borrow_reservation_conflict`
1324 // get around warning `mutable_borrow_reservation_conflict`
1309 // which will be a hard error in the future
1325 // which will be a hard error in the future
helix-view/src/view.rs+33−8
@@ -85,7 +85,12 @@ impl View {
85 self.area.clip_left(OFFSET).clip_bottom(1) // -1 for statusline
85 self.area.clip_left(OFFSET).clip_bottom(1) // -1 for statusline
86 }
86 }
87
87
88− pub fn ensure_cursor_in_view(&mut self, doc: &Document, scrolloff: usize) {
88+ //
89+ pub fn offset_coords_to_in_view(
90+ &self,
91+ doc: &Document,
92+ scrolloff: usize,
93+ ) -> Option<(usize, usize)> {
89 let cursor = doc
94 let cursor = doc
90 .selection(self.id)
95 .selection(self.id)
91 .primary()
96 .primary()
@@ -104,23 +109,43 @@ impl View {
104
109
105 let last_col = self.offset.col + inner_area.width.saturating_sub(1) as usize;
110 let last_col = self.offset.col + inner_area.width.saturating_sub(1) as usize;
106
111
107− if line > last_line.saturating_sub(scrolloff) {
112+ let row = if line > last_line.saturating_sub(scrolloff) {
108 // scroll down
113 // scroll down
109− self.offset.row += line - (last_line.saturating_sub(scrolloff));
114+ self.offset.row + line - (last_line.saturating_sub(scrolloff))
110 } else if line < self.offset.row + scrolloff {
115 } else if line < self.offset.row + scrolloff {
111 // scroll up
116 // scroll up
112− self.offset.row = line.saturating_sub(scrolloff);
117+ line.saturating_sub(scrolloff)
113− }
118+ } else {
119+ self.offset.row
120+ };
114
121
115− if col > last_col.saturating_sub(scrolloff) {
122+ let col = if col > last_col.saturating_sub(scrolloff) {
116 // scroll right
123 // scroll right
117− self.offset.col += col - (last_col.saturating_sub(scrolloff));
124+ self.offset.col + col - (last_col.saturating_sub(scrolloff))
118 } else if col < self.offset.col + scrolloff {
125 } else if col < self.offset.col + scrolloff {
119 // scroll left
126 // scroll left
120− self.offset.col = col.saturating_sub(scrolloff);
127+ col.saturating_sub(scrolloff)
128+ } else {
129+ self.offset.col
130+ };
131+ if row == self.offset.row && col == self.offset.col {
132+ None
133+ } else {
134+ Some((row, col))
121 }
135 }
122 }
136 }
123
137
138+ pub fn ensure_cursor_in_view(&mut self, doc: &Document, scrolloff: usize) {
139+ if let Some((row, col)) = self.offset_coords_to_in_view(doc, scrolloff) {
140+ self.offset.row = row;
141+ self.offset.col = col;
142+ }
143+ }
144+
145+ pub fn is_cursor_in_view(&mut self, doc: &Document, scrolloff: usize) -> bool {
146+ self.offset_coords_to_in_view(doc, scrolloff).is_none()
147+ }
148+
124 /// Calculates the last visible line on screen
149 /// Calculates the last visible line on screen
125 #[inline]
150 #[inline]
126 pub fn last_line(&self, doc: &Document) -> usize {
151 pub fn last_line(&self, doc: &Document) -> usize {