mirror of https://github.com/helix-editor/helix
Remove ui.cursor.primary and hashmap lookups
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…
Reference in New Issue