Skip to content

Commit b337d3a

Browse files
authored
Use Unicode words for movement (#5)
* Use Unicode words for movement This also skips multiple consecutive non-word characters (word boundaries) as part of the movement in a similar way to how bash/readline do it. * Simplify logic * Fix off by one slicing issue and simplify logic further
1 parent 4c63c7a commit b337d3a

File tree

1 file changed

+22
-14
lines changed

1 file changed

+22
-14
lines changed

src/line_buffer.rs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -100,38 +100,46 @@ impl LineBuffer {
100100
}
101101

102102
pub fn move_word_left(&mut self) -> usize {
103-
match self
104-
.buffer
105-
.rmatch_indices(&[' ', '\t'][..])
106-
.find(|(index, _)| index < &(self.insertion_point - 1))
107-
{
103+
let mut words = self.buffer[..self.insertion_point]
104+
.split_word_bound_indices()
105+
.filter(|(_, word)| !is_word_boundary(word));
106+
107+
match words.next_back() {
108108
Some((index, _)) => {
109-
self.insertion_point = index + 1;
109+
self.insertion_point = index;
110110
}
111111
None => {
112112
self.insertion_point = 0;
113113
}
114114
}
115+
115116
self.insertion_point
116117
}
117118

118119
pub fn move_word_right(&mut self) -> usize {
119-
match self
120-
.buffer
121-
.match_indices(&[' ', '\t'][..])
122-
.find(|(index, _)| index > &(self.insertion_point))
123-
{
124-
Some((index, _)) => {
125-
self.insertion_point = index + 1;
120+
let mut words = self.buffer[self.insertion_point..]
121+
.split_word_bound_indices()
122+
.filter(|(_, word)| !is_word_boundary(word));
123+
124+
match words.next() {
125+
Some((offset, word)) => {
126+
// Move the insertion point just past the end of the next word
127+
self.insertion_point += offset + word.len();
126128
}
127129
None => {
128-
self.insertion_point = self.get_buffer_len();
130+
self.insertion_point = self.buffer.len();
129131
}
130132
}
133+
131134
self.insertion_point
132135
}
133136
}
134137

138+
/// Match any sequence of characters that are considered a word boundary
139+
fn is_word_boundary(s: &str) -> bool {
140+
!s.chars().any(char::is_alphanumeric)
141+
}
142+
135143
#[test]
136144
fn emoji_test() {
137145
//TODO

0 commit comments

Comments
 (0)