diff --git a/assets/settings/default.json b/assets/settings/default.json index 1902aa5e87c79f1894e485fa79d1435f2a3aee8f..94df7a62ccf503081f62848c57e421f939cc64ec 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -362,6 +362,11 @@ // - It is adjacent to an edge (start or end) // - It is adjacent to a whitespace (left or right) "show_whitespaces": "selection", + // Visible characters used to render whitespace when show_whitespaces is enabled. + "whitespace_map": { + "space": "•", + "tab": "→" + }, // Settings related to calls in Zed "calls": { // Join calls with the microphone live by default diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index ff7816afe1504fea31c8fbb342b72b72bcafdd5e..673557a2c653311cc5f1c36b21c9937f146d79c1 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -9259,11 +9259,21 @@ impl Element for EditorElement { }); let invisible_symbol_font_size = font_size / 2.; + let whitespace_map = &self + .editor + .read(cx) + .buffer + .read(cx) + .language_settings(cx) + .whitespace_map; + + let tab_char = whitespace_map.tab(); + let tab_len = tab_char.len(); let tab_invisible = window.text_system().shape_line( - "→".into(), + tab_char, invisible_symbol_font_size, &[TextRun { - len: "→".len(), + len: tab_len, font: self.style.text.font(), color: cx.theme().colors().editor_invisible, background_color: None, @@ -9272,11 +9282,14 @@ impl Element for EditorElement { }], None, ); + + let space_char = whitespace_map.space(); + let space_len = space_char.len(); let space_invisible = window.text_system().shape_line( - "•".into(), + space_char, invisible_symbol_font_size, &[TextRun { - len: "•".len(), + len: space_len, font: self.style.text.font(), color: cx.theme().colors().editor_invisible, background_color: None, diff --git a/crates/language/src/language_settings.rs b/crates/language/src/language_settings.rs index 33dd6208a8aa3ce778f6336b1d1189275452dbe2..cb193960aef4c5dcb3cd0f015e23da895651b4f8 100644 --- a/crates/language/src/language_settings.rs +++ b/crates/language/src/language_settings.rs @@ -8,7 +8,7 @@ use ec4rs::{ property::{FinalNewline, IndentSize, IndentStyle, MaxLineLen, TabWidth, TrimTrailingWs}, }; use globset::{Glob, GlobMatcher, GlobSet, GlobSetBuilder}; -use gpui::{App, Modifiers}; +use gpui::{App, Modifiers, SharedString}; use itertools::{Either, Itertools}; use schemars::{JsonSchema, json_schema}; use serde::{ @@ -123,6 +123,8 @@ pub struct LanguageSettings { pub edit_predictions_disabled_in: Vec, /// Whether to show tabs and spaces in the editor. pub show_whitespaces: ShowWhitespaceSetting, + /// Visible characters used to render whitespace when show_whitespaces is enabled. + pub whitespace_map: WhitespaceMap, /// Whether to start a new line with a comment when a previous line is a comment as well. pub extend_comment_on_newline: bool, /// Inlay hint related settings. @@ -578,6 +580,11 @@ pub struct LanguageSettingsContent { /// Whether to show tabs and spaces in the editor. #[serde(default)] pub show_whitespaces: Option, + /// Visible characters used to render whitespace when show_whitespaces is enabled. + /// + /// Default: "•" for spaces, "→" for tabs. + #[serde(default)] + pub whitespace_map: Option, /// Whether to start a new line with a comment when a previous line is a comment as well. /// /// Default: true @@ -855,6 +862,28 @@ pub enum ShowWhitespaceSetting { Trailing, } +#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema, PartialEq, SettingsUi)] +pub struct WhitespaceMap { + #[serde(default)] + pub space: Option, + #[serde(default)] + pub tab: Option, +} + +impl WhitespaceMap { + pub fn space(&self) -> SharedString { + self.space + .as_ref() + .map_or_else(|| SharedString::from("•"), |s| SharedString::from(s)) + } + + pub fn tab(&self) -> SharedString { + self.tab + .as_ref() + .map_or_else(|| SharedString::from("→"), |s| SharedString::from(s)) + } +} + /// Controls which formatter should be used when formatting code. #[derive(Clone, Debug, Default, PartialEq, Eq, SettingsUi)] pub enum SelectedFormatter { @@ -1643,6 +1672,7 @@ fn merge_settings(settings: &mut LanguageSettings, src: &LanguageSettingsContent src.edit_predictions_disabled_in.clone(), ); merge(&mut settings.show_whitespaces, src.show_whitespaces); + merge(&mut settings.whitespace_map, src.whitespace_map.clone()); merge( &mut settings.extend_comment_on_newline, src.extend_comment_on_newline,