diff --git a/book/src/themes.md b/book/src/themes.md index 80fee3d75a53..2ece249124b3 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -46,48 +46,55 @@ Possible modifiers: Possible keys: -| Key | Notes | -| --- | --- | -| `attribute` | | -| `keyword` | | -| `keyword.directive` | Preprocessor directives (\#if in C) | -| `namespace` | | -| `punctuation` | | -| `punctuation.delimiter` | | -| `operator` | | -| `special` | | -| `property` | | -| `variable` | | -| `variable.parameter` | | -| `type` | | -| `type.builtin` | | -| `constructor` | | -| `function` | | -| `function.macro` | | -| `function.builtin` | | -| `comment` | | -| `variable.builtin` | | -| `constant` | | -| `constant.builtin` | | -| `string` | | -| `number` | | -| `escape` | Escaped characters | -| `label` | For lifetimes | -| `module` | | -| `ui.background` | | -| `ui.linenr` | | -| `ui.statusline` | | -| `ui.popup` | | -| `ui.window` | | -| `ui.help` | | -| `ui.text` | | -| `ui.text.focus` | | -| `ui.menu.selected` | | -| `ui.selection` | For selections in the editing area | -| `warning` | LSP warning | -| `error` | LSP error | -| `info` | LSP info | -| `hint` | LSP hint | +| Key | Notes | +| --- | --- | +| `attribute` | | +| `keyword` | | +| `keyword.directive` | Preprocessor directives (\#if in C) | +| `namespace` | | +| `punctuation` | | +| `punctuation.delimiter` | | +| `operator` | | +| `special` | | +| `property` | | +| `variable` | | +| `variable.parameter` | | +| `type` | | +| `type.builtin` | | +| `constructor` | | +| `function` | | +| `function.macro` | | +| `function.builtin` | | +| `comment` | | +| `variable.builtin` | | +| `constant` | | +| `constant.builtin` | | +| `string` | | +| `number` | | +| `escape` | Escaped characters | +| `label` | For lifetimes | +| `module` | | +| `ui.background` | | +| `ui.cursor` | | +| `ui.cursor.insert` | | +| `ui.cursor.select` | | +| `ui.cursor.match` | Matching bracket etc. | +| `ui.cursor.primary` | Cursor with primary selection | +| `ui.linenr` | | +| `ui.statusline` | | +| `ui.statusline.inactive` | | +| `ui.popup` | | +| `ui.window` | | +| `ui.help` | | +| `ui.text` | | +| `ui.text.focus` | | +| `ui.menu.selected` | | +| `ui.selection` | For selections in the editing area | +| `ui.selection.primary` | | +| `warning` | LSP warning | +| `error` | LSP error | +| `info` | LSP info | +| `hint` | LSP hint | These keys match [tree-sitter scopes](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#theme). We half-follow the common scopes from [macromates language grammars](https://macromates.com/manual/en/language_grammars) with some differences. diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 7f0d06e983a7..c1f23cbbbf47 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -275,21 +275,53 @@ impl EditorView { let end = text.line_to_char(last_line + 1); Range::new(start, end) }; - let cursor_style = Style::default() - // .bg(Color::Rgb(255, 255, 255)) - .add_modifier(Modifier::REVERSED); + + let mode = doc.mode(); + let base_cursor_style = theme + .try_get("ui.cursor") + .unwrap_or_else(|| Style::default().add_modifier(Modifier::REVERSED)); + let cursor_style = match mode { + Mode::Insert => theme.try_get("ui.cursor.insert"), + Mode::Select => theme.try_get("ui.cursor.select"), + Mode::Normal => Some(base_cursor_style), + } + .unwrap_or(base_cursor_style); + let primary_cursor_style = theme + .try_get("ui.cursor.primary") + .map(|style| { + if mode != Mode::Normal { + // we want to make sure that the insert and select highlights + // also affect the primary cursor if set + style.patch(cursor_style) + } else { + style + } + }) + .unwrap_or(cursor_style); let selection_style = theme.get("ui.selection"); + let primary_selection_style = theme + .try_get("ui.selection.primary") + .unwrap_or(selection_style); + + let selection = doc.selection(view.id); + let primary_idx = selection.primary_index(); - for selection in doc - .selection(view.id) + for (i, selection) in selection .iter() - .filter(|range| range.overlaps(&screen)) + .enumerate() + .filter(|(_, range)| range.overlaps(&screen)) { // TODO: render also if only one of the ranges is in viewport let mut start = view.screen_coords_at_pos(doc, text, selection.anchor); let mut end = view.screen_coords_at_pos(doc, text, selection.head); + let (cursor_style, selection_style) = if i == primary_idx { + (primary_cursor_style, primary_selection_style) + } else { + (cursor_style, selection_style) + }; + let head = end; if selection.head < selection.anchor { @@ -382,9 +414,12 @@ impl EditorView { if (pos.col as u16) < viewport.width + view.first_col as u16 && pos.col >= view.first_col { - let style = Style::default() - .add_modifier(Modifier::REVERSED) - .add_modifier(Modifier::DIM); + let style = + theme.try_get("ui.cursor.match").unwrap_or_else(|| { + Style::default() + .add_modifier(Modifier::REVERSED) + .add_modifier(Modifier::DIM) + }); surface .get_mut( diff --git a/theme.toml b/theme.toml index a4f402675d93..6c357ef47d2d 100644 --- a/theme.toml +++ b/theme.toml @@ -52,7 +52,8 @@ "ui.text" = { fg = "#a4a0e8" } # lavender "ui.text.focus" = { fg = "#dbbfef"} # lilac -"ui.selection" = { bg = "#540099" } +"ui.selection" = { bg = "#44258b" } +"ui.selection.primary" = { bg = "#540099" } "ui.menu.selected" = { fg = "#281733", bg = "#ffffff" } # revolver "warning" = "#ffcd1c"