diff --git a/book/src/configuration.md b/book/src/configuration.md index c55426c013d1..09afd0f5c0a8 100644 --- a/book/src/configuration.md +++ b/book/src/configuration.md @@ -255,8 +255,8 @@ Options for rendering whitespace with visible characters. Use `:set whitespace.r | Key | Description | Default | |-----|-------------|---------| -| `render` | Whether to render whitespace. May either be `"all"` or `"none"`, or a table with sub-keys `space`, `nbsp`, `tab`, and `newline` | `"none"` | -| `characters` | Literal characters to use when rendering whitespace. Sub-keys may be any of `tab`, `space`, `nbsp`, `newline` or `tabpad` | See example below | +| `render` | Whether to render whitespace. May either be `"all"` or `"none"`, or a table with sub-keys `space`, `nbsp`, `nnbsp`, `tab`, and `newline` | `"none"` | +| `characters` | Literal characters to use when rendering whitespace. Sub-keys may be any of `tab`, `space`, `nbsp`, `nnbsp`, `newline` or `tabpad` | See example below | Example @@ -270,8 +270,9 @@ tab = "all" newline = "none" [editor.whitespace.characters] -space = "·" +space = "␣" nbsp = "⍽" +nnbsp = "·" tab = "→" newline = "⏎" tabpad = "·" # Tabs will look like "→···" (depending on tab width) diff --git a/helix-term/src/ui/document.rs b/helix-term/src/ui/document.rs index dc61ca2e3b2b..b571b83c2ddd 100644 --- a/helix-term/src/ui/document.rs +++ b/helix-term/src/ui/document.rs @@ -341,6 +341,7 @@ pub struct TextRenderer<'a> { pub indent_guide_style: Style, pub newline: String, pub nbsp: String, + pub nnbsp: String, pub space: String, pub tab: String, pub virtual_tab: String, @@ -395,6 +396,11 @@ impl<'a> TextRenderer<'a> { } else { " ".to_owned() }; + let nnbsp = if ws_render.nnbsp() == WhitespaceRenderValue::All { + ws_chars.nnbsp.into() + } else { + " ".to_owned() + }; let text_style = theme.get("ui.text"); @@ -405,6 +411,7 @@ impl<'a> TextRenderer<'a> { indent_guide_char: editor_config.indent_guides.character.into(), newline, nbsp, + nnbsp, space, tab, virtual_tab, @@ -448,6 +455,7 @@ impl<'a> TextRenderer<'a> { let width = grapheme.width(); let space = if is_virtual { " " } else { &self.space }; let nbsp = if is_virtual { " " } else { &self.nbsp }; + let nnbsp = if is_virtual { " " } else { &self.nnbsp }; let tab = if is_virtual { &self.virtual_tab } else { @@ -461,6 +469,7 @@ impl<'a> TextRenderer<'a> { // TODO special rendering for other whitespaces? Grapheme::Other { ref g } if g == " " => space, Grapheme::Other { ref g } if g == "\u{00A0}" => nbsp, + Grapheme::Other { ref g } if g == "\u{202F}" => nnbsp, Grapheme::Other { ref g } => g, Grapheme::Newline => &self.newline, }; diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 3c530c4e89bf..42915d95c8eb 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -702,6 +702,7 @@ pub enum WhitespaceRender { default: Option, space: Option, nbsp: Option, + nnbsp: Option, tab: Option, newline: Option, }, @@ -733,6 +734,14 @@ impl WhitespaceRender { } } } + pub fn nnbsp(&self) -> WhitespaceRenderValue { + match *self { + Self::Basic(val) => val, + Self::Specific { default, nnbsp, .. } => { + nnbsp.or(default).unwrap_or(WhitespaceRenderValue::None) + } + } + } pub fn tab(&self) -> WhitespaceRenderValue { match *self { Self::Basic(val) => val, @@ -756,6 +765,7 @@ impl WhitespaceRender { pub struct WhitespaceCharacters { pub space: char, pub nbsp: char, + pub nnbsp: char, pub tab: char, pub tabpad: char, pub newline: char, @@ -764,8 +774,9 @@ pub struct WhitespaceCharacters { impl Default for WhitespaceCharacters { fn default() -> Self { Self { - space: '·', // U+00B7 + space: '␣', // U+2423 nbsp: '⍽', // U+237D + nnbsp: '·', // U+00B7 tab: '→', // U+2192 newline: '⏎', // U+23CE tabpad: ' ',