Add word_characters
to language overrides & use for more things
Use word_characters to feed completion trigger characters as well and also recognize kebab as a potential sub-word splitter. This is fine for non-kebab-case languages because we'd only ever attempt to split a word with a kebab in it in language scopes which are kebab-cased Co-Authored-By: Max Brunsfeld <max@zed.dev>
This commit is contained in:
parent
a394aaa524
commit
fc457d45f5
13 changed files with 178 additions and 56 deletions
|
@ -439,12 +439,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, |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)
|
||||
|
@ -464,12 +464,12 @@ 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 {
|
||||
*point.column_mut() += 1;
|
||||
point = movement::find_boundary(map, point, |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
|
||||
});
|
||||
|
@ -495,13 +495,13 @@ 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, |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'
|
||||
});
|
||||
|
@ -511,7 +511,7 @@ fn previous_word_start(
|
|||
|
||||
fn first_non_whitespace(map: &DisplaySnapshot, from: DisplayPoint) -> DisplayPoint {
|
||||
let mut last_point = DisplayPoint::new(from.row(), 0);
|
||||
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;
|
||||
|
@ -519,7 +519,7 @@ fn first_non_whitespace(map: &DisplaySnapshot, from: DisplayPoint) -> DisplayPoi
|
|||
|
||||
last_point = point;
|
||||
|
||||
if char_kind(language, ch) != CharKind::Whitespace {
|
||||
if char_kind(&scope, ch) != CharKind::Whitespace {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,19 +82,19 @@ 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, |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
|
||||
});
|
||||
|
|
|
@ -122,18 +122,20 @@ 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_in_line(
|
||||
map,
|
||||
right(map, relative_to, 1),
|
||||
|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_in_line(map, relative_to, |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)
|
||||
|
@ -156,11 +158,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 {
|
||||
|
@ -184,21 +188,23 @@ 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_in_line(
|
||||
map,
|
||||
right(map, relative_to, 1),
|
||||
|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, |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