diff --git a/crates/editor/src/editor_settings_controls.rs b/crates/editor/src/editor_settings_controls.rs index 7de2f6a4ec..7deb85413b 100644 --- a/crates/editor/src/editor_settings_controls.rs +++ b/crates/editor/src/editor_settings_controls.rs @@ -1,4 +1,6 @@ -use gpui::{AppContext, FontWeight}; +use std::sync::Arc; + +use gpui::{AppContext, FontFeatures, FontWeight}; use project::project_settings::{InlineBlameSettings, ProjectSettings}; use settings::{EditableSettingControl, Settings}; use theme::{FontFamilyCache, ThemeSettings}; @@ -28,7 +30,8 @@ impl RenderOnce for EditorSettingsControls { .child(BufferFontFamilyControl) .child(BufferFontWeightControl), ) - .child(BufferFontSizeControl), + .child(BufferFontSizeControl) + .child(BufferFontLigaturesControl), ) .child(SettingsGroup::new("Editor").child(InlineGitBlameControl)) } @@ -190,6 +193,76 @@ impl RenderOnce for BufferFontWeightControl { } } +#[derive(IntoElement)] +struct BufferFontLigaturesControl; + +impl EditableSettingControl for BufferFontLigaturesControl { + type Value = bool; + type Settings = ThemeSettings; + + fn name(&self) -> SharedString { + "Buffer Font Ligatures".into() + } + + fn read(cx: &AppContext) -> Self::Value { + let settings = ThemeSettings::get_global(cx); + settings + .buffer_font + .features + .is_calt_enabled() + .unwrap_or(true) + } + + fn apply( + settings: &mut ::FileContent, + value: Self::Value, + _cx: &AppContext, + ) { + let value = if value { 1 } else { 0 }; + + let mut features = settings + .buffer_font_features + .as_ref() + .map(|features| { + features + .tag_value_list() + .into_iter() + .cloned() + .collect::>() + }) + .unwrap_or_default(); + + if let Some(calt_index) = features.iter().position(|(tag, _)| tag == "calt") { + features[calt_index].1 = value; + } else { + features.push(("calt".into(), value)); + } + + settings.buffer_font_features = Some(FontFeatures(Arc::new(features))); + } +} + +impl RenderOnce for BufferFontLigaturesControl { + fn render(self, cx: &mut WindowContext) -> impl IntoElement { + let value = Self::read(cx); + + CheckboxWithLabel::new( + "buffer-font-ligatures", + Label::new(self.name()), + value.into(), + |selection, cx| { + Self::write( + match selection { + Selection::Selected => true, + Selection::Unselected | Selection::Indeterminate => false, + }, + cx, + ); + }, + ) + } +} + #[derive(IntoElement)] struct InlineGitBlameControl; diff --git a/crates/gpui/src/text_system/font_features.rs b/crates/gpui/src/text_system/font_features.rs index d9da15686c..a24a80e90a 100644 --- a/crates/gpui/src/text_system/font_features.rs +++ b/crates/gpui/src/text_system/font_features.rs @@ -12,6 +12,16 @@ impl FontFeatures { pub fn tag_value_list(&self) -> &[(String, u32)] { &self.0.as_slice() } + + /// Returns whether the `calt` feature is enabled. + /// + /// Returns `None` if the feature is not present. + pub fn is_calt_enabled(&self) -> Option { + self.0 + .iter() + .find(|(feature, _)| feature == "calt") + .map(|(_, value)| *value == 1) + } } impl std::fmt::Debug for FontFeatures { diff --git a/crates/settings_ui/src/appearance_settings_controls.rs b/crates/settings_ui/src/appearance_settings_controls.rs index e1e375a9f3..1947c8be0a 100644 --- a/crates/settings_ui/src/appearance_settings_controls.rs +++ b/crates/settings_ui/src/appearance_settings_controls.rs @@ -1,9 +1,11 @@ -use gpui::{AppContext, FontWeight}; +use std::sync::Arc; + +use gpui::{AppContext, FontFeatures, FontWeight}; use settings::{EditableSettingControl, Settings}; use theme::{FontFamilyCache, SystemAppearance, ThemeMode, ThemeRegistry, ThemeSettings}; use ui::{ - prelude::*, ContextMenu, DropdownMenu, NumericStepper, SettingsContainer, SettingsGroup, - ToggleButton, + prelude::*, CheckboxWithLabel, ContextMenu, DropdownMenu, NumericStepper, SettingsContainer, + SettingsGroup, ToggleButton, }; #[derive(IntoElement)] @@ -36,7 +38,8 @@ impl RenderOnce for AppearanceSettingsControls { .child(UiFontFamilyControl) .child(UiFontWeightControl), ) - .child(UiFontSizeControl), + .child(UiFontSizeControl) + .child(UiFontLigaturesControl), ) } } @@ -320,3 +323,69 @@ impl RenderOnce for UiFontWeightControl { )) } } + +#[derive(IntoElement)] +struct UiFontLigaturesControl; + +impl EditableSettingControl for UiFontLigaturesControl { + type Value = bool; + type Settings = ThemeSettings; + + fn name(&self) -> SharedString { + "UI Font Ligatures".into() + } + + fn read(cx: &AppContext) -> Self::Value { + let settings = ThemeSettings::get_global(cx); + settings.ui_font.features.is_calt_enabled().unwrap_or(true) + } + + fn apply( + settings: &mut ::FileContent, + value: Self::Value, + _cx: &AppContext, + ) { + let value = if value { 1 } else { 0 }; + + let mut features = settings + .ui_font_features + .as_ref() + .map(|features| { + features + .tag_value_list() + .into_iter() + .cloned() + .collect::>() + }) + .unwrap_or_default(); + + if let Some(calt_index) = features.iter().position(|(tag, _)| tag == "calt") { + features[calt_index].1 = value; + } else { + features.push(("calt".into(), value)); + } + + settings.ui_font_features = Some(FontFeatures(Arc::new(features))); + } +} + +impl RenderOnce for UiFontLigaturesControl { + fn render(self, cx: &mut WindowContext) -> impl IntoElement { + let value = Self::read(cx); + + CheckboxWithLabel::new( + "ui-font-ligatures", + Label::new(self.name()), + value.into(), + |selection, cx| { + Self::write( + match selection { + Selection::Selected => true, + Selection::Unselected | Selection::Indeterminate => false, + }, + cx, + ); + }, + ) + } +}