mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-18 13:55:23 -05:00
Fix replacing optional fields
This fixes an issue with the default `SerdeReplace` implementation where it would never recurse through options but always replace the entire option with the new value. Closes #7518.
This commit is contained in:
parent
8f57367ead
commit
5685ce8bf8
9 changed files with 81 additions and 14 deletions
|
@ -22,6 +22,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
- IME input lagging behind on X11
|
- IME input lagging behind on X11
|
||||||
- xdotool modifiers input not working correctly on X11
|
- xdotool modifiers input not working correctly on X11
|
||||||
- Parsing numbers fails for mouse bindings
|
- Parsing numbers fails for mouse bindings
|
||||||
|
- Some config options overriding each other in CLI/IPC
|
||||||
|
|
||||||
## 0.13.0
|
## 0.13.0
|
||||||
|
|
||||||
|
|
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -70,6 +70,7 @@ dependencies = [
|
||||||
name = "alacritty_config"
|
name = "alacritty_config"
|
||||||
version = "0.1.3-dev"
|
version = "0.1.3-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"alacritty_config_derive",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
"toml",
|
"toml",
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
use alacritty_config_derive::ConfigDeserialize;
|
use alacritty_config_derive::ConfigDeserialize;
|
||||||
|
|
||||||
/// Debugging options.
|
/// Debugging options.
|
||||||
|
@ -47,17 +45,17 @@ impl Default for Debug {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The renderer configuration options.
|
/// The renderer configuration options.
|
||||||
#[derive(Deserialize, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(ConfigDeserialize, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum RendererPreference {
|
pub enum RendererPreference {
|
||||||
/// OpenGL 3.3 renderer.
|
/// OpenGL 3.3 renderer.
|
||||||
#[serde(rename = "glsl3")]
|
#[config(rename = "glsl3")]
|
||||||
Glsl3,
|
Glsl3,
|
||||||
|
|
||||||
/// GLES 2 renderer, with optional extensions like dual source blending.
|
/// GLES 2 renderer, with optional extensions like dual source blending.
|
||||||
#[serde(rename = "gles2")]
|
#[config(rename = "gles2")]
|
||||||
Gles2,
|
Gles2,
|
||||||
|
|
||||||
/// Pure GLES 2 renderer.
|
/// Pure GLES 2 renderer.
|
||||||
#[serde(rename = "gles2_pure")]
|
#[config(rename = "gles2_pure")]
|
||||||
Gles2Pure,
|
Gles2Pure,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::error::Error;
|
||||||
use std::fmt::{self, Formatter};
|
use std::fmt::{self, Formatter};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use alacritty_config::SerdeReplace;
|
||||||
use alacritty_terminal::term::Config as TermConfig;
|
use alacritty_terminal::term::Config as TermConfig;
|
||||||
use alacritty_terminal::tty::{Options as PtyOptions, Shell};
|
use alacritty_terminal::tty::{Options as PtyOptions, Shell};
|
||||||
use log::{error, warn};
|
use log::{error, warn};
|
||||||
|
@ -656,6 +658,14 @@ impl From<Program> for Shell {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SerdeReplace for Program {
|
||||||
|
fn replace(&mut self, value: toml::Value) -> Result<(), Box<dyn Error>> {
|
||||||
|
*self = Self::deserialize(value)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct StringVisitor;
|
pub(crate) struct StringVisitor;
|
||||||
impl<'de> serde::de::Visitor<'de> for StringVisitor {
|
impl<'de> serde::de::Visitor<'de> for StringVisitor {
|
||||||
type Value = String;
|
type Value = String;
|
||||||
|
|
|
@ -3,10 +3,10 @@ use std::fmt::{self, Formatter};
|
||||||
use log::{error, warn};
|
use log::{error, warn};
|
||||||
use serde::de::{self, MapAccess, Visitor};
|
use serde::de::{self, MapAccess, Visitor};
|
||||||
use serde::{Deserialize, Deserializer, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
use winit::window::{Fullscreen, Theme};
|
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use winit::platform::macos::OptionAsAlt as WinitOptionAsAlt;
|
use winit::platform::macos::OptionAsAlt as WinitOptionAsAlt;
|
||||||
|
use winit::window::{Fullscreen, Theme as WinitTheme};
|
||||||
|
|
||||||
use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
|
use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
|
||||||
|
|
||||||
|
@ -31,9 +31,6 @@ pub struct WindowConfig {
|
||||||
#[config(skip)]
|
#[config(skip)]
|
||||||
pub embed: Option<u32>,
|
pub embed: Option<u32>,
|
||||||
|
|
||||||
/// System decorations theme variant.
|
|
||||||
pub decorations_theme_variant: Option<Theme>,
|
|
||||||
|
|
||||||
/// Spread out additional padding evenly.
|
/// Spread out additional padding evenly.
|
||||||
pub dynamic_padding: bool,
|
pub dynamic_padding: bool,
|
||||||
|
|
||||||
|
@ -62,6 +59,9 @@ pub struct WindowConfig {
|
||||||
|
|
||||||
/// Initial dimensions.
|
/// Initial dimensions.
|
||||||
dimensions: Dimensions,
|
dimensions: Dimensions,
|
||||||
|
|
||||||
|
/// System decorations theme variant.
|
||||||
|
decorations_theme_variant: Option<Theme>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for WindowConfig {
|
impl Default for WindowConfig {
|
||||||
|
@ -149,6 +149,10 @@ impl WindowConfig {
|
||||||
OptionAsAlt::None => WinitOptionAsAlt::None,
|
OptionAsAlt::None => WinitOptionAsAlt::None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn theme(&self) -> Option<WinitTheme> {
|
||||||
|
self.decorations_theme_variant.map(WinitTheme::from)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(ConfigDeserialize, Debug, Clone, PartialEq, Eq)]
|
#[derive(ConfigDeserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -292,3 +296,19 @@ pub enum OptionAsAlt {
|
||||||
#[default]
|
#[default]
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// System decorations theme variant.
|
||||||
|
#[derive(ConfigDeserialize, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum Theme {
|
||||||
|
Light,
|
||||||
|
Dark,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Theme> for WinitTheme {
|
||||||
|
fn from(theme: Theme) -> Self {
|
||||||
|
match theme {
|
||||||
|
Theme::Light => WinitTheme::Light,
|
||||||
|
Theme::Dark => WinitTheme::Dark,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -165,7 +165,7 @@ impl Window {
|
||||||
|
|
||||||
let window = window_builder
|
let window = window_builder
|
||||||
.with_title(&identity.title)
|
.with_title(&identity.title)
|
||||||
.with_theme(config.window.decorations_theme_variant)
|
.with_theme(config.window.theme())
|
||||||
.with_visible(false)
|
.with_visible(false)
|
||||||
.with_transparent(true)
|
.with_transparent(true)
|
||||||
.with_blur(config.window.blur)
|
.with_blur(config.window.blur)
|
||||||
|
|
|
@ -289,7 +289,7 @@ impl WindowContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always reload the theme to account for auto-theme switching.
|
// Always reload the theme to account for auto-theme switching.
|
||||||
self.display.window.set_theme(self.config.window.decorations_theme_variant);
|
self.display.window.set_theme(self.config.window.theme());
|
||||||
|
|
||||||
// Update display if either padding options or resize increments were changed.
|
// Update display if either padding options or resize increments were changed.
|
||||||
let window_config = &old_config.window;
|
let window_config = &old_config.window;
|
||||||
|
|
|
@ -12,3 +12,7 @@ rust-version = "1.70.0"
|
||||||
log = { version = "0.4.17", features = ["serde"] }
|
log = { version = "0.4.17", features = ["serde"] }
|
||||||
serde = "1.0.163"
|
serde = "1.0.163"
|
||||||
toml = "0.8.2"
|
toml = "0.8.2"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
alacritty_config_derive = { path = "../alacritty_config_derive" }
|
||||||
|
serde = { version = "1.0.163", features = ["derive"] }
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -9,6 +10,7 @@ pub trait SerdeReplace {
|
||||||
fn replace(&mut self, value: Value) -> Result<(), Box<dyn Error>>;
|
fn replace(&mut self, value: Value) -> Result<(), Box<dyn Error>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
macro_rules! impl_replace {
|
macro_rules! impl_replace {
|
||||||
($($ty:ty),*$(,)*) => {
|
($($ty:ty),*$(,)*) => {
|
||||||
$(
|
$(
|
||||||
|
@ -29,6 +31,7 @@ impl_replace!(
|
||||||
bool,
|
bool,
|
||||||
char,
|
char,
|
||||||
String,
|
String,
|
||||||
|
PathBuf,
|
||||||
LevelFilter,
|
LevelFilter,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -47,9 +50,12 @@ impl<'de, T: Deserialize<'de>> SerdeReplace for Vec<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, T: Deserialize<'de>> SerdeReplace for Option<T> {
|
impl<'de, T: SerdeReplace + Deserialize<'de>> SerdeReplace for Option<T> {
|
||||||
fn replace(&mut self, value: Value) -> Result<(), Box<dyn Error>> {
|
fn replace(&mut self, value: Value) -> Result<(), Box<dyn Error>> {
|
||||||
replace_simple(self, value)
|
match self {
|
||||||
|
Some(inner) => inner.replace(value),
|
||||||
|
None => replace_simple(self, value),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,3 +64,30 @@ impl<'de, T: Deserialize<'de>> SerdeReplace for HashMap<String, T> {
|
||||||
replace_simple(self, value)
|
replace_simple(self, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use crate as alacritty_config;
|
||||||
|
use alacritty_config_derive::ConfigDeserialize;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn replace_option() {
|
||||||
|
#[derive(ConfigDeserialize, Default, PartialEq, Eq, Debug)]
|
||||||
|
struct ReplaceOption {
|
||||||
|
a: usize,
|
||||||
|
b: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut subject: Option<ReplaceOption> = None;
|
||||||
|
|
||||||
|
let value: Value = toml::from_str("a=1").unwrap();
|
||||||
|
SerdeReplace::replace(&mut subject, value).unwrap();
|
||||||
|
|
||||||
|
let value: Value = toml::from_str("b=2").unwrap();
|
||||||
|
SerdeReplace::replace(&mut subject, value).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(subject, Some(ReplaceOption { a: 1, b: 2 }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue