@@ -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
@@ -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,
@@ -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<String>,
/// 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<ShowWhitespaceSetting>,
+ /// Visible characters used to render whitespace when show_whitespaces is enabled.
+ ///
+ /// Default: "•" for spaces, "→" for tabs.
+ #[serde(default)]
+ pub whitespace_map: Option<WhitespaceMap>,
/// 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<String>,
+ #[serde(default)]
+ pub tab: Option<String>,
+}
+
+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,