From 7961355ba1c0cd521372496c507a31a51b41ddf2 Mon Sep 17 00:00:00 2001 From: Gokul Soumya Date: Wed, 24 Nov 2021 12:17:41 +0530 Subject: Change cursor shape on mode change Fixes #323. Due to terminal limitations we can only change the shape of the primary cursor. --- helix-term/src/ui/editor.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'helix-term/src/ui') diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 27d33d22..8ad54dbd 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -250,7 +250,9 @@ impl EditorView { // Special-case: cursor at end of the rope. if range.head == range.anchor && range.head == text.len_chars() { - spans.push((cursor_scope, range.head..range.head + 1)); + if i != primary_idx { + spans.push((cursor_scope, range.head..range.head + 1)); + } continue; } @@ -259,11 +261,15 @@ impl EditorView { // Standard case. let cursor_start = prev_grapheme_boundary(text, range.head); spans.push((selection_scope, range.anchor..cursor_start)); - spans.push((cursor_scope, cursor_start..range.head)); + if i != primary_idx { + spans.push((cursor_scope, cursor_start..range.head)); + } } else { // Reverse case. let cursor_end = next_grapheme_boundary(text, range.head); - spans.push((cursor_scope, range.head..cursor_end)); + if i != primary_idx { + spans.push((cursor_scope, range.head..cursor_end)); + } spans.push((selection_scope, cursor_end..range.anchor)); } } -- cgit v1.2.3-70-g09d2 From c08d2fae587a0a5dd2a1e2e44a1f385d142c9d59 Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Tue, 30 Nov 2021 15:40:38 +0800 Subject: Improve dedent behavior, make kill_to_line_end behave like emacs (#1173) * restore indent when press esc right after open a new line * add comment for restore_indent * fix, and make kill to line end behaves like emacs * update comment * fix comment * adjust cancel restore_indent situation * check esc logic in mode transaction * improve comment * add more check for dedent * update comment * use matches to check for last_cmd * no need to introduct CommandFun type--- helix-term/src/commands.rs | 19 +++++++++++++++---- helix-term/src/ui/editor.rs | 13 +++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) (limited to 'helix-term/src/ui') diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index b4cc9ae9..0a2ecf9c 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -173,6 +173,10 @@ impl Command { self.doc } + pub fn fun(&self) -> fn(&mut Context) { + self.fun + } + #[rustfmt::skip] commands!( no_op, "Do nothing", @@ -603,8 +607,15 @@ fn kill_to_line_end(cx: &mut Context) { let selection = doc.selection(view.id).clone().transform(|range| { let line = range.cursor_line(text); - let pos = line_end_char_index(&text, line); - range.put_cursor(text, pos, true) + let line_end_pos = line_end_char_index(&text, line); + let pos = range.cursor(text); + + let mut new_range = range.put_cursor(text, line_end_pos, true); + // don't want to remove the line separator itself if the cursor doesn't reach the end of line. + if pos != line_end_pos { + new_range.head = line_end_pos; + } + new_range }); delete_selection_insert_mode(doc, view, &selection); } @@ -3503,12 +3514,12 @@ fn open(cx: &mut Context, open: Open) { } // o inserts a new line after each line with a selection -fn open_below(cx: &mut Context) { +pub(crate) fn open_below(cx: &mut Context) { open(cx, Open::Below) } // O inserts a new line before each line with a selection -fn open_above(cx: &mut Context) { +pub(crate) fn open_above(cx: &mut Context) { open(cx, Open::Above) } diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 83be816f..c6d0e71f 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -1023,6 +1023,19 @@ impl Component for EditorView { (Mode::Insert, Mode::Normal) => { // if exiting insert mode, remove completion self.completion = None; + + let last_cmd = self.last_insert.0.fun(); + const OPEN_BELOW_FUN: fn(&mut commands::Context) = commands::open_below; + const OPEN_ABOVE_FUN: fn(&mut commands::Context) = commands::open_above; + // For user friendly, + // Remove whitespaces if we go from insert mode(through open below/above) to normal mode without any keys in between. + // Example: `o`. + if matches!(last_cmd, OPEN_BELOW_FUN | OPEN_ABOVE_FUN) + && self.last_insert.1.len() == 1 + { + commands::Command::goto_line_start.execute(&mut cxt); + commands::Command::kill_to_line_end.execute(&mut cxt); + } } _ => (), } -- cgit v1.2.3-70-g09d2 From 7bbf4c5b0675bb794bd88c070472773bd7d7e6bf Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Wed, 1 Dec 2021 12:57:57 +0900 Subject: ui: Only calculate span styling when it's actually in bounds --- helix-term/src/ui/editor.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'helix-term/src/ui') diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index c6d0e71f..6299014c 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -304,17 +304,17 @@ impl EditorView { use helix_core::graphemes::{grapheme_width, RopeGraphemes}; - let style = spans.iter().fold(text_style, |acc, span| { - let style = theme.get(theme.scopes()[span.0].as_str()); - acc.patch(style) - }); - for grapheme in RopeGraphemes::new(text) { let out_of_bounds = visual_x < offset.col as u16 || visual_x >= viewport.width + offset.col as u16; if LineEnding::from_rope_slice(&grapheme).is_some() { if !out_of_bounds { + let style = spans.iter().fold(text_style, |acc, span| { + let style = theme.get(theme.scopes()[span.0].as_str()); + acc.patch(style) + }); + // we still want to render an empty cell with the style surface.set_string( viewport.x + visual_x - offset.col as u16, @@ -345,6 +345,11 @@ impl EditorView { }; if !out_of_bounds { + let style = spans.iter().fold(text_style, |acc, span| { + let style = theme.get(theme.scopes()[span.0].as_str()); + acc.patch(style) + }); + // if we're offscreen just keep going until we hit a new line surface.set_string( viewport.x + visual_x - offset.col as u16, -- cgit v1.2.3-70-g09d2 From 259678585c3410044683bf4d2619b2d024a04514 Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Wed, 1 Dec 2021 13:08:20 +0900 Subject: ui: Optimize tree-sitter style lookups Tree sitter returns an index referring to the position of the scope in the scopes array. We can use that same index to avoid a hashmap lookup and instead store the styles in an array. This currently stores the styles in both a map and an array because the UI still uses hashmap lookups, but it's a reasonable tradeoff. --- helix-term/src/ui/editor.rs | 6 ++---- helix-view/src/theme.rs | 27 +++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 8 deletions(-) (limited to 'helix-term/src/ui') diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 6299014c..a4fbca99 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -311,8 +311,7 @@ impl EditorView { if LineEnding::from_rope_slice(&grapheme).is_some() { if !out_of_bounds { let style = spans.iter().fold(text_style, |acc, span| { - let style = theme.get(theme.scopes()[span.0].as_str()); - acc.patch(style) + acc.patch(theme.highlight(span.0)) }); // we still want to render an empty cell with the style @@ -346,8 +345,7 @@ impl EditorView { if !out_of_bounds { let style = spans.iter().fold(text_style, |acc, span| { - let style = theme.get(theme.scopes()[span.0].as_str()); - acc.patch(style) + acc.patch(theme.highlight(span.0)) }); // if we're offscreen just keep going until we hit a new line diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs index 757316bd..2366ff7d 100644 --- a/helix-view/src/theme.rs +++ b/helix-view/src/theme.rs @@ -78,8 +78,11 @@ impl Loader { #[derive(Clone, Debug)] pub struct Theme { - scopes: Vec, + // UI styles are stored in a HashMap styles: HashMap, + // tree-sitter highlight styles are stored in a Vec to optimize lookups + scopes: Vec, + highlights: Vec