@@ -5,16 +5,15 @@ use tree_sitter::{Node, QueryCursor};
55
66use crate::{
77 chars::{categorize_char, char_is_line_ending, CharCategory},
8− coords_at_pos,
98 graphemes::{
109 next_grapheme_boundary, nth_next_grapheme_boundary, nth_prev_grapheme_boundary,
1110 prev_grapheme_boundary,
1211 },
1312 line_ending::rope_is_line_ending,
14− pos_at_coords,
13+ pos_at_visual_coords,
1514 syntax::LanguageConfiguration,
1615 textobject::TextObject,
17− Position, Range, RopeSlice,
16+ visual_coords_at_pos, Position, Range, RopeSlice,
1817};
1918
2019#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -35,6 +34,7 @@ pub fn move_horizontally(
3534 dir: Direction,
3635 count: usize,
3736 behaviour: Movement,
37+ _: usize,
3838) -> Range {
3939 let pos = range.cursor(slice);
4040
@@ -54,15 +54,12 @@ pub fn move_vertically(
5454 dir: Direction,
5555 count: usize,
5656 behaviour: Movement,
57+ tab_width: usize,
5758) -> Range {
5859 let pos = range.cursor(slice);
5960
6061 // Compute the current position's 2d coordinates.
61− // TODO: switch this to use `visual_coords_at_pos` rather than
62− // `coords_at_pos` as this will cause a jerky movement when the visual
63− // position does not match, like moving from a line with tabs/CJK to
64− // a line without
65− let Position { row, col } = coords_at_pos(slice, pos);
62+ let Position { row, col } = visual_coords_at_pos(slice, pos, tab_width);
6663 let horiz = range.horiz.unwrap_or(col as u32);
6764
6865 // Compute the new position.
@@ -71,7 +68,7 @@ pub fn move_vertically(
7168 Direction::Backward => row.saturating_sub(count),
7269 };
7370 let new_col = col.max(horiz as usize);
74− let new_pos = pos_at_coords(slice, Position::new(new_row, new_col), true);
71+ let new_pos = pos_at_visual_coords(slice, Position::new(new_row, new_col), tab_width);
7572
7673 // Special-case to avoid moving to the end of the last non-empty line.
7774 if behaviour == Movement::Extend && slice.line(new_row).len_chars() == 0 {
@@ -446,6 +443,8 @@ pub fn goto_treesitter_object(
446443mod test {
447444 use ropey::Rope;
448445
446+ use crate::{coords_at_pos, pos_at_coords};
447+
449448 use super::*;
450449
451450 const SINGLE_LINE_SAMPLE: &str = "This is a simple alphabetic line";
@@ -472,7 +471,7 @@ mod test {
472471 assert_eq!(
473472 coords_at_pos(
474473 slice,
475− move_vertically(slice, range, Direction::Forward, 1, Movement::Move).head
474+ move_vertically(slice, range, Direction::Forward, 1, Movement::Move, 4).head
476475 ),
477476 (1, 3).into()
478477 );
@@ -496,7 +495,7 @@ mod test {
496495 ];
497496
498497 for ((direction, amount), coordinates) in moves_and_expected_coordinates {
499− range = move_horizontally(slice, range, direction, amount, Movement::Move);
498+ range = move_horizontally(slice, range, direction, amount, Movement::Move, 0);
500499 assert_eq!(coords_at_pos(slice, range.head), coordinates.into())
501500 }
502501 }
@@ -522,7 +521,7 @@ mod test {
522521 ];
523522
524523 for ((direction, amount), coordinates) in moves_and_expected_coordinates {
525− range = move_horizontally(slice, range, direction, amount, Movement::Move);
524+ range = move_horizontally(slice, range, direction, amount, Movement::Move, 0);
526525 assert_eq!(coords_at_pos(slice, range.head), coordinates.into());
527526 assert_eq!(range.head, range.anchor);
528527 }
@@ -544,7 +543,7 @@ mod test {
544543 ];
545544
546545 for (direction, amount) in moves {
547− range = move_horizontally(slice, range, direction, amount, Movement::Extend);
546+ range = move_horizontally(slice, range, direction, amount, Movement::Extend, 0);
548547 assert_eq!(range.anchor, original_anchor);
549548 }
550549 }
@@ -568,7 +567,7 @@ mod test {
568567 ];
569568
570569 for ((direction, amount), coordinates) in moves_and_expected_coordinates {
571− range = move_vertically(slice, range, direction, amount, Movement::Move);
570+ range = move_vertically(slice, range, direction, amount, Movement::Move, 4);
572571 assert_eq!(coords_at_pos(slice, range.head), coordinates.into());
573572 assert_eq!(range.head, range.anchor);
574573 }
@@ -602,8 +601,8 @@ mod test {
602601
603602 for ((axis, direction, amount), coordinates) in moves_and_expected_coordinates {
604603 range = match axis {
605− Axis::H => move_horizontally(slice, range, direction, amount, Movement::Move),
606− Axis::V => move_vertically(slice, range, direction, amount, Movement::Move),
604+ Axis::H => move_horizontally(slice, range, direction, amount, Movement::Move, 0),
605+ Axis::V => move_vertically(slice, range, direction, amount, Movement::Move, 4),
607606 };
608607 assert_eq!(coords_at_pos(slice, range.head), coordinates.into());
609608 assert_eq!(range.head, range.anchor);
@@ -627,18 +626,18 @@ mod test {
627626 let moves_and_expected_coordinates = [
628627 // Places cursor at the fourth kana.
629628 ((Axis::H, Direction::Forward, 4), (0, 4)),
630− // Descent places cursor at the 4th character.
631− ((Axis::V, Direction::Forward, 1usize), (1, 4)),
632− // Moving back 1 character.
633− ((Axis::H, Direction::Backward, 1usize), (1, 3)),
629+ // Descent places cursor at the 8th character.
630+ ((Axis::V, Direction::Forward, 1usize), (1, 8)),
631+ // Moving back 2 characters.
632+ ((Axis::H, Direction::Backward, 2usize), (1, 6)),
634633 // Jumping back up 1 line.
635634 ((Axis::V, Direction::Backward, 1usize), (0, 3)),
636635 ];
637636
638637 for ((axis, direction, amount), coordinates) in moves_and_expected_coordinates {
639638 range = match axis {
640− Axis::H => move_horizontally(slice, range, direction, amount, Movement::Move),
641− Axis::V => move_vertically(slice, range, direction, amount, Movement::Move),
639+ Axis::H => move_horizontally(slice, range, direction, amount, Movement::Move, 0),
640+ Axis::V => move_vertically(slice, range, direction, amount, Movement::Move, 4),
642641 };
643642 assert_eq!(coords_at_pos(slice, range.head), coordinates.into());
644643 assert_eq!(range.head, range.anchor);