mirror of
https://github.com/elkowar/eww.git
synced 2024-09-19 07:37:18 +03:00
Support Multi-file configuration (#45)
* install pango in CI * <includes> xml support and EwwConfig merging * Moved EwwConfig changes after merge * Implemented relative paths * Implemented paths in error messages * Corrected include's error context message * Written merge_includes test, fixed a simple bug * Added "includes" label error check * cargo format * install pango in CI * <includes> xml support and EwwConfig merging * Moved EwwConfig changes after merge * Implemented relative paths * Implemented paths in error messages * Corrected include's error context message * Written merge_includes test, fixed a simple bug * Added "includes" label error check * cargo format * Removed outdated comments and unused imports * Fix dependency error * Updated docs to add the <includes> block * Removed unnecessary comment Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com> * Removed duplicated test block Should'nt be there in the first place. My bad. Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com> * Better error context handling in eww_config.rs Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com> * Better error context handling in eww_config.rs (again) Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com> * Removed unnecessary error check Co-authored-by: ElKowar <5300871+elkowar@users.noreply.github.com> Co-authored-by: elkowar <5300871+elkowar@users.noreply.github.com> Co-authored-by: druskus20@gmail.com <druskus20>
This commit is contained in:
parent
ac8bc7d8b5
commit
bc555900d3
@ -25,6 +25,10 @@ $HOME
|
||||
Your config structure should look like this:
|
||||
```xml
|
||||
<eww>
|
||||
<definitions>
|
||||
<!-- Put your <file>'s in here -->
|
||||
</definitions>
|
||||
|
||||
<definitions>
|
||||
<!-- Put your <def>'s in here -->
|
||||
</definitions>
|
||||
@ -38,7 +42,9 @@ Your config structure should look like this:
|
||||
</windows>
|
||||
</eww>
|
||||
```
|
||||
See [The `<definitons>` block](#the-definitions-block),
|
||||
See
|
||||
[The `<includes>` block](#the-includes-block),
|
||||
[The `<definitons>` block](#the-definitions-block),
|
||||
[Variables](#variables) and the
|
||||
[The `<windows>` block](#the-windows-block).
|
||||
|
||||
@ -107,6 +113,15 @@ If you don't want a set interval and instead want it to tail (run the script whe
|
||||
</script-var>
|
||||
</variables>
|
||||
```
|
||||
### The `<includes>` block
|
||||
Here you can include other config files so that they are merged together at startup. Currently namespaced variables are not supported so be careful when reusing code.
|
||||
|
||||
```xml
|
||||
<includes>
|
||||
<file path="./something.xml"/>
|
||||
<file path="./somethingelse.xml"/>
|
||||
</includes>
|
||||
```
|
||||
|
||||
### The `<definitions>` block
|
||||
In here you whole widget will be made, and you can also create your own widgets. Check [Widget Documentation](@/main/widgets.md) for pre-defined widgets.
|
||||
|
@ -23,15 +23,40 @@ pub struct EwwConfig {
|
||||
}
|
||||
|
||||
impl EwwConfig {
|
||||
pub fn merge_includes(eww_config: EwwConfig, includes: Vec<EwwConfig>) -> Result<EwwConfig> {
|
||||
let mut eww_config = eww_config.clone();
|
||||
for config in includes {
|
||||
eww_config.widgets.extend(config.widgets);
|
||||
eww_config.windows.extend(config.windows);
|
||||
eww_config.script_vars.extend(config.script_vars);
|
||||
eww_config.initial_variables.extend(config.initial_variables);
|
||||
}
|
||||
Ok(eww_config)
|
||||
}
|
||||
|
||||
pub fn read_from_file<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
|
||||
let content = util::replace_env_var_references(std::fs::read_to_string(path)?);
|
||||
let content = util::replace_env_var_references(std::fs::read_to_string(path.as_ref())?);
|
||||
let document = roxmltree::Document::parse(&content)?;
|
||||
|
||||
let result = EwwConfig::from_xml_element(XmlNode::from(document.root_element()).as_element()?.clone());
|
||||
let result = EwwConfig::from_xml_element(XmlNode::from(document.root_element()).as_element()?.clone(), path.as_ref());
|
||||
result
|
||||
}
|
||||
|
||||
pub fn from_xml_element(xml: XmlElement) -> Result<Self> {
|
||||
pub fn from_xml_element<P: AsRef<std::path::Path>>(xml: XmlElement, path: P) -> Result<Self> {
|
||||
let path = path.as_ref();
|
||||
let includes = match xml.child("includes") {
|
||||
Ok(tag) => tag
|
||||
.child_elements()
|
||||
.map(|child| {
|
||||
let childpath = child.attr("path")?;
|
||||
let basepath = path.parent().unwrap();
|
||||
EwwConfig::read_from_file(basepath.join(childpath))
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()
|
||||
.context(format!("error handling include definitions: {}", path.display()))?,
|
||||
Err(_) => Vec::new(),
|
||||
};
|
||||
|
||||
let definitions = xml
|
||||
.child("definitions")?
|
||||
.child_elements()
|
||||
@ -40,7 +65,7 @@ impl EwwConfig {
|
||||
Ok((def.name.clone(), def))
|
||||
})
|
||||
.collect::<Result<HashMap<_, _>>>()
|
||||
.context("error parsing widget definitions")?;
|
||||
.with_context(|| format!("error parsing widget definitions: {}", path.display()))?;
|
||||
|
||||
let windows = xml
|
||||
.child("windows")?
|
||||
@ -50,7 +75,7 @@ impl EwwConfig {
|
||||
Ok((def.name.to_owned(), def))
|
||||
})
|
||||
.collect::<Result<HashMap<_, _>>>()
|
||||
.context("error parsing window definitions")?;
|
||||
.with_context(|| format!("error parsing window definitions: {}", path.display()))?;
|
||||
|
||||
let variables_block = xml.child("variables").ok();
|
||||
|
||||
@ -77,12 +102,13 @@ impl EwwConfig {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(EwwConfig {
|
||||
let current_config = EwwConfig {
|
||||
widgets: definitions,
|
||||
windows,
|
||||
initial_variables,
|
||||
script_vars,
|
||||
})
|
||||
};
|
||||
EwwConfig::merge_includes(current_config, includes)
|
||||
}
|
||||
|
||||
// TODO this is kinda ugly
|
||||
@ -122,3 +148,78 @@ impl EwwConfig {
|
||||
self.script_vars.iter().find(|x| x.name() == name)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::config::{EwwConfig, XmlNode};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[test]
|
||||
fn test_merge_includes() {
|
||||
let input1 = r#"
|
||||
<eww>
|
||||
<definitions>
|
||||
<def name="test1">
|
||||
<box orientation="v">
|
||||
{{var1}}
|
||||
</box>
|
||||
</def>
|
||||
</definitions>
|
||||
|
||||
<variables>
|
||||
<var name="var1">var1</var>
|
||||
</variables>
|
||||
<windows>
|
||||
<window name="window1">
|
||||
<size x="100" y="200" />
|
||||
<pos x="100" y="200" />
|
||||
<widget>
|
||||
<test1 name="test2" />
|
||||
</widget>
|
||||
</window>
|
||||
</windows>
|
||||
</eww>
|
||||
"#;
|
||||
let input2 = r#"
|
||||
<eww>
|
||||
<definitions>
|
||||
<def name="test2">
|
||||
<box orientation="v">
|
||||
{{var2}}
|
||||
</box>
|
||||
</def>
|
||||
</definitions>
|
||||
<variables>
|
||||
<var name="var2">var2</var>
|
||||
</variables>
|
||||
<windows>
|
||||
<window name="window2">
|
||||
<size x="100" y="200" />
|
||||
<pos x="100" y="200" />
|
||||
<widget>
|
||||
<test2 name="test2" />
|
||||
</widget>
|
||||
</window>
|
||||
</windows>
|
||||
</eww>
|
||||
"#;
|
||||
|
||||
let document1 = roxmltree::Document::parse(&input1).unwrap();
|
||||
let document2 = roxmltree::Document::parse(input2).unwrap();
|
||||
let config1 = EwwConfig::from_xml_element(XmlNode::from(document1.root_element()).as_element().unwrap().clone(), "");
|
||||
let config2 = EwwConfig::from_xml_element(XmlNode::from(document2.root_element()).as_element().unwrap().clone(), "");
|
||||
let base_config = EwwConfig {
|
||||
widgets: HashMap::new(),
|
||||
windows: HashMap::new(),
|
||||
initial_variables: HashMap::new(),
|
||||
script_vars: Vec::new(),
|
||||
};
|
||||
|
||||
let merged_config = EwwConfig::merge_includes(base_config, vec![config1.unwrap(), config2.unwrap()]).unwrap();
|
||||
|
||||
assert_eq!(merged_config.widgets.len(), 2);
|
||||
assert_eq!(merged_config.windows.len(), 2);
|
||||
assert_eq!(merged_config.initial_variables.len(), 2);
|
||||
assert_eq!(merged_config.script_vars.len(), 0);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use crate::{
|
||||
util,
|
||||
value::{PrimitiveValue, VarName},
|
||||
};
|
||||
|
||||
use anyhow::*;
|
||||
|
||||
use element::*;
|
||||
|
@ -11,7 +11,6 @@ use crate::{
|
||||
use anyhow::*;
|
||||
use app::EwwCommand;
|
||||
|
||||
use itertools::Itertools;
|
||||
use dashmap::DashMap;
|
||||
use std::io::BufRead;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user