aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Vegdahl2021-08-06 00:32:33 +0000
committerGitHub2021-08-06 00:32:33 +0000
commit953125d3f381880f288afa2b59f9936e76d534fa (patch)
treee27c975e955e2afcd320fa76e1a919f982af55e9
parent10c77cdc038f77869a969b9e7182bce235783db7 (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.rs61
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))],
),