Fix vim code working on display map chars (#10103)

Release Notes:

- vim: Fixed motion bugs when softwrap, folds or inlay hints were used.
This commit is contained in:
Conrad Irwin 2024-04-02 22:16:52 -06:00 committed by GitHub
parent 754547f349
commit 5a2a85a7db
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 95 additions and 140 deletions

View file

@ -6,7 +6,10 @@ use crate::{
Vim,
};
use editor::{
display_map::DisplaySnapshot, movement::TextLayoutDetails, scroll::Autoscroll, DisplayPoint,
display_map::{DisplaySnapshot, ToDisplayPoint},
movement::TextLayoutDetails,
scroll::Autoscroll,
Bias, DisplayPoint,
};
use gpui::WindowContext;
use language::{char_kind, CharKind, Selection};
@ -56,15 +59,17 @@ pub fn change_motion(vim: &mut Vim, motion: Motion, times: Option<usize>, cx: &m
&text_layout_details,
);
if let Motion::CurrentLine = motion {
let mut start_offset = selection.start.to_offset(map, Bias::Left);
let scope = map
.buffer_snapshot
.language_scope_at(selection.start.to_point(&map));
for (ch, _) in map.chars_at(selection.start) {
for (ch, offset) in map.buffer_chars_at(start_offset) {
if ch == '\n' || char_kind(&scope, ch) != CharKind::Whitespace {
break;
}
*selection.start.column_mut() += 1;
start_offset = offset + ch.len_utf8();
}
selection.start = start_offset.to_display_point(map);
}
result
};
@ -126,7 +131,7 @@ fn expand_changed_word_selection(
.buffer_snapshot
.language_scope_at(selection.start.to_point(map));
let in_word = map
.chars_at(selection.head())
.buffer_chars_at(selection.head().to_offset(map, Bias::Left))
.next()
.map(|(c, _)| char_kind(&scope, c) != CharKind::Whitespace)
.unwrap_or_default();

View file

@ -84,13 +84,15 @@ pub fn delete_object(vim: &mut Vim, object: Object, around: bool, cx: &mut Windo
selection.start = (start - '\n'.len_utf8()).to_display_point(map);
}
};
let range = selection.start.to_offset(map, Bias::Left)
..selection.end.to_offset(map, Bias::Right);
let contains_only_newlines = map
.chars_at(selection.start)
.take_while(|(_, p)| p < &selection.end)
.buffer_chars_at(range.start)
.take_while(|(_, p)| p < &range.end)
.all(|(char, _)| char == '\n')
&& !offset_range.is_empty();
let end_at_newline = map
.chars_at(selection.end)
.buffer_chars_at(range.end)
.next()
.map(|(c, _)| c == '\n')
.unwrap_or(false);