summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--book/src/themes.md1
-rw-r--r--helix-term/src/ui/editor.rs17
-rw-r--r--helix-view/src/document.rs6
-rw-r--r--helix-view/src/editor.rs36
4 files changed, 35 insertions, 25 deletions
diff --git a/book/src/themes.md b/book/src/themes.md
index ecbbb6e9..6b38fb43 100644
--- a/book/src/themes.md
+++ b/book/src/themes.md
@@ -173,7 +173,6 @@ These scopes are used for theming the editor interface.
| `ui.cursor.insert` | |
| `ui.cursor.select` | |
| `ui.cursor.match` | Matching bracket etc. |
-| `ui.cursor.primary` | Cursor with primary selection |
| `ui.linenr` | |
| `ui.linenr.selected` | |
| `ui.statusline` | Statusline |
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index 8ad54dbd..e8f8fd9b 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -233,24 +233,23 @@ impl EditorView {
}
.unwrap_or(base_cursor_scope);
- let primary_cursor_scope = theme
- .find_scope_index("ui.cursor.primary")
- .unwrap_or(cursor_scope);
let primary_selection_scope = theme
.find_scope_index("ui.selection.primary")
.unwrap_or(selection_scope);
let mut spans: Vec<(usize, std::ops::Range<usize>)> = Vec::new();
for (i, range) in selection.iter().enumerate() {
- let (cursor_scope, selection_scope) = if i == primary_idx {
- (primary_cursor_scope, primary_selection_scope)
+ let selection_is_primary = i == primary_idx;
+ let selection_scope = if selection_is_primary {
+ primary_selection_scope
} else {
- (cursor_scope, selection_scope)
+ selection_scope
};
// Special-case: cursor at end of the rope.
if range.head == range.anchor && range.head == text.len_chars() {
- if i != primary_idx {
+ if !selection_is_primary {
+ // Terminal cursor acts as the primary cursor
spans.push((cursor_scope, range.head..range.head + 1));
}
continue;
@@ -261,13 +260,13 @@ impl EditorView {
// Standard case.
let cursor_start = prev_grapheme_boundary(text, range.head);
spans.push((selection_scope, range.anchor..cursor_start));
- if i != primary_idx {
+ if !selection_is_primary {
spans.push((cursor_scope, cursor_start..range.head));
}
} else {
// Reverse case.
let cursor_end = next_grapheme_boundary(text, range.head);
- if i != primary_idx {
+ if !selection_is_primary {
spans.push((cursor_scope, range.head..cursor_end));
}
spans.push((selection_scope, cursor_end..range.anchor));
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index 76b19a07..01975452 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -29,9 +29,9 @@ pub const SCRATCH_BUFFER_NAME: &str = "[scratch]";
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Mode {
- Normal,
- Select,
- Insert,
+ Normal = 0,
+ Select = 1,
+ Insert = 2,
}
impl Display for Mode {
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index b558c183..a121a836 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -22,10 +22,10 @@ use anyhow::Error;
pub use helix_core::diagnostic::Severity;
pub use helix_core::register::Registers;
-use helix_core::{hashmap, syntax};
+use helix_core::syntax;
use helix_core::{Position, Selection};
-use serde::Deserialize;
+use serde::{Deserialize, Deserializer};
fn deserialize_duration_millis<'de, D>(deserializer: D) -> Result<Duration, D::Error>
where
@@ -107,12 +107,28 @@ pub struct Config {
pub cursor_shape: CursorShapeConfig,
}
-#[derive(Debug, Clone, PartialEq, Deserialize)]
-#[serde(transparent)]
-pub struct CursorShapeConfig(HashMap<Mode, CursorKind>);
+// Cursor shape is read and used on every rendered frame and so needs
+// to be fast. Therefore we avoid a hashmap and use an enum indexed array.
+#[derive(Debug, Clone, PartialEq)]
+pub struct CursorShapeConfig([CursorKind; 3]);
+
+impl<'de> Deserialize<'de> for CursorShapeConfig {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ let m = HashMap::<Mode, CursorKind>::deserialize(deserializer)?;
+ let into_cursor = |mode: Mode| m.get(&mode).copied().unwrap_or_default();
+ Ok(CursorShapeConfig([
+ into_cursor(Mode::Normal),
+ into_cursor(Mode::Select),
+ into_cursor(Mode::Insert),
+ ]))
+ }
+}
impl std::ops::Deref for CursorShapeConfig {
- type Target = HashMap<Mode, CursorKind>;
+ type Target = [CursorKind; 3];
fn deref(&self) -> &Self::Target {
&self.0
@@ -121,11 +137,7 @@ impl std::ops::Deref for CursorShapeConfig {
impl Default for CursorShapeConfig {
fn default() -> Self {
- Self(hashmap!(
- Mode::Insert => CursorKind::Block,
- Mode::Normal => CursorKind::Block,
- Mode::Select => CursorKind::Block,
- ))
+ Self([CursorKind::Block; 3])
}
}
@@ -621,7 +633,7 @@ impl Editor {
let cursorkind = self
.config
.cursor_shape
- .get(&doc.mode())
+ .get(doc.mode() as usize)
.copied()
.unwrap_or_default();
(Some(pos), cursorkind)