Skip to content

Commit

Permalink
Remember the newline move mode on the range
Browse files Browse the repository at this point in the history
  • Loading branch information
mitsuhiko committed Oct 14, 2022
1 parent 66fa94b commit bc36983
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 9 deletions.
31 changes: 23 additions & 8 deletions helix-core/src/movement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,13 @@ pub fn move_vertically_anchored(
tab_width: usize,
) -> Range {
let pos = range.cursor(slice);
let on_newline = pos == line_end_char_index(&slice, slice.char_to_line(pos));
let line = slice.char_to_line(pos);

// if we are resting on a newline character and we did not just move
// across an empty line where the newline_mode_mode flag was negativley
// carried we are in newline movement mode.
let newline_move_mode = pos == line_end_char_index(&slice, line)
&& !(!range.newline_move_mode && slice.line(line).len_chars() == 1);

// Compute the current position's 2d coordinates.
let Position { row, col } = visual_coords_at_pos(slice, pos, tab_width);
Expand All @@ -135,11 +141,17 @@ pub fn move_vertically_anchored(

// if we are already on a newline character, we want to navigate to the
// newline character on the new line we moved to.
let new_pos = if on_newline {
let new_pos = pos_at_visual_coords(slice, Position::new(new_row, col), tab_width);
line_end_char_index(&slice, slice.char_to_line(new_pos))
let (new_pos, newline_move_mode) = if newline_move_mode {
let new_pos = line_end_char_index(
&slice,
slice.char_to_line(pos_at_visual_coords(
slice,
Position::new(new_row, col),
tab_width,
)),
);

// otherwise place us on the last character before the actual newline character.
(new_pos, true)
} else {
let new_col = col.max(horiz as usize);
let mut new_pos = pos_at_visual_coords(slice, Position::new(new_row, new_col), tab_width);
Expand All @@ -150,15 +162,18 @@ pub fn move_vertically_anchored(
}

// Move away from the newline character.
let end_index = line_end_char_index(&slice, slice.char_to_line(new_pos));
if new_pos == end_index {
let end_index = line_end_char_index(&slice, new_row);
if new_pos == end_index && slice.line(new_row).len_chars() != 1 {
new_pos = graphemes::prev_grapheme_boundary(slice, end_index);
}
new_pos

// non newline movement mode carries the flag of the range forward
(new_pos, range.newline_move_mode)
};

let mut new_range = range.put_cursor(slice, new_pos, behaviour == Movement::Extend);
new_range.horiz = Some(horiz);
new_range.newline_move_mode = newline_move_mode;
new_range
}

Expand Down
22 changes: 21 additions & 1 deletion helix-core/src/selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,12 @@ pub struct Range {
pub anchor: usize,
/// The head of the range, moved when extending.
pub head: usize,
/// Retains the information about the horizontal column we were on
pub horiz: Option<u32>,
/// Disambiugation state for movement across empty lines for anchored
/// newline movement. If this flag is `true` it means that we came
/// from the newline character rather than a character in the line.
pub newline_move_mode: bool,
}

impl Range {
Expand All @@ -62,6 +67,7 @@ impl Range {
anchor,
head,
horiz: None,
newline_move_mode: false,
}
}

Expand Down Expand Up @@ -128,6 +134,7 @@ impl Range {
anchor: self.head,
head: self.anchor,
horiz: self.horiz,
newline_move_mode: self.newline_move_mode,
}
}

Expand Down Expand Up @@ -186,6 +193,7 @@ impl Range {
anchor,
head,
horiz: None,
newline_move_mode: false,
}
}

Expand All @@ -199,12 +207,14 @@ impl Range {
anchor: self.anchor.min(from),
head: self.head.max(to),
horiz: None,
newline_move_mode: false,
}
} else {
Self {
anchor: self.anchor.max(to),
head: self.head.min(from),
horiz: None,
newline_move_mode: false,
}
}
}
Expand All @@ -220,12 +230,14 @@ impl Range {
anchor: self.anchor.max(other.anchor),
head: self.head.min(other.head),
horiz: None,
newline_move_mode: false,
}
} else {
Range {
anchor: self.from().min(other.from()),
head: self.to().max(other.to()),
horiz: None,
newline_move_mode: false,
}
}
}
Expand Down Expand Up @@ -284,6 +296,11 @@ impl Range {
} else {
None
},
newline_move_mode: if new_anchor == self.anchor {
self.newline_move_mode
} else {
false
},
}
}

Expand All @@ -307,6 +324,7 @@ impl Range {
anchor: self.anchor,
head: next_grapheme_boundary(slice, self.head),
horiz: self.horiz,
newline_move_mode: self.newline_move_mode,
}
} else {
*self
Expand Down Expand Up @@ -379,6 +397,7 @@ impl From<(usize, usize)> for Range {
anchor,
head,
horiz: None,
newline_move_mode: false,
}
}
}
Expand Down Expand Up @@ -482,7 +501,8 @@ impl Selection {
ranges: smallvec![Range {
anchor,
head,
horiz: None
horiz: None,
newline_move_mode: false,
}],
primary_index: 0,
}
Expand Down

0 comments on commit bc36983

Please sign in to comment.