Fix Vim 'e' Behavior When Boundary Is Last Point on Line (#7424)
This was originally just to fix https://github.com/zed-industries/zed/issues/4354, which I did by just returning the previous offset in `find_boundary`.. but `find_boundary` is used in the "insert mode" / normal editor too, so returning the previous boundary breaks existing functionality in that case. I was considering a new `find_boundary` function just for some of the vim motions like this, but I thought that this is straightforward enough and future Vim functions might need similar logic too. Release Notes: - Fixed https://github.com/zed-industries/zed/issues/4354
This commit is contained in:
parent
90cd3b5e87
commit
3aa4e0c90b
3 changed files with 48 additions and 20 deletions
|
@ -395,14 +395,17 @@ pub fn find_preceding_boundary(
|
|||
/// Scans for a boundary following the given start point until a boundary is found, indicated by the
|
||||
/// given predicate returning true. The predicate is called with the character to the left and right
|
||||
/// of the candidate boundary location, and will be called with `\n` characters indicating the start
|
||||
/// or end of a line.
|
||||
pub fn find_boundary(
|
||||
/// or end of a line. The function supports optionally returning the point just before the boundary
|
||||
/// is found via return_point_before_boundary.
|
||||
pub fn find_boundary_point(
|
||||
map: &DisplaySnapshot,
|
||||
from: DisplayPoint,
|
||||
find_range: FindRange,
|
||||
mut is_boundary: impl FnMut(char, char) -> bool,
|
||||
return_point_before_boundary: bool,
|
||||
) -> DisplayPoint {
|
||||
let mut offset = from.to_offset(&map, Bias::Right);
|
||||
let mut prev_offset = offset;
|
||||
let mut prev_ch = None;
|
||||
|
||||
for ch in map.buffer_snapshot.chars_at(offset) {
|
||||
|
@ -411,16 +414,38 @@ pub fn find_boundary(
|
|||
}
|
||||
if let Some(prev_ch) = prev_ch {
|
||||
if is_boundary(prev_ch, ch) {
|
||||
break;
|
||||
if return_point_before_boundary {
|
||||
return map.clip_point(prev_offset.to_display_point(map), Bias::Right);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prev_offset = offset;
|
||||
offset += ch.len_utf8();
|
||||
prev_ch = Some(ch);
|
||||
}
|
||||
map.clip_point(offset.to_display_point(map), Bias::Right)
|
||||
}
|
||||
|
||||
pub fn find_boundary(
|
||||
map: &DisplaySnapshot,
|
||||
from: DisplayPoint,
|
||||
find_range: FindRange,
|
||||
is_boundary: impl FnMut(char, char) -> bool,
|
||||
) -> DisplayPoint {
|
||||
return find_boundary_point(map, from, find_range, is_boundary, false);
|
||||
}
|
||||
|
||||
pub fn find_boundary_exclusive(
|
||||
map: &DisplaySnapshot,
|
||||
from: DisplayPoint,
|
||||
find_range: FindRange,
|
||||
is_boundary: impl FnMut(char, char) -> bool,
|
||||
) -> DisplayPoint {
|
||||
return find_boundary_point(map, from, find_range, is_boundary, true);
|
||||
}
|
||||
|
||||
/// Returns an iterator over the characters following a given offset in the [`DisplaySnapshot`].
|
||||
/// The returned value also contains a range of the start/end of a returned character in
|
||||
/// the [`DisplaySnapshot`]. The offsets are relative to the start of a buffer.
|
||||
|
@ -763,7 +788,7 @@ mod tests {
|
|||
&snapshot,
|
||||
display_points[0],
|
||||
FindRange::MultiLine,
|
||||
is_boundary
|
||||
is_boundary,
|
||||
),
|
||||
display_points[1]
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue