From ef839cc207eb8d29158497342b00fc335fc7c59e Mon Sep 17 00:00:00 2001 From: John Tur Date: Wed, 8 Oct 2025 19:19:48 -0400 Subject: [PATCH] Improve importing font-family settings from VS Code (#39736) Closes https://github.com/zed-industries/zed/issues/39259 - Fixes import of `editor.fontFamily` (we were looking for the wrong key) - Adds basic support for the CSS font-family syntax used by VS Code, including font fallback Release Notes: - N/A --- crates/settings/src/settings_file.rs | 4 +- crates/settings/src/settings_store.rs | 47 ++++++++++++++++++++++ crates/settings/src/vscode_import.rs | 51 ++++++++++++++++++++++++ crates/terminal/src/terminal_settings.rs | 8 ++-- crates/theme/src/settings.rs | 8 ++-- 5 files changed, 110 insertions(+), 8 deletions(-) diff --git a/crates/settings/src/settings_file.rs b/crates/settings/src/settings_file.rs index b4038aa9168e6f49a49726ade197ec926385ac31..df6aa8bbb4de45ae8b3f037396ed38faf20a0873 100644 --- a/crates/settings/src/settings_file.rs +++ b/crates/settings/src/settings_file.rs @@ -22,7 +22,7 @@ pub fn test_settings() -> String { "buffer_font_family": "Courier", "buffer_font_features": {}, "buffer_font_size": 14, - "buffer_font_fallback": [], + "buffer_font_fallbacks": [], "theme": EMPTY_THEME_NAME, }), &mut value, @@ -37,7 +37,7 @@ pub fn test_settings() -> String { "buffer_font_family": "Courier New", "buffer_font_features": {}, "buffer_font_size": 14, - "buffer_font_fallback": [], + "buffer_font_fallbacks": [], "theme": EMPTY_THEME_NAME, }), &mut value, diff --git a/crates/settings/src/settings_store.rs b/crates/settings/src/settings_store.rs index 79ba18fc0aaf7cb7e54673749f5105d679c86a6c..33ad826482a21c61e83beaa06c723b0caf5b519a 100644 --- a/crates/settings/src/settings_store.rs +++ b/crates/settings/src/settings_store.rs @@ -1201,6 +1201,32 @@ mod tests { } } + #[derive(Debug, PartialEq)] + struct ThemeSettings { + buffer_font_family: FontFamilyName, + buffer_font_fallbacks: Vec, + } + + impl Settings for ThemeSettings { + fn from_settings(content: &SettingsContent) -> Self { + let content = content.theme.clone(); + ThemeSettings { + buffer_font_family: content.buffer_font_family.unwrap(), + buffer_font_fallbacks: content.buffer_font_fallbacks.unwrap(), + } + } + + fn import_from_vscode(vscode: &VsCodeSettings, content: &mut SettingsContent) { + let content = &mut content.theme; + + vscode.font_family_setting( + "editor.fontFamily", + &mut content.buffer_font_family, + &mut content.buffer_font_fallbacks, + ); + } + } + #[gpui::test] fn test_settings_store_basic(cx: &mut App) { let mut store = SettingsStore::new(cx, &default_settings()); @@ -1523,6 +1549,7 @@ mod tests { store.register_setting::(); store.register_setting::(); store.register_setting::(); + store.register_setting::(); // create settings that werent present check_vscode_import( @@ -1594,6 +1621,26 @@ mod tests { .unindent(), cx, ); + + // font-family + check_vscode_import( + &mut store, + r#"{ + } + "# + .unindent(), + r#"{ "editor.fontFamily": "Cascadia Code, 'Consolas', Courier New" }"#.to_owned(), + r#"{ + "buffer_font_fallbacks": [ + "Consolas", + "Courier New" + ], + "buffer_font_family": "Cascadia Code" + } + "# + .unindent(), + cx, + ); } #[track_caller] diff --git a/crates/settings/src/vscode_import.rs b/crates/settings/src/vscode_import.rs index f7ef48b0d536fc1245b8648e357f32eaf85cb3ad..c0c1085684b448dbd3d4ef83faabf21ca1cfbf7f 100644 --- a/crates/settings/src/vscode_import.rs +++ b/crates/settings/src/vscode_import.rs @@ -4,6 +4,8 @@ use paths::{cursor_settings_file_paths, vscode_settings_file_paths}; use serde_json::{Map, Value}; use std::{path::Path, sync::Arc}; +use crate::FontFamilyName; + #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum VsCodeSettingsSource { VsCode, @@ -145,4 +147,53 @@ impl VsCodeSettings { pub fn read_enum(&self, key: &str, f: impl FnOnce(&str) -> Option) -> Option { self.content.get(key).and_then(Value::as_str).and_then(f) } + + pub fn font_family_setting( + &self, + key: &str, + font_family: &mut Option, + font_fallbacks: &mut Option>, + ) { + let Some(css_name) = self.content.get(key).and_then(Value::as_str) else { + return; + }; + + let mut name_buffer = String::new(); + let mut quote_char: Option = None; + let mut fonts = Vec::new(); + let mut add_font = |buffer: &mut String| { + let trimmed = buffer.trim(); + if !trimmed.is_empty() { + fonts.push(trimmed.to_string().into()); + } + + buffer.clear(); + }; + + for ch in css_name.chars() { + match (ch, quote_char) { + ('"' | '\'', None) => { + quote_char = Some(ch); + } + (_, Some(q)) if ch == q => { + quote_char = None; + } + (',', None) => { + add_font(&mut name_buffer); + } + _ => { + name_buffer.push(ch); + } + } + } + + add_font(&mut name_buffer); + + let mut iter = fonts.into_iter(); + *font_family = iter.next(); + let fallbacks: Vec<_> = iter.collect(); + if !fallbacks.is_empty() { + *font_fallbacks = Some(fallbacks); + } + } } diff --git a/crates/terminal/src/terminal_settings.rs b/crates/terminal/src/terminal_settings.rs index 4386720cb9d38a8de31853630a26f391cc1b7797..cc5dbc13ad80628bca355d3e85f860ef45177ed3 100644 --- a/crates/terminal/src/terminal_settings.rs +++ b/crates/terminal/src/terminal_settings.rs @@ -123,9 +123,11 @@ impl settings::Settings for TerminalSettings { let name = |s| format!("terminal.integrated.{s}"); vscode.f32_setting(&name("fontSize"), &mut current.font_size); - if let Some(font_family) = vscode.read_string(&name("fontFamily")) { - current.font_family = Some(FontFamilyName(font_family.into())); - } + vscode.font_family_setting( + &name("fontFamily"), + &mut current.font_family, + &mut current.font_fallbacks, + ); vscode.bool_setting(&name("copyOnSelection"), &mut current.copy_on_select); vscode.bool_setting("macOptionIsMeta", &mut current.option_as_meta); vscode.usize_setting("scrollback", &mut current.max_scroll_history_lines); diff --git a/crates/theme/src/settings.rs b/crates/theme/src/settings.rs index 9ec72b3dde11de7f18fe3e44e5325ca629d5351f..9f753d5a034466631d2324e52fbad7bd858e8c5c 100644 --- a/crates/theme/src/settings.rs +++ b/crates/theme/src/settings.rs @@ -731,9 +731,11 @@ impl settings::Settings for ThemeSettings { fn import_from_vscode(vscode: &settings::VsCodeSettings, current: &mut SettingsContent) { vscode.from_f32_setting("editor.fontWeight", &mut current.theme.buffer_font_weight); vscode.from_f32_setting("editor.fontSize", &mut current.theme.buffer_font_size); - if let Some(font) = vscode.read_string("editor.font") { - current.theme.buffer_font_family = Some(FontFamilyName(font.into())); - } + vscode.font_family_setting( + "editor.fontFamily", + &mut current.theme.buffer_font_family, + &mut current.theme.buffer_font_fallbacks, + ) // TODO: possibly map editor.fontLigatures to buffer_font_features? } }