feat: subword accounts for dash

pull/12026/head
Nikita Revenco 2 weeks ago
parent 26438eadb8
commit fd8f17bcb7

@ -33,6 +33,12 @@ pub fn char_is_line_ending(ch: char) -> bool {
LineEnding::from_char(ch).is_some() LineEnding::from_char(ch).is_some()
} }
/// Determine whether a character is a subword delimiter.
#[inline]
pub fn char_is_subword_delimiter(ch: char) -> bool {
ch == '_' || ch == '-'
}
/// Determine whether a character qualifies as (non-line-break) /// Determine whether a character qualifies as (non-line-break)
/// whitespace. /// whitespace.
#[inline] #[inline]

@ -3,7 +3,7 @@ use std::fmt::Display;
use ropey::RopeSlice; use ropey::RopeSlice;
use tree_sitter::{Node, QueryCursor}; use tree_sitter::{Node, QueryCursor};
use crate::chars::{categorize_char, char_is_whitespace, CharCategory}; use crate::chars::{categorize_char, char_is_subword_delimiter, char_is_whitespace, CharCategory};
use crate::graphemes::{next_grapheme_boundary, prev_grapheme_boundary}; use crate::graphemes::{next_grapheme_boundary, prev_grapheme_boundary};
use crate::line_ending::rope_is_line_ending; use crate::line_ending::rope_is_line_ending;
use crate::movement::Direction; use crate::movement::Direction;
@ -64,7 +64,7 @@ fn find_word_boundary(
&& pos != slice.len_chars(); && pos != slice.len_chars();
let matches_subword = is_subword let matches_subword = is_subword
&& ((prev_ch == '_' || ch == '_') && ((char_is_subword_delimiter(prev_ch) || char_is_subword_delimiter(ch))
|| match direction { || match direction {
Direction::Forward => prev_ch.is_lowercase() && ch.is_uppercase(), Direction::Forward => prev_ch.is_lowercase() && ch.is_uppercase(),
Direction::Backward => prev_ch.is_uppercase() && ch.is_lowercase(), Direction::Backward => prev_ch.is_uppercase() && ch.is_lowercase(),
@ -129,9 +129,27 @@ pub fn textobject_word(
return Range::new(word_start, word_end); return Range::new(word_start, word_end);
} }
match textobject { match (textobject, is_subword) {
TextObject::Inside => Range::new(word_start, word_end), (TextObject::Inside, true) => Range::new(word_start, word_end),
TextObject::Around => { (TextObject::Around, true) => {
let underscores_count_right = slice
.chars_at(word_end)
.take_while(|c| char_is_subword_delimiter(*c))
.count();
if underscores_count_right > 0 {
Range::new(word_start, word_end + underscores_count_right)
} else {
let underscore_count_left = {
let mut iter = slice.chars_at(word_start);
iter.reverse();
iter.take_while(|c| char_is_subword_delimiter(*c)).count()
};
Range::new(word_start - underscore_count_left, word_end)
}
}
(TextObject::Inside, false) => Range::new(word_start, word_end),
(TextObject::Around, false) => {
let whitespace_count_right = slice let whitespace_count_right = slice
.chars_at(word_end) .chars_at(word_end)
.take_while(|c| char_is_whitespace(*c)) .take_while(|c| char_is_whitespace(*c))
@ -148,7 +166,8 @@ pub fn textobject_word(
Range::new(word_start - whitespace_count_left, word_end) Range::new(word_start - whitespace_count_left, word_end)
} }
} }
TextObject::Movement => unreachable!(), (TextObject::Movement, false) => unreachable!(),
(TextObject::Movement, true) => unreachable!(),
} }
} }

Loading…
Cancel
Save