config: add window-rule infrastructure
This commit is contained in:
parent
a6257910bb
commit
59f8acdfde
26 changed files with 1829 additions and 38 deletions
|
|
@ -39,6 +39,9 @@ mod tearing;
|
|||
mod theme;
|
||||
mod ui_drag;
|
||||
mod vrr;
|
||||
mod window_match;
|
||||
mod window_rule;
|
||||
mod window_type;
|
||||
mod xwayland;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ use {
|
|||
theme::ThemeParser,
|
||||
ui_drag::UiDragParser,
|
||||
vrr::VrrParser,
|
||||
window_rule::WindowRulesParser,
|
||||
xwayland::XwaylandParser,
|
||||
},
|
||||
spanned::SpannedErrorExt,
|
||||
|
|
@ -121,7 +122,14 @@ impl Parser for ConfigParser<'_> {
|
|||
ui_drag_val,
|
||||
xwayland_val,
|
||||
),
|
||||
(color_management_val, float_val, actions_val, max_action_depth_val, client_rules_val),
|
||||
(
|
||||
color_management_val,
|
||||
float_val,
|
||||
actions_val,
|
||||
max_action_depth_val,
|
||||
client_rules_val,
|
||||
window_rules_val,
|
||||
),
|
||||
) = ext.extract((
|
||||
(
|
||||
opt(val("keymap")),
|
||||
|
|
@ -165,6 +173,7 @@ impl Parser for ConfigParser<'_> {
|
|||
opt(val("actions")),
|
||||
recover(opt(int("max-action-depth"))),
|
||||
opt(val("clients")),
|
||||
opt(val("windows")),
|
||||
),
|
||||
))?;
|
||||
let mut keymap = None;
|
||||
|
|
@ -428,6 +437,13 @@ impl Parser for ConfigParser<'_> {
|
|||
Err(e) => log::warn!("Could not parse the client rules: {}", self.0.error(e)),
|
||||
}
|
||||
}
|
||||
let mut window_rules = vec![];
|
||||
if let Some(value) = window_rules_val {
|
||||
match value.parse(&mut WindowRulesParser(self.0)) {
|
||||
Ok(v) => window_rules = v,
|
||||
Err(e) => log::warn!("Could not parse the window rules: {}", self.0.error(e)),
|
||||
}
|
||||
}
|
||||
Ok(Config {
|
||||
keymap,
|
||||
repeat_rate,
|
||||
|
|
@ -463,6 +479,7 @@ impl Parser for ConfigParser<'_> {
|
|||
named_actions,
|
||||
max_action_depth,
|
||||
client_rules,
|
||||
window_rules,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
113
toml-config/src/config/parsers/window_match.rs
Normal file
113
toml-config/src/config/parsers/window_match.rs
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
use {
|
||||
crate::{
|
||||
config::{
|
||||
GenericMatch, MatchExactly, WindowMatch,
|
||||
context::Context,
|
||||
extractor::{Extractor, ExtractorError, arr, n32, opt, str, val},
|
||||
parser::{DataType, ParseResult, Parser, UnexpectedDataType},
|
||||
parsers::window_type::{WindowTypeParser, WindowTypeParserError},
|
||||
},
|
||||
toml::{
|
||||
toml_span::{DespanExt, Span, Spanned},
|
||||
toml_value::Value,
|
||||
},
|
||||
},
|
||||
indexmap::IndexMap,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WindowMatchParserError {
|
||||
#[error(transparent)]
|
||||
Expected(#[from] UnexpectedDataType),
|
||||
#[error(transparent)]
|
||||
Extract(#[from] ExtractorError),
|
||||
#[error(transparent)]
|
||||
WindowTypes(#[from] WindowTypeParserError),
|
||||
}
|
||||
|
||||
pub struct WindowMatchParser<'a>(pub &'a Context<'a>);
|
||||
|
||||
impl Parser for WindowMatchParser<'_> {
|
||||
type Value = WindowMatch;
|
||||
type Error = WindowMatchParserError;
|
||||
const EXPECTED: &'static [DataType] = &[DataType::Table];
|
||||
|
||||
fn parse_table(
|
||||
&mut self,
|
||||
span: Span,
|
||||
table: &IndexMap<Spanned<String>, Spanned<Value>>,
|
||||
) -> ParseResult<Self> {
|
||||
let mut ext = Extractor::new(self.0, span, table);
|
||||
let ((name, not_val, all_val, any_val, exactly_val, types_val),) = ext.extract(((
|
||||
opt(str("name")),
|
||||
opt(val("not")),
|
||||
opt(arr("all")),
|
||||
opt(arr("any")),
|
||||
opt(val("exactly")),
|
||||
opt(val("types")),
|
||||
),))?;
|
||||
let mut not = None;
|
||||
if let Some(value) = not_val {
|
||||
not = Some(Box::new(value.parse(&mut WindowMatchParser(self.0))?));
|
||||
}
|
||||
macro_rules! list {
|
||||
($val:expr) => {{
|
||||
let mut list = None;
|
||||
if let Some(value) = $val {
|
||||
let mut res = vec![];
|
||||
for value in value.value {
|
||||
res.push(value.parse(&mut WindowMatchParser(self.0))?);
|
||||
}
|
||||
list = Some(res);
|
||||
}
|
||||
list
|
||||
}};
|
||||
}
|
||||
let all = list!(all_val);
|
||||
let any = list!(any_val);
|
||||
let mut types = None;
|
||||
if let Some(value) = types_val {
|
||||
types = Some(value.parse_map(&mut WindowTypeParser)?);
|
||||
}
|
||||
let mut exactly = None;
|
||||
if let Some(value) = exactly_val {
|
||||
exactly = Some(value.parse(&mut WindowMatchExactlyParser(self.0))?);
|
||||
}
|
||||
Ok(WindowMatch {
|
||||
generic: GenericMatch {
|
||||
name: name.despan_into(),
|
||||
not,
|
||||
all,
|
||||
any,
|
||||
exactly,
|
||||
},
|
||||
types,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WindowMatchExactlyParser<'a>(pub &'a Context<'a>);
|
||||
|
||||
impl Parser for WindowMatchExactlyParser<'_> {
|
||||
type Value = MatchExactly<WindowMatch>;
|
||||
type Error = WindowMatchParserError;
|
||||
const EXPECTED: &'static [DataType] = &[DataType::Table];
|
||||
|
||||
fn parse_table(
|
||||
&mut self,
|
||||
span: Span,
|
||||
table: &IndexMap<Spanned<String>, Spanned<Value>>,
|
||||
) -> ParseResult<Self> {
|
||||
let mut ext = Extractor::new(self.0, span, table);
|
||||
let (num, list_val) = ext.extract((n32("num"), arr("list")))?;
|
||||
let mut list = vec![];
|
||||
for el in list_val.value {
|
||||
list.push(el.parse(&mut WindowMatchParser(self.0))?);
|
||||
}
|
||||
Ok(MatchExactly {
|
||||
num: num.value as _,
|
||||
list,
|
||||
})
|
||||
}
|
||||
}
|
||||
104
toml-config/src/config/parsers/window_rule.rs
Normal file
104
toml-config/src/config/parsers/window_rule.rs
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
use {
|
||||
crate::{
|
||||
config::{
|
||||
WindowMatch, WindowRule,
|
||||
context::Context,
|
||||
extractor::{Extractor, ExtractorError, opt, str, val},
|
||||
parser::{DataType, ParseResult, Parser, UnexpectedDataType},
|
||||
parsers::{
|
||||
action::{ActionParser, ActionParserError},
|
||||
window_match::{WindowMatchParser, WindowMatchParserError},
|
||||
},
|
||||
spanned::SpannedErrorExt,
|
||||
},
|
||||
toml::{
|
||||
toml_span::{DespanExt, Span, Spanned},
|
||||
toml_value::Value,
|
||||
},
|
||||
},
|
||||
indexmap::IndexMap,
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WindowRuleParserError {
|
||||
#[error(transparent)]
|
||||
Expected(#[from] UnexpectedDataType),
|
||||
#[error(transparent)]
|
||||
Extract(#[from] ExtractorError),
|
||||
#[error(transparent)]
|
||||
Match(#[from] WindowMatchParserError),
|
||||
#[error(transparent)]
|
||||
Action(ActionParserError),
|
||||
#[error(transparent)]
|
||||
Latch(ActionParserError),
|
||||
}
|
||||
|
||||
pub struct WindowRuleParser<'a>(pub &'a Context<'a>);
|
||||
|
||||
impl Parser for WindowRuleParser<'_> {
|
||||
type Value = WindowRule;
|
||||
type Error = WindowRuleParserError;
|
||||
const EXPECTED: &'static [DataType] = &[DataType::Table];
|
||||
|
||||
fn parse_table(
|
||||
&mut self,
|
||||
span: Span,
|
||||
table: &IndexMap<Spanned<String>, Spanned<Value>>,
|
||||
) -> ParseResult<Self> {
|
||||
let mut ext = Extractor::new(self.0, span, table);
|
||||
let (name, match_val, action_val, latch_val) = ext.extract((
|
||||
opt(str("name")),
|
||||
opt(val("match")),
|
||||
opt(val("action")),
|
||||
opt(val("latch")),
|
||||
))?;
|
||||
let mut action = None;
|
||||
if let Some(value) = action_val {
|
||||
action = Some(
|
||||
value
|
||||
.parse(&mut ActionParser(self.0))
|
||||
.map_spanned_err(WindowRuleParserError::Action)?,
|
||||
);
|
||||
}
|
||||
let mut latch = None;
|
||||
if let Some(value) = latch_val {
|
||||
latch = Some(
|
||||
value
|
||||
.parse(&mut ActionParser(self.0))
|
||||
.map_spanned_err(WindowRuleParserError::Latch)?,
|
||||
);
|
||||
}
|
||||
let match_ = match match_val {
|
||||
None => WindowMatch::default(),
|
||||
Some(m) => m.parse_map(&mut WindowMatchParser(self.0))?,
|
||||
};
|
||||
Ok(WindowRule {
|
||||
name: name.despan_into(),
|
||||
match_,
|
||||
action,
|
||||
latch,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WindowRulesParser<'a>(pub &'a Context<'a>);
|
||||
|
||||
impl Parser for WindowRulesParser<'_> {
|
||||
type Value = Vec<WindowRule>;
|
||||
type Error = WindowRuleParserError;
|
||||
const EXPECTED: &'static [DataType] = &[DataType::Array];
|
||||
|
||||
fn parse_array(&mut self, _span: Span, array: &[Spanned<Value>]) -> ParseResult<Self> {
|
||||
let mut res = vec![];
|
||||
for el in array {
|
||||
match el.parse(&mut WindowRuleParser(self.0)) {
|
||||
Ok(o) => res.push(o),
|
||||
Err(e) => {
|
||||
log::warn!("Could not parse window rule: {}", self.0.error(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
53
toml-config/src/config/parsers/window_type.rs
Normal file
53
toml-config/src/config/parsers/window_type.rs
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
use {
|
||||
crate::{
|
||||
config::parser::{DataType, ParseResult, Parser, UnexpectedDataType},
|
||||
toml::{
|
||||
toml_span::{Span, Spanned, SpannedExt},
|
||||
toml_value::Value,
|
||||
},
|
||||
},
|
||||
jay_config::{window, window::WindowType},
|
||||
thiserror::Error,
|
||||
};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WindowTypeParserError {
|
||||
#[error(transparent)]
|
||||
Expected(#[from] UnexpectedDataType),
|
||||
#[error("Unknown window type `{}`", .0)]
|
||||
UnknownWindowType(String),
|
||||
}
|
||||
|
||||
pub struct WindowTypeParser;
|
||||
|
||||
impl Parser for WindowTypeParser {
|
||||
type Value = WindowType;
|
||||
type Error = WindowTypeParserError;
|
||||
const EXPECTED: &'static [DataType] = &[DataType::Array, DataType::String];
|
||||
|
||||
fn parse_string(&mut self, span: Span, string: &str) -> ParseResult<Self> {
|
||||
let ty = match string {
|
||||
"none" => WindowType(0),
|
||||
"any" => WindowType(!0),
|
||||
"container" => window::CONTAINER,
|
||||
"placeholder" => window::PLACEHOLDER,
|
||||
"xdg-toplevel" => window::XDG_TOPLEVEL,
|
||||
"x-window" => window::X_WINDOW,
|
||||
"client-window" => window::CLIENT_WINDOW,
|
||||
_ => {
|
||||
return Err(
|
||||
WindowTypeParserError::UnknownWindowType(string.to_owned()).spanned(span)
|
||||
);
|
||||
}
|
||||
};
|
||||
Ok(ty)
|
||||
}
|
||||
|
||||
fn parse_array(&mut self, _span: Span, array: &[Spanned<Value>]) -> ParseResult<Self> {
|
||||
let mut ty = WindowType(0);
|
||||
for el in array {
|
||||
ty |= el.parse(&mut WindowTypeParser)?;
|
||||
}
|
||||
Ok(ty)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue