mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-19 02:17:35 +03:00
Stop unnecessary repeat cursor movements in Vim mode (#7641)
Fixes: #7605 When repeating some cursor movements in Vim mode (e.g. `99999999 w`), Zed tries to repeat the movement that many times, even if further actions don't have any effect. This causes Zed to hang. This commit makes those movements like other actions (like moving the cursor left/right), stopping the repeat movement if a boundary of the text is reached/the cursor can't move anymore. Release Notes: - Fixed [#7605](https://github.com/zed-industries/zed/issues/7605).
This commit is contained in:
parent
0304edd8ab
commit
e2a3e89318
@ -617,6 +617,9 @@ fn left(map: &DisplaySnapshot, mut point: DisplayPoint, times: usize) -> Display
|
||||
fn backspace(map: &DisplaySnapshot, mut point: DisplayPoint, times: usize) -> DisplayPoint {
|
||||
for _ in 0..times {
|
||||
point = movement::left(map, point);
|
||||
if point.is_zero() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
point
|
||||
}
|
||||
@ -624,6 +627,9 @@ fn backspace(map: &DisplaySnapshot, mut point: DisplayPoint, times: usize) -> Di
|
||||
fn space(map: &DisplaySnapshot, mut point: DisplayPoint, times: usize) -> DisplayPoint {
|
||||
for _ in 0..times {
|
||||
point = wrapping_right(map, point);
|
||||
if point == map.max_point() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
point
|
||||
}
|
||||
@ -768,7 +774,7 @@ pub(crate) fn next_word_start(
|
||||
let scope = map.buffer_snapshot.language_scope_at(point.to_point(map));
|
||||
for _ in 0..times {
|
||||
let mut crossed_newline = false;
|
||||
point = movement::find_boundary(map, point, FindRange::MultiLine, |left, right| {
|
||||
let new_point = movement::find_boundary(map, point, FindRange::MultiLine, |left, right| {
|
||||
let left_kind = coerce_punctuation(char_kind(&scope, left), ignore_punctuation);
|
||||
let right_kind = coerce_punctuation(char_kind(&scope, right), ignore_punctuation);
|
||||
let at_newline = right == '\n';
|
||||
@ -779,7 +785,11 @@ pub(crate) fn next_word_start(
|
||||
|
||||
crossed_newline |= at_newline;
|
||||
found
|
||||
})
|
||||
});
|
||||
if point == new_point {
|
||||
break;
|
||||
}
|
||||
point = new_point;
|
||||
}
|
||||
point
|
||||
}
|
||||
@ -792,21 +802,30 @@ fn next_word_end(
|
||||
) -> DisplayPoint {
|
||||
let scope = map.buffer_snapshot.language_scope_at(point.to_point(map));
|
||||
for _ in 0..times {
|
||||
if point.column() < map.line_len(point.row()) {
|
||||
*point.column_mut() += 1;
|
||||
} else if point.row() < map.max_buffer_row() {
|
||||
*point.row_mut() += 1;
|
||||
*point.column_mut() = 0;
|
||||
let mut new_point = point;
|
||||
if new_point.column() < map.line_len(new_point.row()) {
|
||||
*new_point.column_mut() += 1;
|
||||
} else if new_point.row() < map.max_buffer_row() {
|
||||
*new_point.row_mut() += 1;
|
||||
*new_point.column_mut() = 0;
|
||||
}
|
||||
|
||||
point =
|
||||
movement::find_boundary_exclusive(map, point, FindRange::MultiLine, |left, right| {
|
||||
let new_point = movement::find_boundary_exclusive(
|
||||
map,
|
||||
new_point,
|
||||
FindRange::MultiLine,
|
||||
|left, right| {
|
||||
let left_kind = coerce_punctuation(char_kind(&scope, left), ignore_punctuation);
|
||||
let right_kind = coerce_punctuation(char_kind(&scope, right), ignore_punctuation);
|
||||
|
||||
left_kind != right_kind && left_kind != CharKind::Whitespace
|
||||
});
|
||||
point = map.clip_point(point, Bias::Left);
|
||||
},
|
||||
);
|
||||
let new_point = map.clip_point(new_point, Bias::Left);
|
||||
if point == new_point {
|
||||
break;
|
||||
}
|
||||
point = new_point;
|
||||
}
|
||||
point
|
||||
}
|
||||
@ -821,13 +840,17 @@ fn previous_word_start(
|
||||
for _ in 0..times {
|
||||
// This works even though find_preceding_boundary is called for every character in the line containing
|
||||
// cursor because the newline is checked only once.
|
||||
point =
|
||||
let new_point =
|
||||
movement::find_preceding_boundary(map, point, FindRange::MultiLine, |left, right| {
|
||||
let left_kind = coerce_punctuation(char_kind(&scope, left), ignore_punctuation);
|
||||
let right_kind = coerce_punctuation(char_kind(&scope, right), ignore_punctuation);
|
||||
|
||||
(left_kind != right_kind && !right.is_whitespace()) || left == '\n'
|
||||
});
|
||||
if point == new_point {
|
||||
break;
|
||||
}
|
||||
point = new_point;
|
||||
}
|
||||
point
|
||||
}
|
||||
@ -967,10 +990,14 @@ fn find_forward(
|
||||
|
||||
for _ in 0..times {
|
||||
found = false;
|
||||
to = find_boundary(map, to, FindRange::SingleLine, |_, right| {
|
||||
let new_to = find_boundary(map, to, FindRange::SingleLine, |_, right| {
|
||||
found = right == target;
|
||||
found
|
||||
});
|
||||
if to == new_to {
|
||||
break;
|
||||
}
|
||||
to = new_to;
|
||||
}
|
||||
|
||||
if found {
|
||||
@ -995,7 +1022,12 @@ fn find_backward(
|
||||
let mut to = from;
|
||||
|
||||
for _ in 0..times {
|
||||
to = find_preceding_boundary(map, to, FindRange::SingleLine, |_, right| right == target);
|
||||
let new_to =
|
||||
find_preceding_boundary(map, to, FindRange::SingleLine, |_, right| right == target);
|
||||
if to == new_to {
|
||||
break;
|
||||
}
|
||||
to = new_to;
|
||||
}
|
||||
|
||||
if map.buffer_snapshot.chars_at(to.to_point(map)).next() == Some(target) {
|
||||
|
Loading…
Reference in New Issue
Block a user