diff options
38 files changed, 1037 insertions, 1048 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c005e62..ae6deaea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Changed - Nonexistent config imports are ignored instead of raising an error +- Value for disabling logging with `config.log_level` is `Off` instead of `None` ### Fixed @@ -51,6 +52,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * `--dimensions` * `--position` - `live-shader-reload` feature +- Config option `dynamic_title`, you should use `window.dynamic_title` instead +- Config option `scrolling.faux_multiplier`, which was replaced by escape `CSI ? 1007 h/l` ## 0.6.0 @@ -25,6 +25,7 @@ dependencies = [ name = "alacritty" version = "0.7.0-dev" dependencies = [ + "alacritty_config_derive", "alacritty_terminal", "bitflags", "clap", @@ -54,9 +55,22 @@ dependencies = [ ] [[package]] +name = "alacritty_config_derive" +version = "0.1.0" +dependencies = [ + "log", + "proc-macro2", + "quote", + "serde", + "serde_yaml", + "syn", +] + +[[package]] name = "alacritty_terminal" version = "0.11.1-dev" dependencies = [ + "alacritty_config_derive", "base64", "bitflags", "libc", @@ -1077,6 +1091,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ "cfg-if", + "serde", ] [[package]] @@ -1794,9 +1809,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.8.13" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae3e2dd40a7cdc18ca80db804b7f461a39bb721160a85c9a1fa30134bf3c02a5" +checksum = "f7baae0a99f1a324984bcdc5f0718384c1f69775f1c7eec8b859b71b443e3fd7" dependencies = [ "dtoa", "linked-hash-map", @@ -1942,9 +1957,9 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" [[package]] name = "syn" -version = "1.0.46" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad5de3220ea04da322618ded2c42233d02baca219d6f160a3e9c87cda16c942" +checksum = "8833e20724c24de12bbaba5ad230ea61c3eafb05b881c7c9d3cfe8638b187e68" dependencies = [ "proc-macro2", "quote", @@ -2,6 +2,7 @@ members = [ "alacritty", "alacritty_terminal", + "alacritty_config_derive", ] [profile.release] diff --git a/alacritty.yml b/alacritty.yml index 72fbcf8c..89a1c65f 100644 --- a/alacritty.yml +++ b/alacritty.yml @@ -799,7 +799,7 @@ # Log level # # Values for `log_level`: - # - None + # - Off # - Error # - Warn # - Info 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<T>(option: &mut T, value: Option<T>) { - 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<Value, serde_yaml::Error> { 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<T: Eq> Binding<T> { } } -#[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<LevelFilter, D::Error> -where - D: Deserializer<'a>, -{ - Ok(match failure_default::<D, String>(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<i8>, + + /// Glyph offset within character cell. + pub glyph_offset: Delta<i8>, + + 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<i8>, - - /// Glyph offset within character cell. - #[serde(deserialize_with = "failure_default")] - pub glyph_offset: Delta<i8>, - - #[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<String>, } @@ -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<String>, - #[serde(deserialize_with = "failure_default")] style: Option<String>, } @@ -153,66 +109,37 @@ impl SecondaryFontDescription { } } -trait DeserializeSize: Sized { - fn deserialize<'a, D>(_: D) -> ::std::result::Result<Self, D::Error> - 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<Self, D::Error> +impl<'de> Deserialize<'de> for Size { + fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 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<E>(self, value: f64) -> ::std::result::Result<Self::Value, E> - where - E: ::serde::de::Error, - { - Ok(value) + fn visit_f64<E: de::Error>(self, value: f64) -> Result<Self::Value, E> { + Ok(Size(FontSize::new(value as f32))) } - fn visit_u64<E>(self, value: u64) -> ::std::result::Result<Self::Value, E> - where - E: ::serde::de::Error, - { - Ok(value as f64) + fn visit_u64<E: de::Error>(self, value: u64) -> Result<Self::Value, E> { + Ok(Size(FontSize::new(value as f32))) } } - let value = serde_yaml::Value::deserialize(deserializer)?; - let size = value - .deserialize_any(NumVisitor::<D> { _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<Config> { 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<PathBuf> { 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<Program>, /// 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<Option<Program>, 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 laun |