on master help sign in
Short-circuit the word and treesitter object movement commands (#5851)
c704701Mike Trinkala
helix-core/src/movement.rs+27−4
@@ -227,9 +227,15 @@ fn word_move(slice: RopeSlice, range: Range, count: usize, target: WordMotionTar
227 };
227 };
228
228
229 // Do the main work.
229 // Do the main work.
230− (0..count).fold(start_range, |r, _| {
230+ let mut range = start_range;
231+ for _ in 0..count {
231− slice.chars_at(r.head).range_to_target(target, r)
232+ let next_range = slice.chars_at(range.head).range_to_target(target, range);
233+ if range == next_range {
234+ break;
235+ }
236+ range = next_range;
232− })
237+ }
238+ range
233}
239}
234
240
235pub fn move_prev_paragraph(
241pub fn move_prev_paragraph(
@@ -251,6 +257,7 @@ pub fn move_prev_paragraph(
251 let mut lines = slice.lines_at(line);
257 let mut lines = slice.lines_at(line);
252 lines.reverse();
258 lines.reverse();
253 let mut lines = lines.map(rope_is_line_ending).peekable();
259 let mut lines = lines.map(rope_is_line_ending).peekable();
260+ let mut last_line = line;
254 for _ in 0..count {
261 for _ in 0..count {
255 while lines.next_if(|&e| e).is_some() {
262 while lines.next_if(|&e| e).is_some() {
256 line -= 1;
263 line -= 1;
@@ -258,6 +265,10 @@ pub fn move_prev_paragraph(
258 while lines.next_if(|&e| !e).is_some() {
265 while lines.next_if(|&e| !e).is_some() {
259 line -= 1;
266 line -= 1;
260 }
267 }
268+ if line == last_line {
269+ break;
270+ }
271+ last_line = line;
261 }
272 }
262
273
263 let head = slice.line_to_char(line);
274 let head = slice.line_to_char(line);
@@ -293,6 +304,7 @@ pub fn move_next_paragraph(
293 line += 1;
304 line += 1;
294 }
305 }
295 let mut lines = slice.lines_at(line).map(rope_is_line_ending).peekable();
306 let mut lines = slice.lines_at(line).map(rope_is_line_ending).peekable();
307+ let mut last_line = line;
296 for _ in 0..count {
308 for _ in 0..count {
297 while lines.next_if(|&e| !e).is_some() {
309 while lines.next_if(|&e| !e).is_some() {
298 line += 1;
310 line += 1;
@@ -300,6 +312,10 @@ pub fn move_next_paragraph(
300 while lines.next_if(|&e| e).is_some() {
312 while lines.next_if(|&e| e).is_some() {
301 line += 1;
313 line += 1;
302 }
314 }
315+ if line == last_line {
316+ break;
317+ }
318+ last_line = line;
303 }
319 }
304 let head = slice.line_to_char(line);
320 let head = slice.line_to_char(line);
305 let anchor = if behavior == Movement::Move {
321 let anchor = if behavior == Movement::Move {
@@ -523,7 +539,14 @@ pub fn goto_treesitter_object(
523 // head of range should be at beginning
539 // head of range should be at beginning
524 Some(Range::new(start_char, end_char))
540 Some(Range::new(start_char, end_char))
525 };
541 };
526− (0..count).fold(range, |range, _| get_range(range).unwrap_or(range))
542+ let mut last_range = range;
543+ for _ in 0..count {
544+ match get_range(last_range) {
545+ Some(r) if r != last_range => last_range = r,
546+ _ => break,
547+ }
548+ }
549+ last_range
527}
550}
528
551
529#[cfg(test)]
552#[cfg(test)]