Merge branch 'main' into vim-softwrap-word
This commit is contained in:
commit
aa7b65bbaf
111 changed files with 4173 additions and 1585 deletions
|
@ -590,12 +590,12 @@ pub(crate) fn next_word_start(
|
|||
ignore_punctuation: bool,
|
||||
times: usize,
|
||||
) -> DisplayPoint {
|
||||
let language = map.buffer_snapshot.language_at(point.to_point(map));
|
||||
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 left_kind = char_kind(language, left).coerce_punctuation(ignore_punctuation);
|
||||
let right_kind = char_kind(language, right).coerce_punctuation(ignore_punctuation);
|
||||
let left_kind = char_kind(&scope, left).coerce_punctuation(ignore_punctuation);
|
||||
let right_kind = char_kind(&scope, right).coerce_punctuation(ignore_punctuation);
|
||||
let at_newline = right == '\n';
|
||||
|
||||
let found = (left_kind != right_kind && right_kind != CharKind::Whitespace)
|
||||
|
@ -615,7 +615,7 @@ fn next_word_end(
|
|||
ignore_punctuation: bool,
|
||||
times: usize,
|
||||
) -> DisplayPoint {
|
||||
let language = map.buffer_snapshot.language_at(point.to_point(map));
|
||||
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;
|
||||
|
@ -623,10 +623,9 @@ fn next_word_end(
|
|||
*point.row_mut() += 1;
|
||||
*point.column_mut() = 0;
|
||||
}
|
||||
// *point.column_mut() += 1;
|
||||
point = movement::find_boundary(map, point, FindRange::MultiLine, |left, right| {
|
||||
let left_kind = char_kind(language, left).coerce_punctuation(ignore_punctuation);
|
||||
let right_kind = char_kind(language, right).coerce_punctuation(ignore_punctuation);
|
||||
let left_kind = char_kind(&scope, left).coerce_punctuation(ignore_punctuation);
|
||||
let right_kind = char_kind(&scope, right).coerce_punctuation(ignore_punctuation);
|
||||
|
||||
left_kind != right_kind && left_kind != CharKind::Whitespace
|
||||
});
|
||||
|
@ -652,14 +651,14 @@ fn previous_word_start(
|
|||
ignore_punctuation: bool,
|
||||
times: usize,
|
||||
) -> DisplayPoint {
|
||||
let language = map.buffer_snapshot.language_at(point.to_point(map));
|
||||
let scope = map.buffer_snapshot.language_scope_at(point.to_point(map));
|
||||
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 =
|
||||
movement::find_preceding_boundary(map, point, FindRange::MultiLine, |left, right| {
|
||||
let left_kind = char_kind(language, left).coerce_punctuation(ignore_punctuation);
|
||||
let right_kind = char_kind(language, right).coerce_punctuation(ignore_punctuation);
|
||||
let left_kind = char_kind(&scope, left).coerce_punctuation(ignore_punctuation);
|
||||
let right_kind = char_kind(&scope, right).coerce_punctuation(ignore_punctuation);
|
||||
|
||||
(left_kind != right_kind && !right.is_whitespace()) || left == '\n'
|
||||
});
|
||||
|
@ -673,7 +672,7 @@ fn first_non_whitespace(
|
|||
from: DisplayPoint,
|
||||
) -> DisplayPoint {
|
||||
let mut last_point = start_of_line(map, display_lines, from);
|
||||
let language = map.buffer_snapshot.language_at(from.to_point(map));
|
||||
let scope = map.buffer_snapshot.language_scope_at(from.to_point(map));
|
||||
for (ch, point) in map.chars_at(last_point) {
|
||||
if ch == '\n' {
|
||||
return from;
|
||||
|
@ -681,7 +680,7 @@ fn first_non_whitespace(
|
|||
|
||||
last_point = point;
|
||||
|
||||
if char_kind(language, ch) != CharKind::Whitespace {
|
||||
if char_kind(&scope, ch) != CharKind::Whitespace {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,22 +89,21 @@ fn expand_changed_word_selection(
|
|||
ignore_punctuation: bool,
|
||||
) -> bool {
|
||||
if times.is_none() || times.unwrap() == 1 {
|
||||
let language = map
|
||||
let scope = map
|
||||
.buffer_snapshot
|
||||
.language_at(selection.start.to_point(map));
|
||||
.language_scope_at(selection.start.to_point(map));
|
||||
let in_word = map
|
||||
.chars_at(selection.head())
|
||||
.next()
|
||||
.map(|(c, _)| char_kind(language, c) != CharKind::Whitespace)
|
||||
.map(|(c, _)| char_kind(&scope, c) != CharKind::Whitespace)
|
||||
.unwrap_or_default();
|
||||
|
||||
if in_word {
|
||||
selection.end =
|
||||
movement::find_boundary(map, selection.end, FindRange::MultiLine, |left, right| {
|
||||
let left_kind =
|
||||
char_kind(language, left).coerce_punctuation(ignore_punctuation);
|
||||
let left_kind = char_kind(&scope, left).coerce_punctuation(ignore_punctuation);
|
||||
let right_kind =
|
||||
char_kind(language, right).coerce_punctuation(ignore_punctuation);
|
||||
char_kind(&scope, right).coerce_punctuation(ignore_punctuation);
|
||||
|
||||
left_kind != right_kind && left_kind != CharKind::Whitespace
|
||||
});
|
||||
|
|
|
@ -67,7 +67,8 @@ fn scroll_editor(editor: &mut Editor, amount: &ScrollAmount, cx: &mut ViewContex
|
|||
let top_anchor = editor.scroll_manager.anchor().anchor;
|
||||
|
||||
editor.change_selections(None, cx, |s| {
|
||||
s.move_heads_with(|map, head, goal| {
|
||||
s.move_with(|map, selection| {
|
||||
let head = selection.head();
|
||||
let top = top_anchor.to_display_point(map);
|
||||
let min_row = top.row() + VERTICAL_SCROLL_MARGIN as u32;
|
||||
let max_row = top.row() + visible_rows - VERTICAL_SCROLL_MARGIN as u32 - 1;
|
||||
|
@ -79,7 +80,11 @@ fn scroll_editor(editor: &mut Editor, amount: &ScrollAmount, cx: &mut ViewContex
|
|||
} else {
|
||||
head
|
||||
};
|
||||
(new_head, goal)
|
||||
if selection.is_empty() {
|
||||
selection.collapse_to(new_head, selection.goal)
|
||||
} else {
|
||||
selection.set_head(new_head, selection.goal)
|
||||
};
|
||||
})
|
||||
});
|
||||
}
|
||||
|
@ -90,12 +95,35 @@ mod test {
|
|||
use crate::{state::Mode, test::VimTestContext};
|
||||
use gpui::geometry::vector::vec2f;
|
||||
use indoc::indoc;
|
||||
use language::Point;
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_scroll(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = VimTestContext::new(cx, true).await;
|
||||
|
||||
cx.set_state(indoc! {"ˇa\nb\nc\nd\ne\n"}, Mode::Normal);
|
||||
let window = cx.window;
|
||||
let line_height =
|
||||
cx.editor(|editor, cx| editor.style(cx).text.line_height(cx.font_cache()));
|
||||
window.simulate_resize(vec2f(1000., 8.0 * line_height - 1.0), &mut cx);
|
||||
|
||||
cx.set_state(
|
||||
indoc!(
|
||||
"ˇone
|
||||
two
|
||||
three
|
||||
four
|
||||
five
|
||||
six
|
||||
seven
|
||||
eight
|
||||
nine
|
||||
ten
|
||||
eleven
|
||||
twelve
|
||||
"
|
||||
),
|
||||
Mode::Normal,
|
||||
);
|
||||
|
||||
cx.update_editor(|editor, cx| {
|
||||
assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 0.))
|
||||
|
@ -112,5 +140,33 @@ mod test {
|
|||
cx.update_editor(|editor, cx| {
|
||||
assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 2.))
|
||||
});
|
||||
|
||||
// does not select in normal mode
|
||||
cx.simulate_keystrokes(["g", "g"]);
|
||||
cx.update_editor(|editor, cx| {
|
||||
assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 0.))
|
||||
});
|
||||
cx.simulate_keystrokes(["ctrl-d"]);
|
||||
cx.update_editor(|editor, cx| {
|
||||
assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 2.0));
|
||||
assert_eq!(
|
||||
editor.selections.newest(cx).range(),
|
||||
Point::new(5, 0)..Point::new(5, 0)
|
||||
)
|
||||
});
|
||||
|
||||
// does select in visual mode
|
||||
cx.simulate_keystrokes(["g", "g"]);
|
||||
cx.update_editor(|editor, cx| {
|
||||
assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 0.))
|
||||
});
|
||||
cx.simulate_keystrokes(["v", "ctrl-d"]);
|
||||
cx.update_editor(|editor, cx| {
|
||||
assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 2.0));
|
||||
assert_eq!(
|
||||
editor.selections.newest(cx).range(),
|
||||
Point::new(0, 0)..Point::new(5, 1)
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -182,19 +182,22 @@ fn in_word(
|
|||
ignore_punctuation: bool,
|
||||
) -> Option<Range<DisplayPoint>> {
|
||||
// Use motion::right so that we consider the character under the cursor when looking for the start
|
||||
let language = map.buffer_snapshot.language_at(relative_to.to_point(map));
|
||||
let scope = map
|
||||
.buffer_snapshot
|
||||
.language_scope_at(relative_to.to_point(map));
|
||||
let start = movement::find_preceding_boundary(
|
||||
map,
|
||||
right(map, relative_to, 1),
|
||||
movement::FindRange::SingleLine,
|
||||
|left, right| {
|
||||
char_kind(language, left).coerce_punctuation(ignore_punctuation)
|
||||
!= char_kind(language, right).coerce_punctuation(ignore_punctuation)
|
||||
char_kind(&scope, left).coerce_punctuation(ignore_punctuation)
|
||||
!= char_kind(&scope, right).coerce_punctuation(ignore_punctuation)
|
||||
},
|
||||
);
|
||||
|
||||
let end = movement::find_boundary(map, relative_to, FindRange::SingleLine, |left, right| {
|
||||
char_kind(language, left).coerce_punctuation(ignore_punctuation)
|
||||
!= char_kind(language, right).coerce_punctuation(ignore_punctuation)
|
||||
char_kind(&scope, left).coerce_punctuation(ignore_punctuation)
|
||||
!= char_kind(&scope, right).coerce_punctuation(ignore_punctuation)
|
||||
});
|
||||
|
||||
Some(start..end)
|
||||
|
@ -217,11 +220,13 @@ fn around_word(
|
|||
relative_to: DisplayPoint,
|
||||
ignore_punctuation: bool,
|
||||
) -> Option<Range<DisplayPoint>> {
|
||||
let language = map.buffer_snapshot.language_at(relative_to.to_point(map));
|
||||
let scope = map
|
||||
.buffer_snapshot
|
||||
.language_scope_at(relative_to.to_point(map));
|
||||
let in_word = map
|
||||
.chars_at(relative_to)
|
||||
.next()
|
||||
.map(|(c, _)| char_kind(language, c) != CharKind::Whitespace)
|
||||
.map(|(c, _)| char_kind(&scope, c) != CharKind::Whitespace)
|
||||
.unwrap_or(false);
|
||||
|
||||
if in_word {
|
||||
|
@ -245,22 +250,24 @@ fn around_next_word(
|
|||
relative_to: DisplayPoint,
|
||||
ignore_punctuation: bool,
|
||||
) -> Option<Range<DisplayPoint>> {
|
||||
let language = map.buffer_snapshot.language_at(relative_to.to_point(map));
|
||||
let scope = map
|
||||
.buffer_snapshot
|
||||
.language_scope_at(relative_to.to_point(map));
|
||||
// Get the start of the word
|
||||
let start = movement::find_preceding_boundary(
|
||||
map,
|
||||
right(map, relative_to, 1),
|
||||
FindRange::SingleLine,
|
||||
|left, right| {
|
||||
char_kind(language, left).coerce_punctuation(ignore_punctuation)
|
||||
!= char_kind(language, right).coerce_punctuation(ignore_punctuation)
|
||||
char_kind(&scope, left).coerce_punctuation(ignore_punctuation)
|
||||
!= char_kind(&scope, right).coerce_punctuation(ignore_punctuation)
|
||||
},
|
||||
);
|
||||
|
||||
let mut word_found = false;
|
||||
let end = movement::find_boundary(map, relative_to, FindRange::MultiLine, |left, right| {
|
||||
let left_kind = char_kind(language, left).coerce_punctuation(ignore_punctuation);
|
||||
let right_kind = char_kind(language, right).coerce_punctuation(ignore_punctuation);
|
||||
let left_kind = char_kind(&scope, left).coerce_punctuation(ignore_punctuation);
|
||||
let right_kind = char_kind(&scope, right).coerce_punctuation(ignore_punctuation);
|
||||
|
||||
let found = (word_found && left_kind != right_kind) || right == '\n' && left == '\n';
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue