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:
Julia 2023-08-25 18:46:30 -04:00
parent a394aaa524
commit fc457d45f5
13 changed files with 178 additions and 56 deletions

View file

@ -177,20 +177,20 @@ pub fn line_end(
pub fn previous_word_start(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPoint {
let raw_point = point.to_point(map);
let language = map.buffer_snapshot.language_at(raw_point);
let scope = map.buffer_snapshot.language_scope_at(raw_point);
find_preceding_boundary(map, point, |left, right| {
(char_kind(language, left) != char_kind(language, right) && !right.is_whitespace())
(char_kind(&scope, left) != char_kind(&scope, right) && !right.is_whitespace())
|| left == '\n'
})
}
pub fn previous_subword_start(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPoint {
let raw_point = point.to_point(map);
let language = map.buffer_snapshot.language_at(raw_point);
let scope = map.buffer_snapshot.language_scope_at(raw_point);
find_preceding_boundary(map, point, |left, right| {
let is_word_start =
char_kind(language, left) != char_kind(language, right) && !right.is_whitespace();
char_kind(&scope, left) != char_kind(&scope, right) && !right.is_whitespace();
let is_subword_start =
left == '_' && right != '_' || left.is_lowercase() && right.is_uppercase();
is_word_start || is_subword_start || left == '\n'
@ -199,19 +199,19 @@ pub fn previous_subword_start(map: &DisplaySnapshot, point: DisplayPoint) -> Dis
pub fn next_word_end(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPoint {
let raw_point = point.to_point(map);
let language = map.buffer_snapshot.language_at(raw_point);
let scope = map.buffer_snapshot.language_scope_at(raw_point);
find_boundary(map, point, |left, right| {
(char_kind(language, left) != char_kind(language, right) && !left.is_whitespace())
(char_kind(&scope, left) != char_kind(&scope, right) && !left.is_whitespace())
|| right == '\n'
})
}
pub fn next_subword_end(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPoint {
let raw_point = point.to_point(map);
let language = map.buffer_snapshot.language_at(raw_point);
let scope = map.buffer_snapshot.language_scope_at(raw_point);
find_boundary(map, point, |left, right| {
let is_word_end =
(char_kind(language, left) != char_kind(language, right)) && !left.is_whitespace();
(char_kind(&scope, left) != char_kind(&scope, right)) && !left.is_whitespace();
let is_subword_end =
left != '_' && right == '_' || left.is_lowercase() && right.is_uppercase();
is_word_end || is_subword_end || right == '\n'
@ -399,14 +399,14 @@ pub fn find_boundary_in_line(
pub fn is_inside_word(map: &DisplaySnapshot, point: DisplayPoint) -> bool {
let raw_point = point.to_point(map);
let language = map.buffer_snapshot.language_at(raw_point);
let scope = map.buffer_snapshot.language_scope_at(raw_point);
let ix = map.clip_point(point, Bias::Left).to_offset(map, Bias::Left);
let text = &map.buffer_snapshot;
let next_char_kind = text.chars_at(ix).next().map(|c| char_kind(language, c));
let next_char_kind = text.chars_at(ix).next().map(|c| char_kind(&scope, c));
let prev_char_kind = text
.reversed_chars_at(ix)
.next()
.map(|c| char_kind(language, c));
.map(|c| char_kind(&scope, c));
prev_char_kind.zip(next_char_kind) == Some((CharKind::Word, CharKind::Word))
}