Window definitions are parsed fully

This commit is contained in:
elkowar 2021-07-20 19:19:43 +02:00
parent dd5078b4be
commit 98cbbff7c9
No known key found for this signature in database
GPG key ID: E321AD71B1D1F27F
6 changed files with 216 additions and 78 deletions

View file

@ -0,0 +1,123 @@
use std::str::FromStr;
use anyhow::*;
use crate::{
enum_parse,
error::AstResult,
parser::{
ast::{Ast, AstIterator, Span},
from_ast::FromAstElementContent,
},
value::NumWithUnit,
};
use super::{attributes::Attributes, window_definition::EnumParseError};
pub type BackendWindowOptions = X11WindowOptions;
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
pub struct X11WindowOptions {
pub wm_ignore: bool,
pub sticky: bool,
pub window_type: EwwWindowType,
pub struts: StrutDefinition,
}
impl X11WindowOptions {
pub fn from_attrs(attrs: &mut Attributes) -> AstResult<Self> {
let struts = attrs.ast_optional("reserve")?;
let window_type = attrs.primitive_optional("windowtype")?;
Ok(X11WindowOptions {
wm_ignore: attrs.primitive_optional("wm-ignore")?.unwrap_or(window_type.is_none() && struts.is_none()),
window_type: window_type.unwrap_or_default(),
sticky: attrs.primitive_optional("sticky")?.unwrap_or(true),
struts: struts.unwrap_or_default(),
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, smart_default::SmartDefault, serde::Serialize)]
pub enum EwwWindowType {
#[default]
Dock,
Dialog,
Toolbar,
Normal,
Utility,
}
impl FromStr for EwwWindowType {
type Err = EnumParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
enum_parse! { "window type", s,
"dock" => Self::Dock,
"toolbar" => Self::Toolbar,
"dialog" => Self::Dialog,
"normal" => Self::Normal,
"utility" => Self::Utility,
}
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, smart_default::SmartDefault, serde::Serialize)]
pub enum Side {
#[default]
Top,
Left,
Right,
Bottom,
}
impl std::str::FromStr for Side {
type Err = EnumParseError;
fn from_str(s: &str) -> Result<Side, Self::Err> {
enum_parse! { "side", s,
"l" | "left" => Side::Left,
"r" | "right" => Side::Right,
"t" | "top" => Side::Top,
"b" | "bottom" => Side::Bottom,
}
}
}
// Surface definition if the backend for X11 is enable
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default, serde::Serialize)]
pub struct StrutDefinition {
pub side: Side,
pub dist: NumWithUnit,
}
impl FromAstElementContent for StrutDefinition {
fn get_element_name() -> &'static str {
"struts"
}
fn from_tail<I: Iterator<Item = Ast>>(span: Span, mut iter: AstIterator<I>) -> AstResult<Self> {
let mut attrs = iter.expect_key_values()?;
Ok(StrutDefinition { side: attrs.primitive_required("side")?, dist: attrs.primitive_required("distance")? })
}
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
pub struct WaylandWindowOptions {
pub exclusive: bool,
pub focusable: bool,
}
impl WaylandWindowOptions {
pub fn from_attrs(attrs: &mut Attributes) -> AstResult<Self> {
Ok(WaylandWindowOptions {
exclusive: attrs.primitive_optional("exclusive")?.unwrap_or(false),
focusable: attrs.primitive_optional("focusable")?.unwrap_or(false),
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
pub struct NoBackendWindowOptions;
impl NoBackendWindowOptions {
pub fn from_attrs(attrs: &mut Attributes) -> Result<Self> {
Ok(NoBackendWindowOptions)
}
}

View file

@ -4,7 +4,7 @@ use simplexpr::SimplExpr;
use super::{ use super::{
script_var_definition::ScriptVarDefinition, var_definition::VarDefinition, widget_definition::WidgetDefinition, script_var_definition::ScriptVarDefinition, var_definition::VarDefinition, widget_definition::WidgetDefinition,
widget_use::WidgetUse, widget_use::WidgetUse, window_definition::WindowDefinition,
}; };
use crate::{ use crate::{
config::script_var_definition::{PollScriptVar, TailScriptVar}, config::script_var_definition::{PollScriptVar, TailScriptVar},
@ -21,6 +21,7 @@ pub enum TopLevel {
VarDefinition(VarDefinition), VarDefinition(VarDefinition),
ScriptVarDefinition(ScriptVarDefinition), ScriptVarDefinition(ScriptVarDefinition),
WidgetDefinition(WidgetDefinition), WidgetDefinition(WidgetDefinition),
WindowDefinition(WindowDefinition),
} }
impl FromAst for TopLevel { impl FromAst for TopLevel {
@ -40,6 +41,9 @@ impl FromAst for TopLevel {
x if x == TailScriptVar::get_element_name() => { x if x == TailScriptVar::get_element_name() => {
Self::ScriptVarDefinition(ScriptVarDefinition::Tail(TailScriptVar::from_tail(span, iter)?)) Self::ScriptVarDefinition(ScriptVarDefinition::Tail(TailScriptVar::from_tail(span, iter)?))
} }
x if x == WindowDefinition::get_element_name() => {
Self::WindowDefinition(WindowDefinition::from_tail(span, iter)?)
}
x => return Err(AstError::UnknownToplevel(Some(sym_span), x.to_string())), x => return Err(AstError::UnknownToplevel(Some(sym_span), x.to_string())),
} }
}) })
@ -49,6 +53,7 @@ impl FromAst for TopLevel {
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize)] #[derive(Debug, PartialEq, Eq, Clone, serde::Serialize)]
pub struct Config { pub struct Config {
widget_definitions: HashMap<String, WidgetDefinition>, widget_definitions: HashMap<String, WidgetDefinition>,
window_definitions: HashMap<String, WindowDefinition>,
var_definitions: HashMap<VarName, VarDefinition>, var_definitions: HashMap<VarName, VarDefinition>,
script_vars: HashMap<VarName, ScriptVarDefinition>, script_vars: HashMap<VarName, ScriptVarDefinition>,
} }
@ -56,8 +61,12 @@ pub struct Config {
impl FromAst for Config { impl FromAst for Config {
fn from_ast(e: Ast) -> AstResult<Self> { fn from_ast(e: Ast) -> AstResult<Self> {
let list = e.as_list()?; let list = e.as_list()?;
let mut config = let mut config = Self {
Self { widget_definitions: HashMap::new(), var_definitions: HashMap::new(), script_vars: HashMap::new() }; widget_definitions: HashMap::new(),
window_definitions: HashMap::new(),
var_definitions: HashMap::new(),
script_vars: HashMap::new(),
};
for element in list { for element in list {
match TopLevel::from_ast(element)? { match TopLevel::from_ast(element)? {
TopLevel::VarDefinition(x) => { TopLevel::VarDefinition(x) => {
@ -69,6 +78,9 @@ impl FromAst for Config {
TopLevel::WidgetDefinition(x) => { TopLevel::WidgetDefinition(x) => {
config.widget_definitions.insert(x.name.clone(), x); config.widget_definitions.insert(x.name.clone(), x);
} }
TopLevel::WindowDefinition(x) => {
config.window_definitions.insert(x.name.clone(), x);
}
} }
} }
Ok(config) Ok(config)

View file

@ -1,4 +1,5 @@
pub mod attributes; pub mod attributes;
pub mod backend_window_options;
mod config; mod config;
pub mod config_parse_error; pub mod config_parse_error;
pub mod script_var_definition; pub mod script_var_definition;

View file

@ -13,9 +13,15 @@ Config(
], ],
widget: WidgetUse( widget: WidgetUse(
name: "text", name: "text",
attrs: { attrs: Attributes(
AttrName("text"): Literal(Span(99, 104, 0), DynVal("bla", None)), span: Span(99, 104, 0),
}, attrs: {
AttrName("text"): AttrEntry(
key_span: Span(99, 104, 0),
value: Literal(Span(99, 104, 0), DynVal("bla", None)),
),
},
),
children: [], children: [],
span: Span(99, 104, 0), span: Span(99, 104, 0),
), ),
@ -29,9 +35,15 @@ Config(
], ],
widget: WidgetUse( widget: WidgetUse(
name: "text", name: "text",
attrs: { attrs: Attributes(
AttrName("text"): Literal(Span(44, 51, 0), DynVal("heyho", None)), span: Span(44, 51, 0),
}, attrs: {
AttrName("text"): AttrEntry(
key_span: Span(44, 51, 0),
value: Literal(Span(44, 51, 0), DynVal("heyho", None)),
),
},
),
children: [], children: [],
span: Span(44, 51, 0), span: Span(44, 51, 0),
), ),
@ -39,6 +51,51 @@ Config(
args_span: Span(26, 31, 0), args_span: Span(26, 31, 0),
), ),
}, },
window_definitions: {
"some-window": WindowDefinition(
name: "some-window",
geometry: Some(WindowGeometry(
anchor_point: AnchorPoint(
x: START,
y: START,
),
offset: Coords(
x: Pixels(0),
y: Pixels(0),
),
size: Coords(
x: Percent(12),
y: Pixels(20),
),
)),
stacking: Foreground,
monitor_number: Some(12),
widget: WidgetUse(
name: "foo",
attrs: Attributes(
span: Span(509, 509, 513),
attrs: {
AttrName("arg"): AttrEntry(
key_span: Span(514, 518, 0),
value: Literal(Span(519, 524, 0), DynVal("bla", None)),
),
},
),
children: [],
span: Span(509, 525, 0),
),
resizable: true,
backend_options: X11WindowOptions(
wm_ignore: false,
sticky: true,
window_type: Dock,
struts: StrutDefinition(
side: Left,
dist: Pixels(30),
),
),
),
},
var_definitions: { var_definitions: {
VarName("some_var"): VarDefinition( VarName("some_var"): VarDefinition(
name: VarName("some_var"), name: VarName("some_var"),

View file

@ -18,6 +18,13 @@ fn test_config() {
(defvar some_var "bla") (defvar some_var "bla")
(defpollvar stuff :interval "12s" "date") (defpollvar stuff :interval "12s" "date")
(deftailvar stuff "tail -f stuff") (deftailvar stuff "tail -f stuff")
(defwindow some-window
:stacking "fg"
:monitor 12
:resizable true
:geometry (geometry :width "12%" :height "20px")
:reserve (struts :side "left" :distance "30px")
(foo :arg "bla"))
"#; "#;
let lexer = Lexer::new(0, input.to_string()); let lexer = Lexer::new(0, input.to_string());

View file

@ -12,20 +12,20 @@ use crate::{
value::{AttrName, NumWithUnit, VarName}, value::{AttrName, NumWithUnit, VarName},
}; };
use super::{widget_use::WidgetUse, window_geometry::WindowGeometry}; use super::{backend_window_options::BackendWindowOptions, widget_use::WidgetUse, window_geometry::WindowGeometry};
#[derive(Debug, Clone, serde::Serialize)] #[derive(Debug, Clone, serde::Serialize, PartialEq, Eq)]
pub struct EwwWindowDefinition { pub struct WindowDefinition {
pub name: String, pub name: String,
pub geometry: Option<WindowGeometry>, pub geometry: Option<WindowGeometry>,
pub stacking: WindowStacking, pub stacking: WindowStacking,
pub monitor_number: Option<i32>, pub monitor_number: Option<i32>,
pub widget: WidgetUse, pub widget: WidgetUse,
pub resizable: bool, pub resizable: bool,
// pub backend_options: BackendWindowOptions, pub backend_options: BackendWindowOptions,
} }
impl FromAstElementContent for EwwWindowDefinition { impl FromAstElementContent for WindowDefinition {
fn get_element_name() -> &'static str { fn get_element_name() -> &'static str {
"defwindow" "defwindow"
} }
@ -37,8 +37,9 @@ impl FromAstElementContent for EwwWindowDefinition {
let resizable = attrs.primitive_optional("resizable")?.unwrap_or(true); let resizable = attrs.primitive_optional("resizable")?.unwrap_or(true);
let stacking = attrs.primitive_optional("stacking")?.unwrap_or(WindowStacking::Foreground); let stacking = attrs.primitive_optional("stacking")?.unwrap_or(WindowStacking::Foreground);
let geometry = attrs.ast_optional("geometry")?; let geometry = attrs.ast_optional("geometry")?;
let backend_options = BackendWindowOptions::from_attrs(&mut attrs)?;
let widget = iter.expect_any()?; let widget = iter.expect_any()?;
Ok(Self { name, monitor_number, resizable, widget, stacking, geometry }) Ok(Self { name, monitor_number, resizable, widget, stacking, geometry, backend_options })
} }
} }
@ -76,69 +77,6 @@ macro_rules! enum_parse {
}; };
} }
#[derive(Debug, Clone, PartialEq, Eq, smart_default::SmartDefault)]
pub enum EwwWindowType {
#[default]
Dock,
Dialog,
Toolbar,
Normal,
Utility,
}
impl FromStr for EwwWindowType {
type Err = EnumParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
enum_parse! { "window type", s,
"dock" => Self::Dock,
"toolbar" => Self::Toolbar,
"dialog" => Self::Dialog,
"normal" => Self::Normal,
"utility" => Self::Utility,
}
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, smart_default::SmartDefault)]
pub enum Side {
#[default]
Top,
Left,
Right,
Bottom,
}
impl std::str::FromStr for Side {
type Err = EnumParseError;
fn from_str(s: &str) -> Result<Side, Self::Err> {
enum_parse! { "side", s,
"l" | "left" => Side::Left,
"r" | "right" => Side::Right,
"t" | "top" => Side::Top,
"b" | "bottom" => Side::Bottom,
}
}
}
// Surface definition if the backend for X11 is enable
#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
pub struct StrutDefinition {
pub side: Side,
pub dist: NumWithUnit,
}
impl FromAstElementContent for StrutDefinition {
fn get_element_name() -> &'static str {
"struts"
}
fn from_tail<I: Iterator<Item = Ast>>(span: Span, mut iter: AstIterator<I>) -> AstResult<Self> {
let mut attrs = iter.expect_key_values()?;
Ok(StrutDefinition { side: attrs.primitive_required("side")?, dist: attrs.primitive_required("distance")? })
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display, smart_default::SmartDefault, serde::Serialize)] #[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display, smart_default::SmartDefault, serde::Serialize)]
pub enum WindowStacking { pub enum WindowStacking {
#[default] #[default]