diff --git a/book/src/configuration.md b/book/src/configuration.md index 253a07269d18..ecc21ec71ec4 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -256,11 +256,12 @@ tabpad = "·" # Tabs will look like "→···" (depending on tab width) Options for rendering vertical indent guides. -| Key | Description | Default | -| --- | --- | --- | -| `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` | +| Key | Description | Default | +| --- | --- | --- | +| `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: @@ -269,6 +270,7 @@ Example: render = true character = "╎" # Some characters that work well: "▏", "┆", "┊", "⸽" skip-levels = 1 +rainbow-option = "normal" ``` ### `[editor.gutters]` Section diff --git a/book/src/themes.md b/book/src/themes.md index 56d0372ca888..c2e3909b10fa 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -136,6 +136,17 @@ inherits = "boo_berry" berry = "#2A2A4D" ``` +### Rainbow + +The `rainbow` key is used for rainbow highlight for matching brackets. +The key is a list of styles. + +```toml +rainbow = ["#ff0000", "#ffa500", "#fff000", { fg = "#00ff00", modifiers = ["bold"] }] +``` + +Colors from the palette and modifiers may be used. + ### Scopes The following is a list of scopes available to use for styling: diff --git a/helix-term/src/ui/document.rs b/helix-term/src/ui/document.rs index 80da1c5427b7..f406a6f9575e 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 1f27603c9011..7557d788ff2b 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -698,12 +698,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 { @@ -712,6 +721,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 a8cc59260291..df7b7f2ab5b6 100644 --- a/helix-view/src/theme.rs +++ b/helix-view/src/theme.rs @@ -216,17 +216,19 @@ pub struct Theme { // tree-sitter highlight styles are stored in a Vec to optimize lookups scopes: Vec, highlights: Vec