Solve an inconsistency between vim and helix
This commit is contained in:
parent
05bc741eaf
commit
309831ea9a
2 changed files with 70 additions and 1 deletions
|
@ -16,7 +16,7 @@ impl Vim {
|
|||
self.update_editor(window, cx, |_, editor, window, cx| {
|
||||
editor.change_selections(Default::default(), window, cx, |s| {
|
||||
s.move_with(|map, selection| {
|
||||
let Some(range) = object.range(map, selection.clone(), around, None) else {
|
||||
let Some(range) = object.helix_range(map, selection.clone(), around) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -714,6 +714,27 @@ impl Object {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the range the object spans if the cursor is over it.
|
||||
/// Follows helix convention.
|
||||
pub fn helix_range(
|
||||
self,
|
||||
map: &DisplaySnapshot,
|
||||
selection: Selection<DisplayPoint>,
|
||||
around: bool,
|
||||
) -> Option<Range<DisplayPoint>> {
|
||||
let relative_to = selection.head();
|
||||
match self {
|
||||
Object::Word { ignore_punctuation } => {
|
||||
if around {
|
||||
helix_around_word(map, relative_to, ignore_punctuation)
|
||||
} else {
|
||||
helix_in_word(map, relative_to, ignore_punctuation)
|
||||
}
|
||||
}
|
||||
_ => self.range(map, selection, around, None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expand_selection(
|
||||
self,
|
||||
map: &DisplaySnapshot,
|
||||
|
@ -759,6 +780,42 @@ fn in_word(
|
|||
Some(start..end)
|
||||
}
|
||||
|
||||
/// Returns a range that surrounds the word `relative_to` is in.
|
||||
///
|
||||
/// If `relative_to` is between words, return `None`.
|
||||
fn helix_in_word(
|
||||
map: &DisplaySnapshot,
|
||||
relative_to: DisplayPoint,
|
||||
ignore_punctuation: bool,
|
||||
) -> Option<Range<DisplayPoint>> {
|
||||
// Use motion::right so that we consider the character under the cursor when looking for the start
|
||||
let classifier = map
|
||||
.buffer_snapshot
|
||||
.char_classifier_at(relative_to.to_point(map))
|
||||
.ignore_punctuation(ignore_punctuation);
|
||||
let char = map
|
||||
.buffer_chars_at(relative_to.to_offset(map, Bias::Left))
|
||||
.next()?
|
||||
.0;
|
||||
|
||||
if classifier.kind(char) == CharKind::Whitespace {
|
||||
return None;
|
||||
}
|
||||
|
||||
let start = movement::find_preceding_boundary_display_point(
|
||||
map,
|
||||
right(map, relative_to, 1),
|
||||
movement::FindRange::SingleLine,
|
||||
|left, right| classifier.kind(left) != classifier.kind(right),
|
||||
);
|
||||
|
||||
let end = movement::find_boundary(map, relative_to, FindRange::SingleLine, |left, right| {
|
||||
classifier.kind(left) != classifier.kind(right)
|
||||
});
|
||||
|
||||
Some(start..end)
|
||||
}
|
||||
|
||||
fn in_subword(
|
||||
map: &DisplaySnapshot,
|
||||
relative_to: DisplayPoint,
|
||||
|
@ -927,6 +984,18 @@ fn around_word(
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the range of the word the cursor is over and all the whitespace on one side.
|
||||
/// If there is whitespace after that is included, otherwise it's whitespace before the word if any.
|
||||
fn helix_around_word(
|
||||
map: &DisplaySnapshot,
|
||||
relative_to: DisplayPoint,
|
||||
ignore_punctuation: bool,
|
||||
) -> Option<Range<DisplayPoint>> {
|
||||
let word_range = helix_in_word(map, relative_to, ignore_punctuation)?;
|
||||
|
||||
Some(expand_to_include_whitespace(map, word_range, true))
|
||||
}
|
||||
|
||||
fn around_subword(
|
||||
map: &DisplaySnapshot,
|
||||
relative_to: DisplayPoint,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue