From 6e1b9d8b2502f5b47dc28eb5e0853e46ad8b4e84 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Mon, 21 Dec 2020 02:44:38 +0000 Subject: Replace serde's derive with custom proc macro This replaces the existing `Deserialize` derive from serde with a `ConfigDeserialize` derive. The goal of this new proc macro is to allow a more error-friendly deserialization for the Alacritty configuration file without having to manage a lot of boilerplate code inside the configuration modules. The first part of the derive macro is for struct deserialization. This takes structs which have `Default` implemented and will only replace fields which can be successfully deserialized. Otherwise the `log` crate is used for printing errors. Since this deserialization takes the default value from the struct instead of the value, it removes the necessity for creating new types just to implement `Default` on them for deserialization. Additionally, the struct deserialization also checks for `Option` values and makes sure that explicitly specifying `none` as text literal is allowed for all options. The other part of the derive macro is responsible for deserializing enums. While only enums with Unit variants are supported, it will automatically implement a deserializer for these enums which accepts any form of capitalization. Since this custom derive prevents us from using serde's attributes on fields, some of the attributes have been reimplemented for `ConfigDeserialize`. These include `#[config(flatten)]`, `#[config(skip)]` and `#[config(alias = "alias)]`. The flatten attribute is currently limited to at most one per struct. Additionally the `#[config(deprecated = "optional message")]` attribute allows easily defining uniform deprecation messages for fields on structs. --- alacritty/Cargo.toml | 6 +- alacritty/src/cli.rs | 30 +++--- alacritty/src/config/bindings.rs | 18 ++-- alacritty/src/config/debug.rs | 41 +------- alacritty/src/config/font.rs | 153 ++++++++--------------------- alacritty/src/config/mod.rs | 56 +---------- alacritty/src/config/mouse.rs | 71 ++------------ alacritty/src/config/ui_config.rs | 129 ++++++++++--------------- alacritty/src/config/window.rs | 198 ++++++++++++++++++-------------------- alacritty/src/cursor.rs | 4 +- alacritty/src/display.rs | 16 ++- alacritty/src/event.rs | 21 ++-- alacritty/src/input.rs | 41 +++----- alacritty/src/logging.rs | 2 +- alacritty/src/main.rs | 2 +- alacritty/src/renderer/mod.rs | 24 ++--- alacritty/src/wayland_theme.rs | 6 +- alacritty/src/window.rs | 9 +- 18 files changed, 282 insertions(+), 545 deletions(-) (limited to 'alacritty') diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index b5ebefe2..6e833f34 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -13,9 +13,13 @@ path = "../alacritty_terminal" version = "0.11.1-dev" default-features = false +[dependencies.alacritty_config_derive] +path = "../alacritty_config_derive" +version = "0.1.0" + [dependencies] clap = "2" -log = { version = "0.4", features = ["std"] } +log = { version = "0.4", features = ["std", "serde"] } time = "0.1.40" fnv = "1" serde = { version = "1", features = ["derive"] } diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index cacffcdc..6dea3319 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -230,13 +230,17 @@ impl Options { config.hold = self.hold; - let dynamic_title = config.ui_config.dynamic_title() && self.title.is_none(); - config.ui_config.set_dynamic_title(dynamic_title); - - replace_if_some(&mut config.ui_config.window.title, self.title.clone()); - replace_if_some(&mut config.ui_config.window.class.instance, self.class_instance.clone()); - replace_if_some(&mut config.ui_config.window.class.general, self.class_general.clone()); + if let Some(title) = self.title.clone() { + config.ui_config.window.title = title + } + if let Some(class_instance) = self.class_instance.clone() { + config.ui_config.window.class.instance = class_instance; + } + if let Some(class_general) = self.class_general.clone() { + config.ui_config.window.class.general = class_general; + } + config.ui_config.window.dynamic_title &= self.title.is_none(); config.ui_config.window.embed = self.embed.as_ref().and_then(|embed| embed.parse().ok()); config.ui_config.debug.print_events |= self.print_events; config.ui_config.debug.log_level = max(config.ui_config.debug.log_level, self.log_level); @@ -249,12 +253,6 @@ impl Options { } } -fn replace_if_some(option: &mut T, value: Option) { - if let Some(value) = value { - *option = value; - } -} - /// Format an option in the format of `parent.field=value` to a serde Value. fn option_as_value(option: &str) -> Result { let mut yaml_text = String::with_capacity(option.len()); @@ -289,11 +287,11 @@ mod tests { #[test] fn dynamic_title_ignoring_options_by_default() { let mut config = Config::default(); - let old_dynamic_title = config.ui_config.dynamic_title(); + let old_dynamic_title = config.ui_config.window.dynamic_title; Options::default().override_config(&mut config); - assert_eq!(old_dynamic_title, config.ui_config.dynamic_title()); + assert_eq!(old_dynamic_title, config.ui_config.window.dynamic_title); } #[test] @@ -304,7 +302,7 @@ mod tests { options.title = Some("foo".to_owned()); options.override_config(&mut config); - assert!(!config.ui_config.dynamic_title()); + assert!(!config.ui_config.window.dynamic_title); } #[test] @@ -314,7 +312,7 @@ mod tests { config.ui_config.window.title = "foo".to_owned(); Options::default().override_config(&mut config); - assert!(config.ui_config.dynamic_title()); + assert!(config.ui_config.window.dynamic_title); } #[test] diff --git a/alacritty/src/config/bindings.rs b/alacritty/src/config/bindings.rs index 80900733..9babd7f0 100644 --- a/alacritty/src/config/bindings.rs +++ b/alacritty/src/config/bindings.rs @@ -10,6 +10,8 @@ use serde::de::{self, MapAccess, Unexpected, Visitor}; use serde::{Deserialize, Deserializer}; use serde_yaml::Value as SerdeValue; +use alacritty_config_derive::ConfigDeserialize; + use alacritty_terminal::config::Program; use alacritty_terminal::term::TermMode; use alacritty_terminal::vi_mode::ViMotion; @@ -79,26 +81,26 @@ impl Binding { } } -#[derive(Debug, Clone, PartialEq, Eq, Deserialize)] +#[derive(ConfigDeserialize, Debug, Clone, PartialEq, Eq)] pub enum Action { /// Write an escape sequence. - #[serde(skip)] + #[config(skip)] Esc(String), /// Run given command. - #[serde(skip)] + #[config(skip)] Command(Program), /// Move vi mode cursor. - #[serde(skip)] + #[config(skip)] ViMotion(ViMotion), /// Perform vi mode action. - #[serde(skip)] + #[config(skip)] ViAction(ViAction), /// Perform search mode action. - #[serde(skip)] + #[config(skip)] SearchAction(SearchAction), /// Paste contents of system clipboard. @@ -227,7 +229,7 @@ impl Display for Action { } /// Vi mode specific actions. -#[derive(Deserialize, Debug, Copy, Clone, PartialEq, Eq)] +#[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)] pub enum ViAction { /// Toggle normal vi selection. ToggleNormalSelection, @@ -912,7 +914,7 @@ impl<'a> Deserialize<'a> for RawBinding { where E: de::Error, { - match value { + match value.to_ascii_lowercase().as_str() { "key" => Ok(Field::Key), "mods" => Ok(Field::Mods), "mode" => Ok(Field::Mode), diff --git a/alacritty/src/config/debug.rs b/alacritty/src/config/debug.rs index 62de0500..f52cdf90 100644 --- a/alacritty/src/config/debug.rs +++ b/alacritty/src/config/debug.rs @@ -1,35 +1,29 @@ -use log::{error, LevelFilter}; -use serde::{Deserialize, Deserializer}; +use log::LevelFilter; -use alacritty_terminal::config::{failure_default, LOG_TARGET_CONFIG}; +use alacritty_config_derive::ConfigDeserialize; /// Debugging options. -#[serde(default)] -#[derive(Deserialize, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(ConfigDeserialize, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub struct Debug { - #[serde(default = "default_log_level", deserialize_with = "deserialize_log_level")] pub log_level: LevelFilter, - #[serde(deserialize_with = "failure_default")] pub print_events: bool, /// Keep the log file after quitting. - #[serde(deserialize_with = "failure_default")] pub persistent_logging: bool, /// Should show render timer. - #[serde(deserialize_with = "failure_default")] pub render_timer: bool, /// Record ref test. - #[serde(skip)] + #[config(skip)] pub ref_test: bool, } impl Default for Debug { fn default() -> Self { Self { - log_level: default_log_level(), + log_level: LevelFilter::Warn, print_events: Default::default(), persistent_logging: Default::default(), render_timer: Default::default(), @@ -37,28 +31,3 @@ impl Default for Debug { } } } - -fn default_log_level() -> LevelFilter { - LevelFilter::Warn -} - -fn deserialize_log_level<'a, D>(deserializer: D) -> Result -where - D: Deserializer<'a>, -{ - Ok(match failure_default::(deserializer)?.to_lowercase().as_str() { - "off" | "none" => LevelFilter::Off, - "error" => LevelFilter::Error, - "warn" => LevelFilter::Warn, - "info" => LevelFilter::Info, - "debug" => LevelFilter::Debug, - "trace" => LevelFilter::Trace, - level => { - error!( - target: LOG_TARGET_CONFIG, - "Problem with config: invalid log level {}; using level Warn", level - ); - default_log_level() - }, - }) -} diff --git a/alacritty/src/config/font.rs b/alacritty/src/config/font.rs index 9982352f..3dc11671 100644 --- a/alacritty/src/config/font.rs +++ b/alacritty/src/config/font.rs @@ -1,14 +1,11 @@ use std::fmt; -use crossfont::Size; -use log::error; -use serde::de::Visitor; +use crossfont::Size as FontSize; +use serde::de::{self, Visitor}; use serde::{Deserialize, Deserializer}; -use alacritty_terminal::config::{failure_default, LOG_TARGET_CONFIG}; +use alacritty_config_derive::ConfigDeserialize; -#[cfg(target_os = "macos")] -use crate::config::ui_config::DefaultTrueBool; use crate::config::ui_config::Delta; /// Font config. @@ -17,62 +14,41 @@ use crate::config::ui_config::Delta; /// field in this struct. It might be nice in the future to have defaults for /// each value independently. Alternatively, maybe erroring when the user /// doesn't provide complete config is Ok. -#[serde(default)] -#[derive(Debug, Deserialize, Clone, PartialEq, Eq)] +#[derive(ConfigDeserialize, Default, Debug, Clone, PartialEq, Eq)] pub struct Font { + /// Extra spacing per character. + pub offset: Delta, + + /// Glyph offset within character cell. + pub glyph_offset: Delta, + + pub use_thin_strokes: bool, + /// Normal font face. - #[serde(deserialize_with = "failure_default")] normal: FontDescription, /// Bold font face. - #[serde(deserialize_with = "failure_default")] bold: SecondaryFontDescription, /// Italic font face. - #[serde(deserialize_with = "failure_default")] italic: SecondaryFontDescription, /// Bold italic font face. - #[serde(deserialize_with = "failure_default")] bold_italic: SecondaryFontDescription, /// Font size in points. - #[serde(deserialize_with = "DeserializeSize::deserialize")] - pub size: Size, - - /// Extra spacing per character. - #[serde(deserialize_with = "failure_default")] - pub offset: Delta, - - /// Glyph offset within character cell. - #[serde(deserialize_with = "failure_default")] - pub glyph_offset: Delta, - - #[cfg(target_os = "macos")] - #[serde(deserialize_with = "failure_default")] - use_thin_strokes: DefaultTrueBool, -} - -impl Default for Font { - fn default() -> Font { - Font { - size: default_font_size(), - normal: Default::default(), - bold: Default::default(), - italic: Default::default(), - bold_italic: Default::default(), - glyph_offset: Default::default(), - offset: Default::default(), - #[cfg(target_os = "macos")] - use_thin_strokes: Default::default(), - } - } + size: Size, } impl Font { /// Get a font clone with a size modification. - pub fn with_size(self, size: Size) -> Font { - Font { size, ..self } + pub fn with_size(self, size: FontSize) -> Font { + Font { size: Size(size), ..self } + } + + #[inline] + pub fn size(&self) -> FontSize { + self.size.0 } /// Get normal font description. @@ -94,29 +70,12 @@ impl Font { pub fn bold_italic(&self) -> FontDescription { self.bold_italic.desc(&self.normal) } - - #[cfg(target_os = "macos")] - pub fn use_thin_strokes(&self) -> bool { - self.use_thin_strokes.0 - } - - #[cfg(not(target_os = "macos"))] - pub fn use_thin_strokes(&self) -> bool { - false - } -} - -fn default_font_size() -> Size { - Size::new(11.) } /// Description of the normal font. -#[serde(default)] -#[derive(Debug, Deserialize, Clone, PartialEq, Eq)] +#[derive(ConfigDeserialize, Debug, Clone, PartialEq, Eq)] pub struct FontDescription { - #[serde(deserialize_with = "failure_default")] pub family: String, - #[serde(deserialize_with = "failure_default")] pub style: Option, } @@ -135,12 +94,9 @@ impl Default for FontDescription { } /// Description of the italic and bold font. -#[serde(default)] -#[derive(Debug, Default, Deserialize, Clone, PartialEq, Eq)] +#[derive(ConfigDeserialize, Debug, Default, Clone, PartialEq, Eq)] pub struct SecondaryFontDescription { - #[serde(deserialize_with = "failure_default")] family: Option, - #[serde(deserialize_with = "failure_default")] style: Option, } @@ -153,66 +109,37 @@ impl SecondaryFontDescription { } } -trait DeserializeSize: Sized { - fn deserialize<'a, D>(_: D) -> ::std::result::Result - where - D: serde::de::Deserializer<'a>; +#[derive(Debug, Clone, PartialEq, Eq)] +struct Size(FontSize); + +impl Default for Size { + fn default() -> Self { + Self(FontSize::new(11.)) + } } -impl DeserializeSize for Size { - fn deserialize<'a, D>(deserializer: D) -> ::std::result::Result +impl<'de> Deserialize<'de> for Size { + fn deserialize(deserializer: D) -> Result where - D: serde::de::Deserializer<'a>, + D: Deserializer<'de>, { - use std::marker::PhantomData; - - struct NumVisitor<__D> { - _marker: PhantomData<__D>, - } - - impl<'a, __D> Visitor<'a> for NumVisitor<__D> - where - __D: serde::de::Deserializer<'a>, - { - type Value = f64; + struct NumVisitor; + impl<'v> Visitor<'v> for NumVisitor { + type Value = Size; fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("f64 or u64") } - fn visit_f64(self, value: f64) -> ::std::result::Result - where - E: ::serde::de::Error, - { - Ok(value) + fn visit_f64(self, value: f64) -> Result { + Ok(Size(FontSize::new(value as f32))) } - fn visit_u64(self, value: u64) -> ::std::result::Result - where - E: ::serde::de::Error, - { - Ok(value as f64) + fn visit_u64(self, value: u64) -> Result { + Ok(Size(FontSize::new(value as f32))) } } - let value = serde_yaml::Value::deserialize(deserializer)?; - let size = value - .deserialize_any(NumVisitor:: { _marker: PhantomData }) - .map(|v| Size::new(v as _)); - - // Use default font size as fallback. - match size { - Ok(size) => Ok(size), - Err(err) => { - let size = default_font_size(); - error!( - target: LOG_TARGET_CONFIG, - "Problem with config: {}; using size {}", - err, - size.as_f32_pts() - ); - Ok(size) - }, - } + deserializer.deserialize_any(NumVisitor) } } diff --git a/alacritty/src/config/mod.rs b/alacritty/src/config/mod.rs index 19888add..0673ffd5 100644 --- a/alacritty/src/config/mod.rs +++ b/alacritty/src/config/mod.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Display, Formatter}; use std::path::PathBuf; use std::{env, fs, io}; -use log::{error, info, warn}; +use log::{error, info}; use serde::Deserialize; use serde_yaml::mapping::Mapping; use serde_yaml::Value; @@ -68,7 +68,7 @@ impl Display for Error { write!(f, "Unable to read $HOME environment variable: {}", err) }, Error::Io(err) => write!(f, "Error reading config file: {}", err), - Error::Yaml(err) => write!(f, "Problem with config: {}", err), + Error::Yaml(err) => write!(f, "Config error: {}", err), } } } @@ -157,8 +157,6 @@ fn read_config(path: &PathBuf, cli_config: Value) -> Result { let mut config = Config::deserialize(config_value)?; config.ui_config.config_paths = config_paths; - print_deprecation_warnings(&config); - Ok(config) } @@ -287,56 +285,6 @@ fn installed_config() -> Option { dirs::config_dir().map(|path| path.join("alacritty\\alacritty.yml")).filter(|new| new.exists()) } -fn print_deprecation_warnings(config: &Config) { - if config.scrolling.faux_multiplier().is_some() { - warn!( - target: LOG_TARGET_CONFIG, - "Config scrolling.faux_multiplier is deprecated; the alternate scroll escape can now \ - be used to disable it and `scrolling.multiplier` controls the number of scrolled \ - lines" - ); - } - - if config.scrolling.auto_scroll.is_some() { - warn!( - target: LOG_TARGET_CONFIG, - "Config scrolling.auto_scroll has been removed and is now always disabled, it can be \ - safely removed from the config" - ); - } - - if config.tabspaces.is_some() { - warn!( - target: LOG_TARGET_CONFIG, - "Config tabspaces has been removed and is now always 8, it can be safely removed from \ - the config" - ); - } - - if config.visual_bell.is_some() { - warn!( - target: LOG_TARGET_CONFIG, - "Config visual_bell has been deprecated; please use bell instead" - ) - } - - if config.ui_config.dynamic_title.is_some() { - warn!( - target: LOG_TARGET_CONFIG, - "Config dynamic_title is deprecated; please use window.dynamic_title instead", - ) - } - - #[cfg(all(windows, not(feature = "winpty")))] - if config.winpty_backend { - warn!( - target: LOG_TARGET_CONFIG, - "Config winpty_backend is deprecated and requires a compilation flag; it should be \ - removed from the config", - ) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/alacritty/src/config/mouse.rs b/alacritty/src/config/mouse.rs index 1a5aec3d..f562ebe0 100644 --- a/alacritty/src/config/mouse.rs +++ b/alacritty/src/config/mouse.rs @@ -1,35 +1,26 @@ use std::time::Duration; use glutin::event::ModifiersState; -use log::error; -use serde::{Deserialize, Deserializer}; -use alacritty_terminal::config::{failure_default, Program, LOG_TARGET_CONFIG}; +use alacritty_config_derive::ConfigDeserialize; +use alacritty_terminal::config::Program; use crate::config::bindings::ModsWrapper; -#[serde(default)] -#[derive(Default, Clone, Debug, Deserialize, PartialEq, Eq)] +#[derive(ConfigDeserialize, Default, Clone, Debug, PartialEq, Eq)] pub struct Mouse { - #[serde(deserialize_with = "failure_default")] pub double_click: ClickHandler, - #[serde(deserialize_with = "failure_default")] pub triple_click: ClickHandler, - #[serde(deserialize_with = "failure_default")] pub hide_when_typing: bool, - #[serde(deserialize_with = "failure_default")] pub url: Url, } -#[serde(default)] -#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] +#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq)] pub struct Url { /// Program for opening links. - #[serde(deserialize_with = "deserialize_launcher")] pub launcher: Option, /// Modifier used to open links. - #[serde(deserialize_with = "failure_default")] modifiers: ModsWrapper, } @@ -39,34 +30,6 @@ impl Url { } } -fn deserialize_launcher<'a, D>(deserializer: D) -> std::result::Result, D::Error> -where - D: Deserializer<'a>, -{ - let default = Url::default().launcher; - - // Deserialize to generic value. - let val = serde_yaml::Value::deserialize(deserializer)?; - - // Accept `None` to disable the launcher. - if val.as_str().filter(|v| v.to_lowercase() == "none").is_some() { - return Ok(None); - } - - match >::deserialize(val) { - Ok(launcher) => Ok(launcher), - Err(err) => { - error!( - target: LOG_TARGET_CONFIG, - "Problem with config: {}; using {}", - err, - default.clone().unwrap().program() - ); - Ok(default) - }, - } -} - impl Default for Url { fn default() -> Url { Url { @@ -81,33 +44,19 @@ impl Default for Url { } } -#[serde(default)] -#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] +#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq)] pub struct ClickHandler { - #[serde(deserialize_with = "deserialize_duration_ms")] - pub threshold: Duration, + threshold: u16, } impl Default for ClickHandler { fn default() -> Self { - ClickHandler { threshold: default_threshold_ms() } + Self { threshold: 300 } } } -fn default_threshold_ms() -> Duration { - Duration::from_millis(300) -} - -fn deserialize_duration_ms<'a, D>(deserializer: D) -> ::std::result::Result -where - D: Deserializer<'a>, -{ - let value = serde_yaml::Value::deserialize(deserializer)?; - match u64::deserialize(value) { - Ok(threshold_ms) => Ok(Duration::from_millis(threshold_ms)), - Err(err) => { - error!(target: LOG_TARGET_CONFIG, "Problem with config: {}; using default value", err); - Ok(default_threshold_ms()) - }, +impl ClickHandler { + pub fn threshold(&self) -> Duration { + Duration::from_millis(self.threshold as u64) } } diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs index 87b27b3e..25f9fb91 100644 --- a/alacritty/src/config/ui_config.rs +++ b/alacritty/src/config/ui_config.rs @@ -3,7 +3,8 @@ use std::path::PathBuf; use log::error; use serde::{Deserialize, Deserializer}; -use alacritty_terminal::config::{failure_default, Percentage, LOG_TARGET_CONFIG}; +use alacritty_config_derive::ConfigDeserialize; +use alacritty_terminal::config::{Percentage, LOG_TARGET_CONFIG}; use crate::config::bindings::{self, Binding, KeyBinding, MouseBinding}; use crate::config::debug::Debug; @@ -11,66 +12,52 @@ use crate::config::font::Font; use crate::config::mouse::Mouse; use crate::config::window::WindowConfig; -#[derive(Debug, PartialEq, Deserialize)] +#[derive(ConfigDeserialize, Debug, PartialEq)] pub struct UIConfig { /// Font configuration. - #[serde(default, deserialize_with = "failure_default")] pub font: Font, /// Window configuration. - #[serde(default, deserialize_with = "failure_default")] pub window: WindowConfig, - #[serde(default, deserialize_with = "failure_default")] pub mouse: Mouse, - /// Keybindings. - #[serde(default = "default_key_bindings", deserialize_with = "deserialize_key_bindings")] - pub key_bindings: Vec, - - /// Bindings for the mouse. - #[serde(default = "default_mouse_bindings", deserialize_with = "deserialize_mouse_bindings")] - pub mouse_bindings: Vec, - /// Debug options. - #[serde(default, deserialize_with = "failure_default")] pub debug: Debug, /// Send escape sequences using the alt key. - #[serde(default, deserialize_with = "failure_default")] - alt_send_esc: DefaultTrueBool, + pub alt_send_esc: bool, /// Live config reload. - #[serde(default, deserialize_with = "failure_default")] - live_config_reload: DefaultTrueBool, - - /// Background opacity from 0.0 to 1.0. - #[serde(default, deserialize_with = "failure_default")] - background_opacity: Percentage, + pub live_config_reload: bool, /// Path where config was loaded from. - #[serde(skip)] + #[config(skip)] pub config_paths: Vec, - // TODO: DEPRECATED - #[serde(default, deserialize_with = "failure_default")] - pub dynamic_title: Option, + /// Keybindings. + key_bindings: KeyBindings, + + /// Bindings for the mouse. + mouse_bindings: MouseBindings, + + /// Background opacity from 0.0 to 1.0. + background_opacity: Percentage, } impl Default for UIConfig { fn default() -> Self { - UIConfig { + Self { + alt_send_esc: true, + live_config_reload: true, font: Default::default(), window: Default::default(), mouse: Default::default(), - key_bindings: default_key_bindings(), - mouse_bindings: default_mouse_bindings(), debug: Default::default(), - alt_send_esc: Default::default(), - background_opacity: Default::default(), - live_config_reload: Default::default(), - dynamic_title: Default::default(), config_paths: Default::default(), + key_bindings: Default::default(), + mouse_bindings: Default::default(), + background_opacity: Default::default(), } } } @@ -82,48 +69,50 @@ impl UIConfig { } #[inline] - pub fn dynamic_title(&self) -> bool { - self.dynamic_title.unwrap_or_else(|| self.window.dynamic_title()) + pub fn key_bindings(&self) -> &[KeyBinding] { + &self.key_bindings.0.as_slice() } #[inline] - pub fn set_dynamic_title(&mut self, dynamic_title: bool) { - self.window.set_dynamic_title(dynamic_title); + pub fn mouse_bindings(&self) -> &[MouseBinding] { + self.mouse_bindings.0.as_slice() } +} - /// Live config reload. - #[inline] - pub fn live_config_reload(&self) -> bool { - self.live_config_reload.0 - } +#[derive(Debug, PartialEq)] +struct KeyBindings(Vec); - /// Send escape sequences using the alt key. - #[inline] - pub fn alt_send_esc(&self) -> bool { - self.alt_send_esc.0 +impl Default for KeyBindings { + fn default() -> Self { + Self(bindings::default_key_bindings()) } } -fn default_key_bindings() -> Vec { - bindings::default_key_bindings() +impl<'de> Deserialize<'de> for KeyBindings { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(Self(deserialize_bindings(deserializer, Self::default().0)?)) + } } -fn default_mouse_bindings() -> Vec { - bindings::default_mouse_bindings() -} +#[derive(Debug, PartialEq)] +struct MouseBindings(Vec); -fn deserialize_key_bindings<'a, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'a>, -{ - deserialize_bindings(deserializer, bindings::default_key_bindings()) +impl Default for MouseBindings { + fn default() -> Self { + Self(bindings::default_mouse_bindings()) + } } -fn deserialize_mouse_bindings<'a, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'a>, -{ - deserialize_bindings(deserializer, bindings::default_mouse_bindings()) +impl<'de> Deserialize<'de> for MouseBindings { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + Ok(Self(deserialize_bindings(deserializer, Self::default().0)?)) + } } fn deserialize_bindings<'a, D, T>( @@ -143,7 +132,7 @@ where match Binding::::deserialize(value) { Ok(binding) => bindings.push(binding), Err(err) => { - error!(target: LOG_TARGET_CONFIG, "Problem with config: {}; ignoring binding", err); + error!(target: LOG_TARGET_CONFIG, "Config error: {}; ignoring binding", err); }, } } @@ -158,23 +147,11 @@ where Ok(bindings) } -#[derive(Deserialize, Copy, Clone, Debug, PartialEq, Eq)] -pub struct DefaultTrueBool(pub bool); - -impl Default for DefaultTrueBool { - fn default() -> Self { - DefaultTrueBool(true) - } -} - /// A delta for a point in a 2 dimensional plane. -#[serde(default, bound(deserialize = "T: Deserialize<'de> + Default"))] -#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq)] -pub struct Delta { +#[derive(ConfigDeserialize, Clone, Copy, Debug, Default, PartialEq, Eq)] +pub struct Delta { /// Horizontal change. - #[serde(deserialize_with = "failure_default")] pub x: T, /// Vertical change. - #[serde(deserialize_with = "failure_default")] pub y: T, } diff --git a/alacritty/src/config/window.rs b/alacritty/src/config/window.rs index ce36d23c..2d501b91 100644 --- a/alacritty/src/config/window.rs +++ b/alacritty/src/config/window.rs @@ -1,81 +1,76 @@ +use std::fmt::{self, Formatter}; use std::os::raw::c_ulong; use glutin::window::Fullscreen; use log::error; +use serde::de::{self, MapAccess, Visitor}; use serde::{Deserialize, Deserializer}; -use serde_yaml::Value; -use alacritty_terminal::config::{failure_default, option_explicit_none, LOG_TARGET_CONFIG}; +use alacritty_config_derive::ConfigDeserialize; +use alacritty_terminal::config::LOG_TARGET_CONFIG; use alacritty_terminal::index::{Column, Line}; -use crate::config::ui_config::{DefaultTrueBool, Delta}; +use crate::config::ui_config::Delta; /// Default Alacritty name, used for window title and class. pub const DEFAULT_NAME: &str = "Alacritty"; -#[serde(default)] -#[derive(Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(ConfigDeserialize, Debug, Clone, PartialEq, Eq)] pub struct WindowConfig { /// Initial position. - #[serde(deserialize_with = "failure_default")] pub position: Option>, /// Draw the window with title bar / borders. - #[serde(deserialize_with = "failure_default")] pub decorations: Decorations, /// Startup mode. - #[serde(deserialize_with = "failure_default")] pub startup_mode: StartupMode, - /// Window title. - #[serde(default = "default_title")] - pub title: String, - - /// Window class. - #[serde(deserialize_with = "deserialize_class")] - pub class: Class, - /// XEmbed parent. - #[serde(skip)] + #[config(skip)] pub embed: Option, /// GTK theme variant. - #[serde(deserialize_with = "option_explicit_none")] pub gtk_theme_variant: Option, /// Spread out additional padding evenly. - #[serde(deserialize_with = "failure_default")] pub dynamic_padding: bool, + /// Use dynamic title. + pub dynamic_title: bool, + + /// Window title. + pub title: String, + + /// Window class. + pub class: Class, + /// Pixel padding. - #[serde(deserialize_with = "failure_default")] padding: Delta, - /// Use dynamic title. - #[serde(default, deserialize_with = "failure_default")] - dynamic_title: DefaultTrueBool, - /// Initial dimensions. - #[serde(deserialize_with = "failure_default")] dimensions: Dimensions, } -pub fn default_title() -> String { - DEFAULT_NAME.to_string() +impl Default for WindowConfig { + fn default() -> Self { + Self { + dynamic_title: true, + title: DEFAULT_NAME.into(), + position: Default::default(), + decorations: Default::default(), + startup_mode: Default::default(), + embed: Default::default(), + gtk_theme_variant: Default::default(), + dynamic_padding: Default::default(), + class: Default::default(), + padding: Default::default(), + dimensions: Default::default(), + } + } } impl WindowConfig { - #[inline] - pub fn dynamic_title(&self) -> bool { - self.dynamic_title.0 - } - - #[inline] - pub fn set_dynamic_title(&mut self, dynamic_title: bool) { - self.dynamic_title.0 = dynamic_title; - } - #[inline] pub fn dimensions(&self) -> Option { if self.dimensions.columns.0 != 0 @@ -110,25 +105,7 @@ impl WindowConfig { } } -impl Default for WindowConfig { - fn default() -> WindowConfig { - WindowConfig { - dimensions: Default::default(), - position: Default::default(), - padding: Default::default(), - decorations: Default::default(), - dynamic_padding: Default::default(), - startup_mode: Default::default(), - class: Default::default(), - embed: Default::default(), - gtk_theme_variant: Default::default(), - title: default_title(), - dynamic_title: Default::default(), - } - } -} - -#[derive(Debug, Deserialize, Copy, Clone, PartialEq, Eq)] +#[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)] pub enum StartupMode { Windowed, Maximized, @@ -143,17 +120,13 @@ impl Default for StartupMode { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize)] +#[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)] pub enum Decorations { - #[serde(rename = "full")] Full, #[cfg(target_os = "macos")] - #[serde(rename = "transparent")] Transparent, #[cfg(target_os = "macos")] - #[serde(rename = "buttonless")] Buttonless, - #[serde(rename = "none")] None, } @@ -166,71 +139,82 @@ impl Default for Decorations { /// Window Dimensions. /// /// Newtype to avoid passing values incorrectly. -#[serde(default)] -#[derive(Default, Debug, Copy, Clone, Deserialize, PartialEq, Eq)] +#[derive(ConfigDeserialize, Default, Debug, Copy, Clone, PartialEq, Eq)] pub struct Dimensions { /// Window width in character columns. - #[serde(deserialize_with = "failure_default")] pub columns: Column, /// Window Height in character lines. - #[serde(deserialize_with = "failure_default")] pub lines: Line, } /// Window class hint. -#[serde(default)] -#[derive(Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct Class { - #[serde(deserialize_with = "deserialize_class_resource")] pub instance: String, - - #[serde(deserialize_with = "deserialize_class_resource")] pub general: String, } impl Default for Class { fn default() -> Self { - Class { instance: DEFAULT_NAME.into(), general: DEFAULT_NAME.into() } - } -} - -fn deserialize_class_resource<'a, D>(deserializer: D) -> Result -where - D: Deserializer<'a>, -{ - let value = Value::deserialize(deserializer)?; - match String::deserialize(value) { - Ok(value) => Ok(value), - Err(err) => { - error!( - target: LOG_TARGET_CONFIG, - "Problem with config: {}, using default value {}", err, DEFAULT_NAME, - ); - - Ok(DEFAULT_NAME.into()) - }, + Self { instance: DEFAULT_NAME.into(), general: DEFAULT_NAME.into() } } } -fn deserialize_class<'a, D>(deserializer: D) -> Result -where - D: Deserializer<'a>, -{ - let value = Value::deserialize(deserializer)?; - - if let Value::String(instance) = value { - return Ok(Class { instance, general: DEFAULT_NAME.into() }); - } +impl<'de> Deserialize<'de> for Class { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ClassVisitor; + impl<'a> Visitor<'a> for ClassVisitor { + type Value = Class; + + fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.write_str("a mapping") + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + Ok(Self::Value { instance: value.into(), ..Self::Value::default() }) + } + + fn visit_map(self, mut map: M) -> Result + where + M: MapAccess<'a>, + { + let mut class = Self::Value::default(); + + while let Some((key, value)) = map.next_entry::()? { + match key.as_str() { + "instance" => match String::deserialize(value) { + Ok(instance) => class.instance = instance, + Err(err) => { + error!( + target: LOG_TARGET_CONFIG, + "Config error: class.instance: {}", err + ); + }, + }, + "general" => match String::deserialize(value) { + Ok(general) => class.general = general, + Err(err) => { + error!( + target: LOG_TARGET_CONFIG, + "Config error: class.instance: {}", err + ); + }, + }, + _ => (), + } + } + + Ok(class) + } + } - match Class::deserialize(value) { - Ok(value) => Ok(value), - Err(err) => { - error!( - target: LOG_TARGET_CONFIG, - "Problem with config: {}; using class {}", err, DEFAULT_NAME - ); - Ok(Class::default()) - }, + deserializer.deserialize_any(ClassVisitor) } } diff --git a/alacritty/src/cursor.rs b/alacritty/src/cursor.rs index edf76bf3..94808029 100644 --- a/alacritty/src/cursor.rs +++ b/alacritty/src/cursor.rs @@ -10,7 +10,7 @@ pub fn get_cursor_glyph( offset_x: i8, offset_y: i8, is_wide: bool, - cursor_thickness: f64, + cursor_thickness: f32, ) -> RasterizedGlyph { // Calculate the cell metrics. // @@ -18,7 +18,7 @@ pub fn get_cursor_glyph( // https://github.com/rust-lang/rust/commit/14d608f1d8a0b84da5f3bccecb3efb3d35f980dc let height = (metrics.line_height + f64::from(offset_y)).max(1.) as usize; let mut width = (metrics.average_advance + f64::from(offset_x)).max(1.) as usize; - let line_width = (cursor_thickness * width as f64).round().max(1.) as usize; + let line_width = (cursor_thickness * width as f32).round().max(1.) as usize; // Double the cursor width if it's above a double-width glyph. if is_wide { diff --git a/alacritty/src/display.rs b/alacritty/src/display.rs index 451874c8..1fe1d2de 100644 --- a/alacritty/src/display.rs +++ b/alacritty/src/display.rs @@ -20,8 +20,6 @@ use unicode_width::UnicodeWidthChar; #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] use wayland_client::{Display as WaylandDisplay, EventQueue}; -#[cfg(target_os = "macos")] -use crossfont::set_font_smoothing; use crossfont::{self, Rasterize, Rasterizer}; use alacritty_terminal::event::{EventListener, OnResize}; @@ -254,7 +252,7 @@ impl Display { // Set subpixel anti-aliasing. #[cfg(target_os = "macos")] - set_font_smoothing(config.ui_config.font.use_thin_strokes()); + crossfont::set_font_smoothing(config.ui_config.font.use_thin_strokes); #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] let is_x11 = event_loop.is_x11(); @@ -313,7 +311,7 @@ impl Display { config: &Config, ) -> Result<(GlyphCache, f32, f32), Error> { let font = config.ui_config.font.clone(); - let rasterizer = Rasterizer::new(dpr as f32, config.ui_config.font.use_thin_strokes())?; + let rasterizer = Rasterizer::new(dpr as f32, config.ui_config.font.use_thin_strokes)?; // Initialize glyph cache. let glyph_cache = { @@ -491,8 +489,8 @@ impl Display { .map_or(false, |viewport_match| viewport_match.contains(&cell_point)) { let colors = config.colors.search.focused_match; - let match_fg = colors.foreground().color(cell.fg, cell.bg); - cell.bg = colors.background().color(cell.fg, cell.bg); + let match_fg = colors.foreground.color(cell.fg, cell.bg); + cell.bg = colors.background.color(cell.fg, cell.bg); cell.fg = match_fg; cell.bg_alpha = 1.0; } @@ -558,8 +556,8 @@ impl Display { let y = size_info.cell_height().mul_add(start_line.0 as f32, size_info.padding_y()); let color = match message.ty() { - MessageType::Error => config.colors.normal().red, - MessageType::Warning => config.colors.normal().yellow, + MessageType::Error => config.colors.normal.red, + MessageType::Warning => config.colors.normal.yellow, }; let message_bar_rect = @@ -680,7 +678,7 @@ impl Display { let timing = format!("{:.3} usec", self.meter.average()); let fg = config.colors.primary.background; - let bg = config.colors.normal().red; + let bg = config.colors.normal.red; self.renderer.with_api(&config.ui_config, config.cursor, &size_info, |mut api| { api.render_string(glyph_cache, size_info.screen_lines() - 2, &timing[..], fg, Some(bg)); diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 4369a689..87b1d5c8 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -4,6 +4,7 @@ use std::borrow::Cow; use std::cmp::{max, min}; use std::collections::VecDeque; use std::env; +use std::f32; use std::fmt::Debug; #[cfg(not(any(target_os = "macos", windows)))] use std::fs; @@ -26,8 +27,6 @@ use glutin::platform::unix::EventLoopWindowTargetExtUnix; use log::info; use serde_json as json; -#[cfg(target_os = "macos")] -use crossfont::set_font_smoothing; use crossfont::{self, Size}; use alacritty_terminal::config::LOG_TARGET_CONFIG; @@ -396,7 +395,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon } fn reset_font_size(&mut self) { - *self.font_size = self.config.ui_config.font.size; + *self.font_size = self.config.ui_config.font.size(); self.display_update_pending.set_font(self.config.ui_config.font.clone()); self.terminal.dirty = true; } @@ -874,7 +873,7 @@ impl Processor { received_count: 0, suppress_chars: false, modifiers: Default::default(), - font_size: config.ui_config.font.size, + font_size: config.ui_config.font.size(), config, message_buffer, display, @@ -1080,13 +1079,13 @@ impl Processor { Event::TerminalEvent(event) => match event { TerminalEvent::Title(title) => { let ui_config = &processor.ctx.config.ui_config; - if ui_config.dynamic_title() { + if ui_config.window.dynamic_title { processor.ctx.window.set_title(&title); } }, TerminalEvent::ResetTitle => { let ui_config = &processor.ctx.config.ui_config; - if ui_config.dynamic_title() { + if ui_config.window.dynamic_title { processor.ctx.window.set_title(&ui_config.window.title); } }, @@ -1241,15 +1240,15 @@ impl Processor { // Reload cursor if its thickness has changed. if (processor.ctx.config.cursor.thickness() - config.cursor.thickness()).abs() - > std::f64::EPSILON + > f32::EPSILON { processor.ctx.display_update_pending.set_cursor_dirty(); } if processor.ctx.config.ui_config.font != config.ui_config.font { // Do not update font size if it has been changed at runtime. - if *processor.ctx.font_size == processor.ctx.config.ui_config.font.size { - *processor.ctx.font_size = config.ui_config.font.size; + if *processor.ctx.font_size == processor.ctx.config.ui_config.font.size() { + *processor.ctx.font_size = config.ui_config.font.size(); } let font = config.ui_config.font.clone().with_size(*processor.ctx.font_size); @@ -1265,7 +1264,7 @@ impl Processor { } // Live title reload. - if !config.ui_config.dynamic_title() + if !config.ui_config.window.dynamic_title || processor.ctx.config.ui_config.window.title != config.ui_config.window.title { processor.ctx.window.set_title(&config.ui_config.window.title); @@ -1278,7 +1277,7 @@ impl Processor { // Set subpixel anti-aliasing. #[cfg(target_os = "macos")] - set_font_smoothing(config.ui_config.font.use_thin_strokes()); + crossfont::set_font_smoothing(config.ui_config.font.use_thin_strokes); *processor.ctx.config = config; diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs index 313c7051..4f66721c 100644 --- a/alacritty/src/input.rs +++ b/alacritty/src/input.rs @@ -561,10 +561,10 @@ impl<'a, T: EventListener, A: ActionContext> Processor<'a, T, A> { self.ctx.mouse_mut().last_click_button = button; ClickState::Click }, - ClickState::Click if elapsed < mouse_config.double_click.threshold => { + ClickState::Click if elapsed < mouse_config.double_click.threshold() => { ClickState::DoubleClick }, - ClickState::DoubleClick if elapsed < mouse_config.triple_click.threshold => { + ClickState::DoubleClick if elapsed < mouse_config.triple_click.threshold() => { ClickState::TripleClick }, _ => ClickState::Click, @@ -714,13 +714,7 @@ impl<'a, T: EventListener, A: ActionContext> Processor<'a, T, A> { .contains(TermMode::ALT_SCREEN | TermMode::ALTERNATE_SCROLL) && !self.ctx.modifiers().shift() { - let multiplier = f64::from( - self.ctx - .config() - .scrolling - .faux_multiplier() - .unwrap_or_else(|| self.ctx.config().scrolling.multiplier()), - ); + let multiplier = f64::from(self.ctx.config().scrolling.multiplier); self.ctx.mouse_mut().scroll_px += new_scroll_px * multiplier; let cmd = if new_scroll_px > 0. { b'A' } else { b'B' }; @@ -734,7 +728,7 @@ impl<'a, T: EventListener, A: ActionContext> Processor<'a, T, A> { } self.ctx.write_to_pty(content); } else { - let multiplier = f64::from(self.ctx.config().scrolling.multiplier()); + let multiplier = f64::from(self.ctx.config().scrolling.multiplier); self.ctx.mouse_mut().scroll_px += new_scroll_px * multiplier; let lines = self.ctx.mouse().scroll_px / height; @@ -878,7 +872,7 @@ impl<'a, T: EventListener, A: ActionContext> Processor<'a, T, A> { c.encode_utf8(&mut bytes[..]); } - if self.ctx.config().ui_config.alt_send_esc() + if self.ctx.config().ui_config.alt_send_esc && *self.ctx.received_count() == 0 && self.ctx.modifiers().alt() && utf8_len == 1 @@ -900,8 +894,8 @@ impl<'a, T: EventListener, A: ActionContext> Processor<'a, T, A> { let mods = *self.ctx.modifiers(); let mut suppress_chars = None; - for i in 0..self.ctx.config().ui_config.key_bindings.len() { - let binding = &self.ctx.config().ui_config.key_bindings[i]; + for i in 0..self.ctx.config().ui_config.key_bindings().len() { + let binding = &self.ctx.config().ui_config.key_bindings()[i]; let key = match (binding.trigger, input.virtual_keycode) { (Key::Scancode(_), _) => Key::Scancode(input.scancode), @@ -932,8 +926,8 @@ impl<'a, T: EventListener, A: ActionContext> Processor<'a, T, A> { let mouse_mode = self.ctx.mouse_mode(); let mods = *self.ctx.modifiers(); - for i in 0..self.ctx.config().ui_config.mouse_bindings.len() { - let mut binding = self.ctx.config().ui_config.mouse_bindings[i].clone(); + for i in 0..self.ctx.config().ui_config.mouse_bindings().len() { + let mut binding = self.ctx.config().ui_config.mouse_bindings()[i].clone(); // Require shift for all modifiers when mouse mode is active. if mouse_mode { @@ -1072,7 +1066,6 @@ mod tests { use alacritty_terminal::event::Event as TerminalEvent; use alacritty_terminal::selection::Selection; - use crate::config::ClickHandler; use crate::message_bar::MessageBuffer; const KEY: VirtualKeyCode = VirtualKeyCode::Key0; @@ -1251,18 +1244,8 @@ mod tests { } => { #[test] fn $name() { - let mut cfg = Config::default(); - cfg.ui_config.mouse = crate::config::Mouse { - double_click: ClickHandler { - threshold: Duration::from_millis(1000), - }, - triple_click: ClickHandler { - threshold: Duration::from_millis(1000), - }, - hide_when_typing: false, - url: Default::default(), - }; - + let mut clipboard = Clipboard::new_nop(); + let cfg = Config::default(); let size = SizeInfo::new( 21.0, 51.0, @@ -1273,8 +1256,6 @@ mod tests { false, ); - let mut clipboard = Clipboard::new_nop(); - let mut terminal = Term::new(&cfg, size, MockEventProxy); let mut mouse = Mouse::default(); diff --git a/alacritty/src/logging.rs b/alacritty/src/logging.rs index 2110d8e1..36d20fa3 100644 --- a/alacritty/src/logging.rs +++ b/alacritty/src/logging.rs @@ -23,7 +23,7 @@ use crate::message_bar::{Message, MessageType}; const ALACRITTY_LOG_ENV: &str = "ALACRITTY_LOG"; /// List of targets which will be logged by Alacritty. const ALLOWED_TARGETS: [&str; 4] = - ["alacritty_terminal", "alacritty_config", "alacritty", "crossfont"]; + ["alacritty_terminal", "alacritty_config_derive", "alacritty", "crossfont"]; pub fn initialize( options: &Options, diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index 3b517efc..0e27c893 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -186,7 +186,7 @@ fn run( // // The monitor watches the config file for changes and reloads it. Pending // config changes are processed in the main loop. - if config.ui_config.live_config_reload() { + if config.ui_config.live_config_reload { monitor::watch(config.ui_config.config_paths.clone(), event_proxy); } diff --git a/alacritty/src/renderer/mod.rs b/alacritty/src/renderer/mod.rs index 3320a860..cc2515be 100644 --- a/alacritty/src/renderer/mod.rs +++ b/alacritty/src/renderer/mod.rs @@ -156,15 +156,15 @@ impl GlyphCache { // Need to load at least one glyph for the face before calling metrics. // The glyph requested here ('m' at the time of writing) has no special // meaning. - rasterizer.get_glyph(GlyphKey { font_key: regular, c: 'm', size: font.size })?; + rasterizer.get_glyph(GlyphKey { font_key: regular, c: 'm', size: font.size() })?; - let metrics = rasterizer.metrics(regular, font.size)?; + let metrics = rasterizer.metrics(regular, font.size())?; let mut cache = Self { cache: HashMap::default(), cursor_cache: HashMap::default(), rasterizer, - font_size: font.size, + font_size: font.size(), font_key: regular, bold_key: bold, italic_key: italic, @@ -190,7 +190,7 @@ impl GlyphCache { font: &Font, rasterizer: &mut Rasterizer, ) -> Result<(FontKey, FontKey, FontKey, FontKey), crossfont::Error> { - let size = font.size; + let size = font.size(); // Load regular font. let regular_desc = Self::make_desc(&font.normal(), Slant::Normal, Weight::Normal); @@ -291,12 +291,12 @@ impl GlyphCache { let (regular, bold, italic, bold_italic) = Self::compute_font_keys(font, &mut self.rasterizer)?; - self.rasterizer.get_glyph(GlyphKey { font_key: regular, c: 'm', size: font.size })?; - let metrics = self.rasterizer.metrics(regular, font.size)?; + self.rasterizer.get_glyph(GlyphKey { font_key: regular, c: 'm', size: font.size() })?; + let metrics = self.rasterizer.metrics(regular, font.size())?; - info!("Font size changed to {:?} with DPR of {}", font.size, dpr); + info!("Font size changed to {:?} with DPR of {}", font.size(), dpr); - self.font_size = font.size; + self.font_size = font.size(); self.font_key = regular; self.bold_key = bold; self.italic_key = italic; @@ -322,12 +322,12 @@ impl GlyphCache { /// Calculate font metrics without access to a glyph cache. pub fn static_metrics(font: Font, dpr: f64) -> Result { - let mut rasterizer = crossfont::Rasterizer::new(dpr as f32, font.use_thin_strokes())?; + let mut rasterizer = crossfont::Rasterizer::new(dpr as f32, font.use_thin_strokes)?; let regular_desc = GlyphCache::make_desc(&font.normal(), Slant::Normal, Weight::Normal); - let regular = Self::load_regular_font(&mut rasterizer, ®ular_desc, font.size)?; - rasterizer.get_glyph(GlyphKey { font_key: regular, c: 'm', size: font.size })?; + let regular = Self::load_regular_font(&mut rasterizer, ®ular_desc, font.size())?; + rasterizer.get_glyph(GlyphKey { font_key: regular, c: 'm', size: font.size() })?; - rasterizer.metrics(regular, font.size) + rasterizer.metrics(regular, font.size()) } } diff --git a/alacritty/src/wayland_theme.rs b/alacritty/src/wayland_theme.rs index b9c4381e..5d3bd922 100644 --- a/alacritty/src/wayland_theme.rs +++ b/alacritty/src/wayland_theme.rs @@ -17,9 +17,9 @@ pub struct AlacrittyWaylandTheme { impl AlacrittyWaylandTheme { pub fn new(colors: &Colors) -> Self { - let hovered_close_icon = colors.normal().red.into_rgba(); - let hovered_maximize_icon = colors.normal().green.into_rgba(); - let hovered_minimize_icon = colors.normal().yellow.into_rgba(); + let hovered_close_icon = colors.normal.red.into_rgba(); + let hovered_maximize_icon = colors.normal.green.into_rgba(); + let hovered_minimize_icon = colors.normal.yellow.into_rgba(); let foreground = colors.search_bar_foreground().into_rgba(); let background = colors.search_bar_background().into_rgba(); diff --git a/alacritty/src/window.rs b/alacritty/src/window.rs index 1b9e7731..f4a38183 100644 --- a/alacritty/src/window.rs +++ b/alacritty/src/window.rs @@ -271,8 +271,6 @@ impl Window { Icon::from_rgba(buf, info.width, info.height) }; - let class = &window_config.class; - let builder = WindowBuilder::new() .with_title(title) .with_visible(false) @@ -285,10 +283,13 @@ impl Window { let builder = builder.with_window_icon(icon.ok()); #[cfg(feature = "wayland")] - let builder = builder.with_app_id(class.instance.clone()); + let builder = builder.with_app_id(window_config.class.instance.to_owned()); #[cfg(feature = "x11")] - let builder = builder.with_class(class.instance.clone(), class.general.clone()); + let builder = builder.with_class( + window_config.class.instance.to_owned(), + window_config.class.general.to_owned(), + ); #[cfg(feature = "x11")] let builder = match &window_config.gtk_theme_variant { -- cgit