diff options
author | Christian Duerr <contact@christianduerr.com> | 2020-12-21 02:44:38 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-21 02:44:38 +0000 |
commit | 6e1b9d8b2502f5b47dc28eb5e0853e46ad8b4e84 (patch) | |
tree | 623a6cd8785529b28cc28af201c26b56fb47ac46 /alacritty_terminal/src/config | |
parent | 37a3198d8882463c9873011c1d18c325ea46d7c8 (diff) | |
download | alacritty-6e1b9d8b2502f5b47dc28eb5e0853e46ad8b4e84.tar.gz alacritty-6e1b9d8b2502f5b47dc28eb5e0853e46ad8b4e84.zip |
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.
Diffstat (limited to 'alacritty_terminal/src/config')
-rw-r--r-- | alacritty_terminal/src/config/bell.rs | 72 | ||||
-rw-r--r-- | alacritty_terminal/src/config/colors.rs | 237 | ||||
-rw-r--r-- | alacritty_terminal/src/config/mod.rs | 224 | ||||
-rw-r--r-- | alacritty_terminal/src/config/scrolling.rs | 78 |
4 files changed, 162 insertions, 449 deletions
diff --git a/alacritty_terminal/src/config/bell.rs b/alacritty_terminal/src/config/bell.rs index 97010f31..825a7b1f 100644 --- a/alacritty_terminal/src/config/bell.rs +++ b/alacritty_terminal/src/config/bell.rs @@ -1,95 +1,45 @@ use std::time::Duration; -use log::error; -use serde::{Deserialize, Deserializer}; -use serde_yaml::Value; +use alacritty_config_derive::ConfigDeserialize; -use crate::config::{failure_default, Program, LOG_TARGET_CONFIG}; +use crate::config::Program; use crate::term::color::Rgb; -const DEFAULT_BELL_COLOR: Rgb = Rgb { r: 255, g: 255, b: 255 }; - -#[serde(default)] -#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] +#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq)] pub struct BellConfig { /// Visual bell animation function. - #[serde(deserialize_with = "failure_default")] pub animation: BellAnimation, - /// Visual bell duration in milliseconds. - #[serde(deserialize_with = "failure_default")] - duration: u16, + /// Command to run on bell. + pub command: Option<Program>, /// Visual bell flash color. - #[serde(deserialize_with = "deserialize_bell_color")] pub color: Rgb, - /// Command to run on bell. - #[serde(deserialize_with = "deserialize_bell_command")] - pub command: Option<Program>, + /// Visual bell duration in milliseconds. + duration: u16, } impl Default for BellConfig { fn default() -> Self { Self { + color: Rgb { r: 255, g: 255, b: 255 }, animation: Default::default(), - duration: Default::default(), command: Default::default(), - color: DEFAULT_BELL_COLOR, + duration: Default::default(), } } } impl BellConfig { - /// Visual bell duration in milliseconds. - #[inline] pub fn duration(&self) -> Duration { - Duration::from_millis(u64::from(self.duration)) - } -} - -fn deserialize_bell_color<'a, D>(deserializer: D) -> Result<Rgb, D::Error> -where - D: Deserializer<'a>, -{ - let value = Value::deserialize(deserializer)?; - match Rgb::deserialize(value) { - Ok(value) => Ok(value), - Err(err) => { - error!( - target: LOG_TARGET_CONFIG, - "Problem with config: {}, using default color value {}", err, DEFAULT_BELL_COLOR - ); - - Ok(DEFAULT_BELL_COLOR) - }, - } -} - -fn deserialize_bell_command<'a, D>(deserializer: D) -> Result<Option<Program>, D::Error> -where - D: Deserializer<'a>, -{ - // Deserialize to generic value. - let val = Value::deserialize(deserializer)?; - - // Accept `None` to disable the bell command. - if val.as_str().filter(|v| v.to_lowercase() == "none").is_some() { - return Ok(None); - } - - match Program::deserialize(val) { - Ok(command) => Ok(Some(command)), - Err(err) => { - error!(target: LOG_TARGET_CONFIG, "Problem with config: {}; ignoring field", err); - Ok(None) - }, + Duration::from_millis(self.duration as u64) } } /// `VisualBellAnimations` are modeled after a subset of CSS transitions and Robert /// Penner's Easing Functions. -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq)] +#[derive(ConfigDeserialize, Clone, Copy, Debug, PartialEq, Eq)] pub enum BellAnimation { // CSS animation. Ease, diff --git a/alacritty_terminal/src/config/colors.rs b/alacritty_terminal/src/config/colors.rs index a292fde4..df52f19f 100644 --- a/alacritty_terminal/src/config/colors.rs +++ b/alacritty_terminal/src/config/colors.rs @@ -1,42 +1,24 @@ -use log::error; +use serde::de::Error as SerdeError; use serde::{Deserialize, Deserializer}; -use serde_yaml::Value; -use crate::config::{failure_default, LOG_TARGET_CONFIG}; +use alacritty_config_derive::ConfigDeserialize; + use crate::term::color::{CellRgb, Rgb}; -#[serde(default)] -#[derive(Deserialize, Clone, Debug, Default, PartialEq, Eq)] +#[derive(ConfigDeserialize, Clone, Debug, Default, PartialEq, Eq)] pub struct Colors { - #[serde(deserialize_with = "failure_default")] pub primary: PrimaryColors, - #[serde(deserialize_with = "failure_default")] - pub cursor: CursorColors, - #[serde(deserialize_with = "failure_default")] - pub vi_mode_cursor: CursorColors, - #[serde(deserialize_with = "failure_default")] + pub cursor: InvertedCellColors, + pub vi_mode_cursor: InvertedCellColors, pub selection: InvertedCellColors, - #[serde(deserialize_with = "failure_default")] - normal: NormalColors, - #[serde(deserialize_with = "failure_default")] - bright: BrightColors, - #[serde(deserialize_with = "failure_default")] - pub dim: Option<AnsiColors>, - #[serde(deserialize_with = "failure_default")] + pub normal: NormalColors, + pub bright: BrightColors, + pub dim: Option<DimColors>, pub indexed_colors: Vec<IndexedColor>, - #[serde(deserialize_with = "failure_default")] pub search: SearchColors, } impl Colors { - pub fn normal(&self) -> &AnsiColors { - &self.normal.0 - } - - pub fn bright(&self) -> &AnsiColors { - &self.bright.0 - } - pub fn search_bar_foreground(&self) -> Rgb { self.search.bar.foreground.unwrap_or(self.primary.background) } @@ -46,158 +28,88 @@ impl Colors { } } -#[derive(Deserialize, Copy, Clone, Debug, PartialEq, Eq)] -struct DefaultForegroundCellRgb(CellRgb); - -impl Default for DefaultForegroundCellRgb { - fn default() -> Self { - Self(CellRgb::CellForeground) - } -} - -#[derive(Deserialize, Copy, Clone, Debug, PartialEq, Eq)] -struct DefaultBackgroundCellRgb(CellRgb); - -impl Default for DefaultBackgroundCellRgb { - fn default() -> Self { - Self(CellRgb::CellBackground) - } -} - -#[serde(default)] -#[derive(Deserialize, Clone, Default, Debug, PartialEq, Eq)] +#[derive(Deserialize, Copy, Clone, Default, Debug, PartialEq, Eq)] pub struct IndexedColor { - #[serde(deserialize_with = "deserialize_color_index")] - pub index: u8, - #[serde(deserialize_with = "failure_default")] pub color: Rgb, -} -fn deserialize_color_index<'a, D>(deserializer: D) -> Result<u8, D::Error> -where - D: Deserializer<'a>, -{ - let value = Value::deserialize(deserializer)?; - match u8::deserialize(value) { - Ok(index) => { - if index < 16 { - error!( - target: LOG_TARGET_CONFIG, - "Problem with config: indexed_color's index is {}, but a value bigger than 15 \ - was expected; ignoring setting", - index - ); - - // Return value out of range to ignore this color. - Ok(0) - } else { - Ok(index) - } - }, - Err(err) => { - error!(target: LOG_TARGET_CONFIG, "Problem with config: {}; ignoring setting", err); + index: ColorIndex, +} - // Return value out of range to ignore this color. - Ok(0) - }, +impl IndexedColor { + #[inline] + pub fn index(&self) -> u8 { + self.index.0 } } -#[serde(default)] -#[derive(Deserialize, Debug, Copy, Clone, Default, PartialEq, Eq)] -pub struct CursorColors { - #[serde(deserialize_with = "failure_default")] - text: DefaultBackgroundCellRgb, - #[serde(deserialize_with = "failure_default")] - cursor: DefaultForegroundCellRgb, -} +#[derive(Copy, Clone, Default, Debug, PartialEq, Eq)] +struct ColorIndex(u8); -impl CursorColors { - pub fn text(self) -> CellRgb { - self.text.0 - } +impl<'de> Deserialize<'de> for ColorIndex { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> + where + D: Deserializer<'de>, + { + let index = u8::deserialize(deserializer)?; - pub fn cursor(self) -> CellRgb { - self.cursor.0 + if index < 16 { + Err(SerdeError::custom( + "Config error: indexed_color's index is {}, but a value bigger than 15 was \ + expected; ignoring setting", + )) + } else { + Ok(Self(index)) + } } } -#[serde(default)] -#[derive(Deserialize, Debug, Copy, Clone, Default, PartialEq, Eq)] +#[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)] pub struct InvertedCellColors { - #[serde(deserialize_with = "failure_default", alias = "text")] - foreground: DefaultBackgroundCellRgb, - #[serde(deserialize_with = "failure_default")] - background: DefaultForegroundCellRgb, + #[config(alias = "text")] + pub foreground: CellRgb, + #[config(alias = "cursor")] + pub background: CellRgb, } -impl InvertedCellColors { - pub fn foreground(self) -> CellRgb { - self.foreground.0 - } - - pub fn background(self) -> CellRgb { - self.background.0 +impl Default for InvertedCellColors { + fn default() -> Self { + Self { foreground: CellRgb::CellBackground, background: CellRgb::CellForeground } } } -#[serde(default)] -#[derive(Deserialize, Debug, Copy, Clone, Default, PartialEq, Eq)] +#[derive(ConfigDeserialize, Debug, Copy, Clone, Default, PartialEq, Eq)] pub struct SearchColors { - #[serde(deserialize_with = "failure_default")] - pub matches: MatchColors, - #[serde(deserialize_with = "failure_default")] pub focused_match: InvertedCellColors, - #[serde(deserialize_with = "failure_default")] + pub matches: MatchColors, bar: BarColors, } -#[serde(default)] -#[derive(Deserialize, Debug, Copy, Clone, PartialEq, Eq)] +#[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)] pub struct MatchColors { - #[serde(deserialize_with = "failure_default")] pub foreground: CellRgb, - #[serde(deserialize_with = "deserialize_match_background")] pub background: CellRgb, } impl Default for MatchColors { fn default() -> Self { - Self { foreground: CellRgb::default(), background: default_match_background() } + Self { + background: CellRgb::Rgb(Rgb { r: 0xff, g: 0xff, b: 0xff }), + foreground: CellRgb::Rgb(Rgb { r: 0x00, g: 0x00, b: 0x00 }), + } } } -fn deserialize_match_background<'a, D>(deserializer: D) -> Result<CellRgb, D::Error> -where - D: Deserializer<'a>, -{ - let value = Value::deserialize(deserializer)?; - Ok(CellRgb::deserialize(value).unwrap_or_else(|_| default_match_background())) -} - -fn default_match_background() -> CellRgb { - CellRgb::Rgb(Rgb { r: 0xff, g: 0xff, b: 0xff }) -} - -#[serde(default)] -#[derive(Deserialize, Debug, Copy, Clone, Default, PartialEq, Eq)] +#[derive(ConfigDeserialize, Debug, Copy, Clone, Default, PartialEq, Eq)] pub struct BarColors { - #[serde(deserialize_with = "failure_default")] foreground: Option<Rgb>, - #[serde(deserialize_with = "failure_default")] background: Option<Rgb>, } -#[serde(default)] -#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] +#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq)] pub struct PrimaryColors { - #[serde(deserialize_with = "failure_default")] - pub background: Rgb, - #[serde(deserialize_with = "failure_default")] pub foreground: Rgb, - #[serde(deserialize_with = "failure_default")] + pub background: Rgb, pub bright_foreground: Option<Rgb>, - #[serde(deserialize_with = "failure_default")] pub dim_foreground: Option<Rgb>, } @@ -212,33 +124,21 @@ impl Default for PrimaryColors { } } -/// The 8-colors sections of config. -#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] -pub struct AnsiColors { - #[serde(deserialize_with = "failure_default")] +#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq)] +pub struct NormalColors { pub black: Rgb, - #[serde(deserialize_with = "failure_default")] pub red: Rgb, - #[serde(deserialize_with = "failure_default")] pub green: Rgb, - #[serde(deserialize_with = "failure_default")] pub yellow: Rgb, - #[serde(deserialize_with = "failure_default")] pub blue: Rgb, - #[serde(deserialize_with = "failure_default")] pub magenta: Rgb, - #[serde(deserialize_with = "failure_default")] pub cyan: Rgb, - #[serde(deserialize_with = "failure_default")] pub white: Rgb, } -#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] -struct NormalColors(AnsiColors); - impl Default for NormalColors { fn default() -> Self { - NormalColors(AnsiColors { + NormalColors { black: Rgb { r: 0x1d, g: 0x1f, b: 0x21 }, red: Rgb { r: 0xcc, g: 0x66, b: 0x66 }, green: Rgb { r: 0xb5, g: 0xbd, b: 0x68 }, @@ -247,16 +147,25 @@ impl Default for NormalColors { magenta: Rgb { r: 0xb2, g: 0x94, b: 0xbb }, cyan: Rgb { r: 0x8a, g: 0xbe, b: 0xb7 }, white: Rgb { r: 0xc5, g: 0xc8, b: 0xc6 }, - }) + } } } -#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] -struct BrightColors(AnsiColors); +#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq)] +pub struct BrightColors { + pub black: Rgb, + pub red: Rgb, + pub green: Rgb, + pub yellow: Rgb, + pub blue: Rgb, + pub magenta: Rgb, + pub cyan: Rgb, + pub white: Rgb, +} impl Default for BrightColors { fn default() -> Self { - BrightColors(AnsiColors { + BrightColors { black: Rgb { r: 0x66, g: 0x66, b: 0x66 }, red: Rgb { r: 0xd5, g: 0x4e, b: 0x53 }, green: Rgb { r: 0xb9, g: 0xca, b: 0x4a }, @@ -265,6 +174,18 @@ impl Default for BrightColors { magenta: Rgb { r: 0xc3, g: 0x97, b: 0xd8 }, cyan: Rgb { r: 0x70, g: 0xc0, b: 0xb1 }, white: Rgb { r: 0xea, g: 0xea, b: 0xea }, - }) + } } } + +#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] +pub struct DimColors { + pub black: Rgb, + pub red: Rgb, + pub green: Rgb, + pub yellow: Rgb, + pub blue: Rgb, + pub magenta: Rgb, + pub cyan: Rgb, + pub white: Rgb, +} diff --git a/alacritty_terminal/src/config/mod.rs b/alacritty_terminal/src/config/mod.rs index f3221920..cbe56057 100644 --- a/alacritty_terminal/src/config/mod.rs +++ b/alacritty_terminal/src/config/mod.rs @@ -1,11 +1,10 @@ use std::cmp::max; use std::collections::HashMap; -use std::fmt::Display; use std::path::PathBuf; -use log::error; -use serde::{Deserialize, Deserializer}; -use serde_yaml::Value; +use serde::Deserialize; + +use alacritty_config_derive::ConfigDeserialize; mod bell; mod colors; @@ -17,132 +16,103 @@ pub use crate::config::bell::{BellAnimation, BellConfig}; pub use crate::config::colors::Colors; pub use crate::config::scrolling::Scrolling; -pub const LOG_TARGET_CONFIG: &str = "alacritty_config"; -const DEFAULT_CURSOR_THICKNESS: f32 = 0.15; -const MAX_SCROLLBACK_LINES: u32 = 100_000; +pub const LOG_TARGET_CONFIG: &str = "alacritty_config_derive"; const MIN_BLINK_INTERVAL: u64 = 10; pub type MockConfig = Config<HashMap<String, serde_yaml::Value>>; /// Top-level config type. -#[derive(Debug, PartialEq, Default, Deserialize)] +#[derive(ConfigDeserialize, Debug, PartialEq, Default)] pub struct Config<T> { /// TERM env variable. - #[serde(default, deserialize_with = "failure_default")] pub env: HashMap<String, String>, /// Should draw bold text with brighter colors instead of bold font. - #[serde(default, deserialize_with = "failure_default")] - draw_bold_text_with_bright_colors: bool, + pub draw_bold_text_with_bright_colors: bool, - #[serde(default, deserialize_with = "failure_default")] pub colors: Colors, - #[serde(default, deserialize_with = "failure_default")] pub selection: Selection, /// Path to a shell program to run on startup. - #[serde(default, deserialize_with = "failure_default")] pub shell: Option<Program>, - /// Bell configuration. - #[serde(default, deserialize_with = "failure_default")] - bell: BellConfig, - /// How much scrolling history to keep. - #[serde(default, deserialize_with = "failure_default")] pub scrolling: Scrolling, /// Cursor configuration. - #[serde(default, deserialize_with = "failure_default")] pub cursor: Cursor, /// Shell startup directory. - #[serde(default, deserialize_with = "option_explicit_none")] pub working_directory: Option<PathBuf>, /// Additional configuration options not directly required by the terminal. - #[serde(flatten)] + #[config(flatten)] pub ui_config: T, /// Remain open after child process exits. - #[serde(skip)] + #[config(skip)] pub hold: bool, - // TODO: DEPRECATED + /// Bell configuration. + bell: BellConfig, + #[cfg(windows)] - #[serde(default, deserialize_with = "failure_default")] + #[config(deprecated = "recompile with winpty feature or remove this setting")] pub winpty_backend: bool, - // TODO: DEPRECATED - #[serde(default, deserialize_with = "failure_default")] + #[config(deprecated = "use `bell` instead")] pub visual_bell: Option<BellConfig>, - - // TODO: REMOVED - #[serde(default, deserialize_with = "failure_default")] - pub tabspaces: Option<usize>, } impl<T> Config<T> { #[inline] - pub fn draw_bold_text_with_bright_colors(&self) -> bool { - self.draw_bold_text_with_bright_colors - } - - #[inline] pub fn bell(&self) -> &BellConfig { self.visual_bell.as_ref().unwrap_or(&self.bell) } } -#[serde(default)] -#[derive(Deserialize, Default, Clone, Debug, PartialEq, Eq)] +#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq)] pub struct Selection { - #[serde(deserialize_with = "failure_default")] - semantic_escape_chars: EscapeChars, - #[serde(deserialize_with = "failure_default")] + pub semantic_escape_chars: String, pub save_to_clipboard: bool, } -impl Selection { - pub fn semantic_escape_chars(&self) -> &str { - &self.semantic_escape_chars.0 - } -} - -#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] -struct EscapeChars(String); - -impl Default for EscapeChars { +impl Default for Selection { fn default() -> Self { - EscapeChars(String::from(",│`|:\"' ()[]{}<>\t")) + Self { + semantic_escape_chars: String::from(",│`|:\"' ()[]{}<>\t"), + save_to_clipboard: Default::default(), + } } } -#[serde(default)] -#[derive(Deserialize, Copy, Clone, Debug, PartialEq)] +#[derive(ConfigDeserialize, Copy, Clone, Debug, PartialEq)] pub struct Cursor { - #[serde(deserialize_with = "failure_default")] pub style: ConfigCursorStyle, - #[serde(deserialize_with = "option_explicit_none")] pub vi_mode_style: Option<ConfigCursorStyle>, - #[serde(deserialize_with = "failure_default")] - blink_interval: BlinkInterval, - #[serde(deserialize_with = "deserialize_cursor_thickness")] + pub unfocused_hollow: bool, + thickness: Percentage, - #[serde(deserialize_with = "failure_default")] - unfocused_hollow: DefaultTrueBool, + blink_interval: u64, } -impl Cursor { - #[inline] - pub fn unfocused_hollow(self) -> bool { - self.unfocused_hollow.0 +impl Default for Cursor { + fn default() -> Self { + Self { + thickness: Percentage(0.15), + unfocused_hollow: true, + blink_interval: 750, + style: Default::default(), + vi_mode_style: Default::default(), + } } +} +impl Cursor { #[inline] - pub fn thickness(self) -> f64 { - self.thickness.0 as f64 + pub fn thickness(self) -> f32 { + self.thickness.as_f32() } #[inline] @@ -157,48 +127,7 @@ impl Cursor { #[inline] pub fn blink_interval(self) -> u64 { - max(self.blink_interval.0, MIN_BLINK_INTERVAL) - } -} - -impl Default for Cursor { - fn default() -> Self { - Self { - style: Default::default(), - vi_mode_style: Default::default(), - thickness: Percentage::new(DEFAULT_CURSOR_THICKNESS), - unfocused_hollow: Default::default(), - blink_interval: Default::default(), - } - } -} - -#[derive(Deserialize, Copy, Clone, Debug, PartialEq)] -struct BlinkInterval(u64); - -impl Default for BlinkInterval { - fn default() -> Self { - BlinkInterval(750) - } -} - -fn deserialize_cursor_thickness<'a, D>(deserializer: D) -> Result<Percentage, D::Error> -where - D: Deserializer<'a>, -{ - let value = Value::deserialize(deserializer)?; - match Percentage::deserialize(value) { - Ok(value) => Ok(value), - Err(err) => { - error!( - target: LOG_TARGET_CONFIG, - "Problem with config: {}, using default thickness value {}", - err, - DEFAULT_CURSOR_THICKNESS - ); - - Ok(Percentage::new(DEFAULT_CURSOR_THICKNESS)) - }, + max(self.blink_interval, MIN_BLINK_INTERVAL) } } @@ -206,17 +135,12 @@ where #[derive(Deserialize, Debug, Copy, Clone, PartialEq, Eq)] pub enum ConfigCursorStyle { Shape(CursorShape), - WithBlinking { - #[serde(default, deserialize_with = "failure_default")] - shape: CursorShape, - #[serde(default, deserialize_with = "failure_default")] - blinking: CursorBlinking, - }, + WithBlinking { shape: CursorShape, blinking: CursorBlinking }, } impl Default for ConfigCursorStyle { fn default() -> Self { - Self::WithBlinking { shape: CursorShape::default(), blinking: CursorBlinking::default() } + Self::Shape(CursorShape::default()) } } @@ -241,7 +165,7 @@ impl From<ConfigCursorStyle> for CursorStyle { } } -#[derive(Deserialize, Debug, Copy, Clone, PartialEq, Eq)] +#[derive(ConfigDeserialize, Debug, Copy, Clone, PartialEq, Eq)] pub enum CursorBlinking { Never, Off, @@ -275,11 +199,7 @@ impl Into<bool> for CursorBlinking { #[derive(Deserialize, Debug, Clone, PartialEq, Eq)] pub enum Program { Just(String), - WithArgs { - program: String, - #[serde(default, deserialize_with = "failure_default")] - args: Vec<String>, - }, + WithArgs { program: String, args: Vec<String> }, } impl Program { @@ -299,9 +219,15 @@ impl Program { } /// Wrapper around f32 that represents a percentage value between 0.0 and 1.0. -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Deserialize, Clone, Copy, Debug, PartialEq)] pub struct Percentage(f32); +impl Default for Percentage { + fn default() -> Self { + Percentage(1.0) + } +} + impl Percentage { pub fn new(value: f32) -> Self { Percentage(if value < 0.0 { @@ -317,55 +243,3 @@ impl Percentage { self.0 } } - -impl Default for Percentage { - fn default() -> Self { - Percentage(1.0) - } -} - -impl<'a> Deserialize<'a> for Percentage { - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where - D: Deserializer<'a>, - { - Ok(Percentage::new(f32::deserialize(deserializer)?)) - } -} - -#[derive(Deserialize, Copy, Clone, Debug, PartialEq, Eq)] -struct DefaultTrueBool(bool); - -impl Default for DefaultTrueBool { - fn default() -> Self { - DefaultTrueBool(true) - } -} - -fn fallback_default<T, E>(err: E) -> T -where - T: Default, - E: Display, -{ - error!(target: LOG_TARGET_CONFIG, "Problem with config: {}; using default value", err); - T::default() -} - -pub fn failure_default<'a, D, T>(deserializer: D) -> Result<T, D::Error> -where - D: Deserializer<'a>, - T: Deserialize<'a> + Default, -{ - Ok(T::deserialize(Value::deserialize(deserializer)?).unwrap_or_else(fallback_default)) -} - -pub fn option_explicit_none<'de, T, D>(deserializer: D) -> Result<Option<T>, D::Error> -where - D: Deserializer<'de>, - T: Deserialize<'de> + Default, -{ - Ok(match Value::deserialize(deserializer)? { - Value::String(ref value) if value.to_lowercase() == "none" => None, - value => Some(T::deserialize(value).unwrap_or_else(fallback_default)), - }) -} diff --git a/alacritty_terminal/src/config/scrolling.rs b/alacritty_terminal/src/config/scrolling.rs index 136e9389..159b0f44 100644 --- a/alacritty_terminal/src/config/scrolling.rs +++ b/alacritty_terminal/src/config/scrolling.rs @@ -1,24 +1,23 @@ -use log::error; +use serde::de::Error as SerdeError; use serde::{Deserialize, Deserializer}; -use crate::config::{failure_default, LOG_TARGET_CONFIG, MAX_SCROLLBACK_LINES}; +use alacritty_config_derive::ConfigDeserialize; + +/// Maximum scrollback amount configurable. +const MAX_SCROLLBACK_LINES: u32 = 100_000; /// Struct for scrolling related settings. -#[serde(default)] -#[derive(Deserialize, Copy, Clone, Default, Debug, PartialEq, Eq)] +#[derive(ConfigDeserialize, Copy, Clone, Debug, PartialEq, Eq)] pub struct Scrolling { - #[serde(deserialize_with = "failure_default")] - history: ScrollingHistory, - #[serde(deserialize_with = "failure_default")] - multiplier: ScrollingMultiplier, + pub multiplier: u8, - // TODO: REMOVED - #[serde(deserialize_with = "failure_default")] - pub auto_scroll: Option<bool>, + history: ScrollingHistory, +} - // TODO: DEPRECATED - #[serde(deserialize_with = "failure_default")] - faux_multiplier: Option<ScrollingMultiplier>, +impl Default for Scrolling { + fn default() -> Self { + Self { multiplier: 3, history: Default::default() } + } } impl Scrolling { @@ -26,29 +25,12 @@ impl Scrolling { self.history.0 } - pub fn multiplier(self) -> u8 { - self.multiplier.0 - } - - pub fn faux_multiplier(self) -> Option<u8> { - self.faux_multiplier.map(|sm| sm.0) - } - // Update the history size, used in ref tests. pub fn set_history(&mut self, history: u32) { self.history = ScrollingHistory(history); } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize)] -struct ScrollingMultiplier(u8); - -impl Default for ScrollingMultiplier { - fn default() -> Self { - Self(3) - } -} - #[derive(Copy, Clone, Debug, PartialEq, Eq)] struct ScrollingHistory(u32); @@ -59,33 +41,19 @@ impl Default for ScrollingHistory { } impl<'de> Deserialize<'de> for ScrollingHistory { - fn deserialize<D>(deserializer: D) -> ::std::result::Result<Self, D::Error> + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>, { - let value = serde_yaml::Value::deserialize(deserializer)?; - match u32::deserialize(value) { - Ok(lines) => { - if lines > MAX_SCROLLBACK_LINES { - error!( - target: LOG_TARGET_CONFIG, - "Problem with config: scrollback size is {}, but expected a maximum of \ - {}; using {1} instead", - lines, - MAX_SCROLLBACK_LINES, - ); - Ok(ScrollingHistory(MAX_SCROLLBACK_LINES)) - } else { - Ok(ScrollingHistory(lines)) - } - }, - Err(err) => { - error!( - target: LOG_TARGET_CONFIG, - "Problem with config: {}; using default value", err - ); - Ok(Default::default()) - }, + let lines = u32::deserialize(deserializer)?; + + if lines > MAX_SCROLLBACK_LINES { + Err(SerdeError::custom(format!( + "exceeded maximum scrolling history ({}/{})", + lines, MAX_SCROLLBACK_LINES + ))) + } else { + Ok(Self(lines)) } } } |