diff options
author | Nathan Vegdahl | 2021-08-06 00:32:33 +0000 |
---|---|---|
committer | GitHub | 2021-08-06 00:32:33 +0000 |
commit | 953125d3f381880f288afa2b59f9936e76d534fa (patch) | |
tree | e27c975e955e2afcd320fa76e1a919f982af55e9 | |
parent | 10c77cdc038f77869a969b9e7182bce235783db7 (diff) |
Fix around-word text-object selection. (#546)
* Fix around-word text-object selection.
* Text object around-word: select to the left if no whitespace on the right.
Also only select around when there's whitespace at all.
* Make select-word-around select all white space on a side.
* Update commented-out test case.
* Fix unused import warning from rebase.
-rw-r--r-- | helix-core/src/textobject.rs | 61 |
1 files changed, 36 insertions, 25 deletions
diff --git a/helix-core/src/textobject.rs b/helix-core/src/textobject.rs index b59ff6fa..b965f6df 100644 --- a/helix-core/src/textobject.rs +++ b/helix-core/src/textobject.rs @@ -1,7 +1,7 @@ use ropey::RopeSlice; -use crate::chars::{categorize_char, CharCategory}; -use crate::graphemes::{next_grapheme_boundary, prev_grapheme_boundary}; +use crate::chars::{categorize_char, char_is_whitespace, CharCategory}; +use crate::graphemes::next_grapheme_boundary; use crate::movement::Direction; use crate::surround; use crate::Range; @@ -73,19 +73,23 @@ pub fn textobject_word( match textobject { TextObject::Inside => Range::new(word_start, word_end), - TextObject::Around => Range::new( - match slice - .get_char(word_start.saturating_sub(1)) - .map(categorize_char) - { - None | Some(CharCategory::Eol) => word_start, - _ => prev_grapheme_boundary(slice, word_start), - }, - match slice.get_char(word_end).map(categorize_char) { - None | Some(CharCategory::Eol) => word_end, - _ => next_grapheme_boundary(slice, word_end), - }, - ), + TextObject::Around => { + let whitespace_count_right = slice + .chars_at(word_end) + .take_while(|c| char_is_whitespace(*c)) + .count(); + + if whitespace_count_right > 0 { + Range::new(word_start, word_end + whitespace_count_right) + } else { + let whitespace_count_left = { + let mut iter = slice.chars_at(word_start); + iter.reverse(); + iter.take_while(|c| char_is_whitespace(*c)).count() + }; + Range::new(word_start - whitespace_count_left, word_end) + } + } } } @@ -126,9 +130,9 @@ mod test { (13, Inside, (10, 16)), (10, Inside, (10, 16)), (15, Inside, (10, 16)), - (13, Around, (9, 17)), - (10, Around, (9, 17)), - (15, Around, (9, 17)), + (13, Around, (10, 17)), + (10, Around, (10, 17)), + (15, Around, (10, 17)), ], ), ( @@ -167,9 +171,9 @@ mod test { (13, Inside, (10, 16)), (10, Inside, (10, 16)), (15, Inside, (10, 16)), - (13, Around, (9, 17)), - (10, Around, (9, 17)), - (15, Around, (9, 17)), + (13, Around, (10, 17)), + (10, Around, (10, 17)), + (15, Around, (10, 17)), ], ), ( @@ -178,10 +182,9 @@ mod test { (14, Inside, (14, 21)), (20, Inside, (14, 21)), (17, Inside, (14, 21)), - (14, Around, (13, 22)), - // FIXME: edge case - // (20, Around, (14, 20)), - (17, Around, (13, 22)), + (14, Around, (14, 21)), + (20, Around, (14, 21)), + (17, Around, (14, 21)), ], ), ( @@ -196,6 +199,14 @@ mod test { ], ), ( + "cursor on word with extra whitespace", + vec![(11, Inside, (10, 14)), (11, Around, (10, 17))], + ), + ( + "cursor at end with extra whitespace", + vec![(28, Inside, (27, 37)), (28, Around, (24, 37))], + ), + ( "cursor at end of doc", vec![(19, Inside, (17, 20)), (19, Around, (16, 20))], ), |