@@ -147,12 +147,23 @@ impl State {
147147 ) -> usize {
148148 let text = &self.doc;
149149 match (dir, granularity) {
150− // TODO: clamp movement to line, prevent moving onto \n at the end
151150 (Direction::Backward, Granularity::Character) => {
152− nth_prev_grapheme_boundary(&text.slice(..), pos, count)
151+ // Clamp to line
152+ let line = text.char_to_line(pos);
153+ let start = text.line_to_char(line);
154+ std::cmp::max(
155+ nth_prev_grapheme_boundary(&text.slice(..), pos, count),
156+ start,
157+ )
153158 }
154159 (Direction::Forward, Granularity::Character) => {
155− nth_next_grapheme_boundary(&text.slice(..), pos, count)
160+ // Clamp to line
161+ let line = text.char_to_line(pos);
162+ let start = text.line_to_char(line);
163+ let len = text.line(line).len_chars();
164+ // convert to 0-indexed, subtract another 1 because len_chars() counts \n
165+ let end = start + len.saturating_sub(2);
166+ std::cmp::min(nth_next_grapheme_boundary(&text.slice(..), pos, count), end)
156167 }
157168 (Direction::Forward, Granularity::Word) => {
158169 Self::move_next_word_start(&text.slice(..), pos)