diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2025-08-27 11:01:59 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-08-27 11:02:04 +0300 |
| commit | 178469301b846eb9e569a029819dd03387e26379 (patch) | |
| tree | bcacf43369ee061fa3242a4d6eeb383de1c8e70d | |
| parent | c637d4ce9978d2ceb9aa678c37dd69374d479bd6 (diff) | |
| download | niri-178469301b846eb9e569a029819dd03387e26379.tar.gz niri-178469301b846eb9e569a029819dd03387e26379.tar.bz2 niri-178469301b846eb9e569a029819dd03387e26379.zip | |
config: Extract misc
| -rw-r--r-- | niri-config/src/lib.rs | 168 | ||||
| -rw-r--r-- | niri-config/src/misc.rs | 169 |
2 files changed, 171 insertions, 166 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs index dfc9ab2d..0888df61 100644 --- a/niri-config/src/lib.rs +++ b/niri-config/src/lib.rs @@ -6,7 +6,6 @@ use std::fs::{self, File}; use std::io::Write; use std::path::{Path, PathBuf}; -use knuffel::errors::DecodeError; use miette::{Context, IntoDiagnostic}; pub mod animations; @@ -17,6 +16,7 @@ pub mod gestures; pub mod input; pub mod layer_rule; pub mod layout; +pub mod misc; pub mod output; pub mod utils; pub mod window_rule; @@ -31,6 +31,7 @@ pub use crate::gestures::Gestures; pub use crate::input::{Input, ModKey, ScrollMethod, TrackLayout, WarpMouseToFocusMode, Xkb}; pub use crate::layer_rule::LayerRule; pub use crate::layout::*; +pub use crate::misc::*; pub use crate::output::{Output, OutputName, Outputs, Position, Vrr}; pub use crate::utils::FloatOrInt; pub use crate::window_rule::{FloatingPosition, RelativeTo, WindowRule}; @@ -89,120 +90,6 @@ pub struct Config { pub workspaces: Vec<Workspace>, } -#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)] -pub struct SpawnAtStartup { - #[knuffel(arguments)] - pub command: Vec<String>, -} - -#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)] -pub struct SpawnShAtStartup { - #[knuffel(argument)] - pub command: String, -} - -#[derive(knuffel::Decode, Debug, PartialEq)] -pub struct Cursor { - #[knuffel(child, unwrap(argument), default = String::from("default"))] - pub xcursor_theme: String, - #[knuffel(child, unwrap(argument), default = 24)] - pub xcursor_size: u8, - #[knuffel(child)] - pub hide_when_typing: bool, - #[knuffel(child, unwrap(argument))] - pub hide_after_inactive_ms: Option<u32>, -} - -impl Default for Cursor { - fn default() -> Self { - Self { - xcursor_theme: String::from("default"), - xcursor_size: 24, - hide_when_typing: false, - hide_after_inactive_ms: None, - } - } -} - -#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)] -pub struct HotkeyOverlay { - #[knuffel(child)] - pub skip_at_startup: bool, - #[knuffel(child)] - pub hide_not_bound: bool, -} - -#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)] -pub struct ConfigNotification { - #[knuffel(child)] - pub disable_failed: bool, -} - -#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)] -pub struct Clipboard { - #[knuffel(child)] - pub disable_primary: bool, -} - -#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] -pub struct Overview { - #[knuffel(child, unwrap(argument), default = Self::default().zoom)] - pub zoom: FloatOrInt<0, 1>, - #[knuffel(child, default = Self::default().backdrop_color)] - pub backdrop_color: Color, - #[knuffel(child, default)] - pub workspace_shadow: appearance::WorkspaceShadow, -} - -impl Default for Overview { - fn default() -> Self { - Self { - zoom: FloatOrInt(0.5), - backdrop_color: appearance::DEFAULT_BACKDROP_COLOR, - workspace_shadow: appearance::WorkspaceShadow::default(), - } - } -} - -#[derive(knuffel::Decode, Debug, Default, Clone, PartialEq, Eq)] -pub struct Environment(#[knuffel(children)] pub Vec<EnvironmentVariable>); - -#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)] -pub struct EnvironmentVariable { - #[knuffel(node_name)] - pub name: String, - #[knuffel(argument)] - pub value: Option<String>, -} - -#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)] -pub struct XwaylandSatellite { - #[knuffel(child)] - pub off: bool, - #[knuffel(child, unwrap(argument), default = Self::default().path)] - pub path: String, -} - -impl Default for XwaylandSatellite { - fn default() -> Self { - Self { - off: false, - path: String::from("xwayland-satellite"), - } - } -} - -#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)] -pub struct Workspace { - #[knuffel(argument)] - pub name: WorkspaceName, - #[knuffel(child, unwrap(argument))] - pub open_on_output: Option<String>, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct WorkspaceName(pub String); - #[derive(Debug, Clone)] pub enum ConfigPath { /// Explicitly set config path. @@ -345,57 +232,6 @@ impl Default for Config { } } -impl<S: knuffel::traits::ErrorSpan> knuffel::DecodeScalar<S> for WorkspaceName { - fn type_check( - type_name: &Option<knuffel::span::Spanned<knuffel::ast::TypeName, S>>, - ctx: &mut knuffel::decode::Context<S>, - ) { - if let Some(type_name) = &type_name { - ctx.emit_error(DecodeError::unexpected( - type_name, - "type name", - "no type name expected for this node", - )); - } - } - - fn raw_decode( - val: &knuffel::span::Spanned<knuffel::ast::Literal, S>, - ctx: &mut knuffel::decode::Context<S>, - ) -> Result<WorkspaceName, DecodeError<S>> { - #[derive(Debug)] - struct WorkspaceNameSet(Vec<String>); - match &**val { - knuffel::ast::Literal::String(ref s) => { - let mut name_set: Vec<String> = match ctx.get::<WorkspaceNameSet>() { - Some(h) => h.0.clone(), - None => Vec::new(), - }; - - if name_set.iter().any(|name| name.eq_ignore_ascii_case(s)) { - ctx.emit_error(DecodeError::unexpected( - val, - "named workspace", - format!("duplicate named workspace: {s}"), - )); - return Ok(Self(String::new())); - } - - name_set.push(s.to_string()); - ctx.set(WorkspaceNameSet(name_set)); - Ok(Self(s.clone().into())) - } - _ => { - ctx.emit_error(DecodeError::unsupported( - val, - "workspace names must be strings", - )); - Ok(Self(String::new())) - } - } - } -} - #[cfg(test)] mod tests { use insta::assert_debug_snapshot; diff --git a/niri-config/src/misc.rs b/niri-config/src/misc.rs new file mode 100644 index 00000000..444fe772 --- /dev/null +++ b/niri-config/src/misc.rs @@ -0,0 +1,169 @@ +use knuffel::errors::DecodeError; + +use crate::appearance::{Color, WorkspaceShadow, DEFAULT_BACKDROP_COLOR}; +use crate::FloatOrInt; + +#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)] +pub struct SpawnAtStartup { + #[knuffel(arguments)] + pub command: Vec<String>, +} + +#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)] +pub struct SpawnShAtStartup { + #[knuffel(argument)] + pub command: String, +} + +#[derive(knuffel::Decode, Debug, PartialEq)] +pub struct Cursor { + #[knuffel(child, unwrap(argument), default = String::from("default"))] + pub xcursor_theme: String, + #[knuffel(child, unwrap(argument), default = 24)] + pub xcursor_size: u8, + #[knuffel(child)] + pub hide_when_typing: bool, + #[knuffel(child, unwrap(argument))] + pub hide_after_inactive_ms: Option<u32>, +} + +impl Default for Cursor { + fn default() -> Self { + Self { + xcursor_theme: String::from("default"), + xcursor_size: 24, + hide_when_typing: false, + hide_after_inactive_ms: None, + } + } +} + +#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)] +pub struct HotkeyOverlay { + #[knuffel(child)] + pub skip_at_startup: bool, + #[knuffel(child)] + pub hide_not_bound: bool, +} + +#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)] +pub struct ConfigNotification { + #[knuffel(child)] + pub disable_failed: bool, +} + +#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)] +pub struct Clipboard { + #[knuffel(child)] + pub disable_primary: bool, +} + +#[derive(knuffel::Decode, Debug, Clone, Copy, PartialEq)] +pub struct Overview { + #[knuffel(child, unwrap(argument), default = Self::default().zoom)] + pub zoom: FloatOrInt<0, 1>, + #[knuffel(child, default = Self::default().backdrop_color)] + pub backdrop_color: Color, + #[knuffel(child, default)] + pub workspace_shadow: WorkspaceShadow, +} + +impl Default for Overview { + fn default() -> Self { + Self { + zoom: FloatOrInt(0.5), + backdrop_color: DEFAULT_BACKDROP_COLOR, + workspace_shadow: WorkspaceShadow::default(), + } + } +} + +#[derive(knuffel::Decode, Debug, Default, Clone, PartialEq, Eq)] +pub struct Environment(#[knuffel(children)] pub Vec<EnvironmentVariable>); + +#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)] +pub struct EnvironmentVariable { + #[knuffel(node_name)] + pub name: String, + #[knuffel(argument)] + pub value: Option<String>, +} + +#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)] +pub struct XwaylandSatellite { + #[knuffel(child)] + pub off: bool, + #[knuffel(child, unwrap(argument), default = Self::default().path)] + pub path: String, +} + +impl Default for XwaylandSatellite { + fn default() -> Self { + Self { + off: false, + path: String::from("xwayland-satellite"), + } + } +} + +#[derive(knuffel::Decode, Debug, Clone, PartialEq, Eq)] +pub struct Workspace { + #[knuffel(argument)] + pub name: WorkspaceName, + #[knuffel(child, unwrap(argument))] + pub open_on_output: Option<String>, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct WorkspaceName(pub String); + +impl<S: knuffel::traits::ErrorSpan> knuffel::DecodeScalar<S> for WorkspaceName { + fn type_check( + type_name: &Option<knuffel::span::Spanned<knuffel::ast::TypeName, S>>, + ctx: &mut knuffel::decode::Context<S>, + ) { + if let Some(type_name) = &type_name { + ctx.emit_error(DecodeError::unexpected( + type_name, + "type name", + "no type name expected for this node", + )); + } + } + + fn raw_decode( + val: &knuffel::span::Spanned<knuffel::ast::Literal, S>, + ctx: &mut knuffel::decode::Context<S>, + ) -> Result<WorkspaceName, DecodeError<S>> { + #[derive(Debug)] + struct WorkspaceNameSet(Vec<String>); + match &**val { + knuffel::ast::Literal::String(ref s) => { + let mut name_set: Vec<String> = match ctx.get::<WorkspaceNameSet>() { + Some(h) => h.0.clone(), + None => Vec::new(), + }; + + if name_set.iter().any(|name| name.eq_ignore_ascii_case(s)) { + ctx.emit_error(DecodeError::unexpected( + val, + "named workspace", + format!("duplicate named workspace: {s}"), + )); + return Ok(Self(String::new())); + } + + name_set.push(s.to_string()); + ctx.set(WorkspaceNameSet(name_set)); + Ok(Self(s.clone().into())) + } + _ => { + ctx.emit_error(DecodeError::unsupported( + val, + "workspace names must be strings", + )); + Ok(Self(String::new())) + } + } + } +} |
