From 368995b51f2b0b8574a87ebe04749cb556b4c538 Mon Sep 17 00:00:00 2001 From: JJ Date: Tue, 31 Oct 2023 18:14:55 -0700 Subject: [PATCH] Add rainbow indentation guides ref: https://github.com/helix-editor/helix/issues/4010 ref: https://github.com/helix-editor/helix/pull/4493 Co-authored-by: SoraTenshi --- book/src/configuration.md | 2 ++ helix-term/src/ui/document.rs | 42 ++++++++++++++++++++++++++--------- helix-view/src/editor.rs | 10 +++++++++ helix-view/src/theme.rs | 4 ++++ 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/book/src/configuration.md b/book/src/configuration.md index 9b0ff36a5..b62aab166 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -267,6 +267,7 @@ Options for rendering vertical indent guides. | `render` | Whether to render indent guides | `false` | | `character` | Literal character to use for rendering the indent guide | `│` | | `skip-levels` | Number of indent levels to skip | `0` | +| `rainbow-option` | Enum to set rainbow indentations. Options: `normal`, `dim` and `none`. | `none` | Example: @@ -275,6 +276,7 @@ Example: render = true character = "╎" # Some characters that work well: "▏", "┆", "┊", "⸽" skip-levels = 1 +rainbow-option = "normal" ``` ### `[editor.gutters]` Section diff --git a/helix-term/src/ui/document.rs b/helix-term/src/ui/document.rs index 80da1c542..f406a6f95 100644 --- a/helix-term/src/ui/document.rs +++ b/helix-term/src/ui/document.rs @@ -7,9 +7,9 @@ use helix_core::syntax::Highlight; use helix_core::syntax::HighlightEvent; use helix_core::text_annotations::TextAnnotations; use helix_core::{visual_offset_from_block, Position, RopeSlice}; -use helix_view::editor::{WhitespaceConfig, WhitespaceRenderValue}; +use helix_view::editor::{RainbowIndentOptions, WhitespaceConfig, WhitespaceRenderValue}; use helix_view::graphics::Rect; -use helix_view::theme::Style; +use helix_view::theme::{Modifier, Style}; use helix_view::view::ViewPosition; use helix_view::Document; use helix_view::Theme; @@ -310,6 +310,8 @@ pub struct TextRenderer<'a> { pub whitespace_style: Style, pub indent_guide_char: String, pub indent_guide_style: Style, + pub indent_guide_rainbow: RainbowIndentOptions, + pub theme: &'a Theme, pub newline: String, pub nbsp: String, pub space: String, @@ -326,7 +328,7 @@ impl<'a> TextRenderer<'a> { pub fn new( surface: &'a mut Surface, doc: &Document, - theme: &Theme, + theme: &'a Theme, col_offset: usize, viewport: Rect, ) -> TextRenderer<'a> { @@ -363,12 +365,19 @@ impl<'a> TextRenderer<'a> { }; let text_style = theme.get("ui.text"); + let basic_style = text_style.patch( + theme + .try_get("ui.virtual.indent-guide") + .unwrap_or_else(|| theme.get("ui.virtual.whitespace")), + ); let indent_width = doc.indent_style.indent_width(tab_width) as u16; TextRenderer { surface, indent_guide_char: editor_config.indent_guides.character.into(), + indent_guide_rainbow: editor_config.indent_guides.rainbow_option.clone(), + theme, newline, nbsp, space, @@ -379,11 +388,7 @@ impl<'a> TextRenderer<'a> { starting_indent: col_offset / indent_width as usize + (col_offset % indent_width as usize != 0) as usize + editor_config.indent_guides.skip_levels as usize, - indent_guide_style: text_style.patch( - theme - .try_get("ui.virtual.indent-guide") - .unwrap_or_else(|| theme.get("ui.virtual.whitespace")), - ), + indent_guide_style: basic_style, text_style, draw_indent_guides: editor_config.indent_guides.render, viewport, @@ -477,8 +482,25 @@ impl<'a> TextRenderer<'a> { as u16; let y = self.viewport.y + row; debug_assert!(self.surface.in_bounds(x, y)); - self.surface - .set_string(x, y, &self.indent_guide_char, self.indent_guide_style); + match self.indent_guide_rainbow { + RainbowIndentOptions::None => { + self.surface + .set_string(x, y, &self.indent_guide_char, self.indent_guide_style) + } + RainbowIndentOptions::Dim => { + let new_style = self + .indent_guide_style + .patch(self.theme.get_rainbow(i)) + .add_modifier(Modifier::DIM); + self.surface + .set_string(x, y, &self.indent_guide_char, new_style); + } + RainbowIndentOptions::Normal => { + let new_style = self.indent_guide_style.patch(self.theme.get_rainbow(i)); + self.surface + .set_string(x, y, &self.indent_guide_char, new_style); + } + }; } } } diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index fbfed656d..b2615c9f4 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -764,12 +764,21 @@ impl Default for WhitespaceCharacters { } } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub enum RainbowIndentOptions { + None, + Dim, + Normal, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(default, rename_all = "kebab-case")] pub struct IndentGuidesConfig { pub render: bool, pub character: char, pub skip_levels: u8, + pub rainbow_option: RainbowIndentOptions, } impl Default for IndentGuidesConfig { @@ -778,6 +787,7 @@ impl Default for IndentGuidesConfig { skip_levels: 0, render: false, character: '│', + rainbow_option: RainbowIndentOptions::None, } } } diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs index 16da247f6..8236d370e 100644 --- a/helix-view/src/theme.rs +++ b/helix-view/src/theme.rs @@ -383,6 +383,10 @@ impl Theme { pub fn rainbow_length(&self) -> usize { self.rainbow_length } + + pub fn get_rainbow(&self, index: usize) -> Style { + self.highlights[index % self.rainbow_length] + } } fn default_rainbow() -> Vec