language_settings: Add whitespace_map setting (#37704)

This setting controls which visible characters are used to render
whitespace when the show_whitespace setting is enabled.

Release Notes:

- Added `whitespace_map` setting to control which visible characters are
used to render whitespace when the `show_whitespace` setting is enabled.

---------

Co-authored-by: Nia Espera <nia@zed.dev>
This commit is contained in:
Ilija Tovilo
2025-09-10 18:19:24 +00:00
committed by GitHub
co-authored by Nia Espera
parent 22e31a0d41
commit b28c979aae
3 changed files with 53 additions and 5 deletions
+5
View File
@@ -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
+17 -4
View File
@@ -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,
+31 -1
View File
@@ -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,