diff --git a/helix-core/src/state.rs b/helix-core/src/state.rs index c17e9c901..36ca221c0 100644 --- a/helix-core/src/state.rs +++ b/helix-core/src/state.rs @@ -20,6 +20,8 @@ pub struct State { pub selection: Selection, pub mode: Mode, + pub restore_cursor: bool, + // pub syntax: Option, } @@ -46,6 +48,7 @@ pub fn new(doc: Rope) -> Self { selection: Selection::single(0, 0), mode: Mode::Normal, syntax: None, + restore_cursor: false, } } diff --git a/helix-term/src/editor.rs b/helix-term/src/editor.rs index 23ecbea96..a3bc8b3b0 100644 --- a/helix-term/src/editor.rs +++ b/helix-term/src/editor.rs @@ -127,7 +127,7 @@ fn render(&mut self) { .ranges() .iter() // TODO: limit selection to one in viewport - .filter(|range| !range.is_empty()) // && range.overlaps(&Range::new(start, end + 1)) + // .filter(|range| !range.is_empty()) // && range.overlaps(&Range::new(start, end + 1)) .copied() .collect(); @@ -178,6 +178,7 @@ fn render(&mut self) { let grapheme = Cow::from(grapheme); let width = grapheme_width(&grapheme) as u16; + // TODO: this should really happen as an after pass let style = if visible_selections .iter() .any(|range| range.contains(char_index)) @@ -188,6 +189,15 @@ fn render(&mut self) { style }; + let style = if visible_selections + .iter() + .any(|range| range.head == char_index) + { + style.clone().bg(Color::Rgb(255, 255, 255)) + } else { + style + }; + // TODO: paint cursor heads except primary self.surface.set_string( diff --git a/helix-view/src/commands.rs b/helix-view/src/commands.rs index 2b2f1239e..93ec2632b 100644 --- a/helix-view/src/commands.rs +++ b/helix-view/src/commands.rs @@ -186,6 +186,7 @@ pub fn insert_mode(view: &mut View, _count: usize) { // inserts at the end of each selection pub fn append_mode(view: &mut View, _count: usize) { view.state.mode = Mode::Insert; + view.state.restore_cursor = true; // TODO: as transaction let text = &view.state.doc.slice(..); @@ -268,8 +269,20 @@ pub fn open_below(view: &mut View, _count: usize) { // O inserts a new line before each line with a selection pub fn normal_mode(view: &mut View, _count: usize) { - // TODO: if leaving append mode, move cursor back by 1 view.state.mode = Mode::Normal; + + // if leaving append mode, move cursor back by 1 + if view.state.restore_cursor { + let text = &view.state.doc.slice(..); + view.state.selection = view.state.selection.transform(|range| { + Range::new( + range.from(), + graphemes::prev_grapheme_boundary(text, range.to()), + ) + }); + + view.state.restore_cursor = false; + } } // TODO: insert means add text just before cursor, on exit we should be on the last letter.