Remove ui.cursor.primary and hashmap lookups

pull/1154/head
Gokul Soumya 3 years ago
parent 058796c18e
commit 016640f4fb

@ -173,7 +173,6 @@ These scopes are used for theming the editor interface.
| `ui.cursor.insert` | | | `ui.cursor.insert` | |
| `ui.cursor.select` | | | `ui.cursor.select` | |
| `ui.cursor.match` | Matching bracket etc. | | `ui.cursor.match` | Matching bracket etc. |
| `ui.cursor.primary` | Cursor with primary selection |
| `ui.linenr` | | | `ui.linenr` | |
| `ui.linenr.selected` | | | `ui.linenr.selected` | |
| `ui.statusline` | Statusline | | `ui.statusline` | Statusline |

@ -233,24 +233,23 @@ impl EditorView {
} }
.unwrap_or(base_cursor_scope); .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 let primary_selection_scope = theme
.find_scope_index("ui.selection.primary") .find_scope_index("ui.selection.primary")
.unwrap_or(selection_scope); .unwrap_or(selection_scope);
let mut spans: Vec<(usize, std::ops::Range<usize>)> = Vec::new(); let mut spans: Vec<(usize, std::ops::Range<usize>)> = Vec::new();
for (i, range) in selection.iter().enumerate() { for (i, range) in selection.iter().enumerate() {
let (cursor_scope, selection_scope) = if i == primary_idx { let selection_is_primary = i == primary_idx;
(primary_cursor_scope, primary_selection_scope) let selection_scope = if selection_is_primary {
primary_selection_scope
} else { } else {
(cursor_scope, selection_scope) selection_scope
}; };
// Special-case: cursor at end of the rope. // Special-case: cursor at end of the rope.
if range.head == range.anchor && range.head == text.len_chars() { 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)); spans.push((cursor_scope, range.head..range.head + 1));
} }
continue; continue;
@ -261,13 +260,13 @@ impl EditorView {
// Standard case. // Standard case.
let cursor_start = prev_grapheme_boundary(text, range.head); let cursor_start = prev_grapheme_boundary(text, range.head);
spans.push((selection_scope, range.anchor..cursor_start)); spans.push((selection_scope, range.anchor..cursor_start));
if i != primary_idx { if !selection_is_primary {
spans.push((cursor_scope, cursor_start..range.head)); spans.push((cursor_scope, cursor_start..range.head));
} }
} else { } else {
// Reverse case. // Reverse case.
let cursor_end = next_grapheme_boundary(text, range.head); 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((cursor_scope, range.head..cursor_end));
} }
spans.push((selection_scope, cursor_end..range.anchor)); spans.push((selection_scope, cursor_end..range.anchor));

@ -29,9 +29,9 @@ pub const SCRATCH_BUFFER_NAME: &str = "[scratch]";
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Mode { pub enum Mode {
Normal, Normal = 0,
Select, Select = 1,
Insert, Insert = 2,
} }
impl Display for Mode { impl Display for Mode {

@ -22,10 +22,10 @@ use anyhow::Error;
pub use helix_core::diagnostic::Severity; pub use helix_core::diagnostic::Severity;
pub use helix_core::register::Registers; pub use helix_core::register::Registers;
use helix_core::{hashmap, syntax}; use helix_core::syntax;
use helix_core::{Position, Selection}; use helix_core::{Position, Selection};
use serde::Deserialize; use serde::{Deserialize, Deserializer};
fn deserialize_duration_millis<'de, D>(deserializer: D) -> Result<Duration, D::Error> fn deserialize_duration_millis<'de, D>(deserializer: D) -> Result<Duration, D::Error>
where where
@ -107,12 +107,28 @@ pub struct Config {
pub cursor_shape: CursorShapeConfig, pub cursor_shape: CursorShapeConfig,
} }
#[derive(Debug, Clone, PartialEq, Deserialize)] // Cursor shape is read and used on every rendered frame and so needs
#[serde(transparent)] // to be fast. Therefore we avoid a hashmap and use an enum indexed array.
pub struct CursorShapeConfig(HashMap<Mode, CursorKind>); #[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 { impl std::ops::Deref for CursorShapeConfig {
type Target = HashMap<Mode, CursorKind>; type Target = [CursorKind; 3];
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.0 &self.0
@ -121,11 +137,7 @@ impl std::ops::Deref for CursorShapeConfig {
impl Default for CursorShapeConfig { impl Default for CursorShapeConfig {
fn default() -> Self { fn default() -> Self {
Self(hashmap!( Self([CursorKind::Block; 3])
Mode::Insert => CursorKind::Block,
Mode::Normal => CursorKind::Block,
Mode::Select => CursorKind::Block,
))
} }
} }
@ -621,7 +633,7 @@ impl Editor {
let cursorkind = self let cursorkind = self
.config .config
.cursor_shape .cursor_shape
.get(&doc.mode()) .get(doc.mode() as usize)
.copied() .copied()
.unwrap_or_default(); .unwrap_or_default();
(Some(pos), cursorkind) (Some(pos), cursorkind)

Loading…
Cancel
Save