Add inline xml support for vars

This commit is contained in:
elkowar 2020-10-11 17:53:45 +02:00
parent 42ae0e6d04
commit 3d5509b570
4 changed files with 51 additions and 20 deletions

View file

@ -286,7 +286,7 @@ mod test {
assert_eq!(
expected,
WidgetDefinition::from_xml_element(xml.as_element().unwrap()).unwrap()
WidgetDefinition::from_xml_element(xml.as_element().unwrap().to_owned()).unwrap()
);
}

View file

@ -57,7 +57,7 @@ impl EwwConfig {
let content = std::fs::read_to_string(path)?;
let document = roxmltree::Document::parse(&content)?;
let result = EwwConfig::from_xml_element(XmlNode::from(document.root_element()).as_element()?);
let result = EwwConfig::from_xml_element(XmlNode::from(document.root_element()).as_element()?.clone());
result
}
@ -97,7 +97,7 @@ impl EwwConfig {
PrimitiveValue::parse_string(
&node
.only_child()
.and_then(|c| Ok(c.as_text()?.text()))
.map(|c| c.as_text_or_sourcecode())
.unwrap_or_else(|_| String::new()),
),
);

View file

@ -11,7 +11,7 @@ macro_rules! with_text_pos_context {
}};
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum XmlNode<'a, 'b> {
Element(XmlElement<'a, 'b>),
Text(XmlText<'a, 'b>),
@ -28,15 +28,44 @@ impl<'a, 'b> fmt::Display for XmlNode<'a, 'b> {
}
}
/// Get the part of a string that is selected by the start and end TextPos.
/// Will panic if the range is out of bounds in any way.
fn get_text_from_text_range(s: &str, (start_pos, end_pos): (roxmltree::TextPos, roxmltree::TextPos)) -> String {
let mut code_text = s
.lines()
.dropping(start_pos.row as usize - 1)
.take(end_pos.row as usize - (start_pos.row as usize - 1))
.collect_vec();
if let Some(first_line) = code_text.first_mut() {
*first_line = first_line.split_at(start_pos.col as usize - 1).1;
}
if let Some(last_line) = code_text.last_mut() {
*last_line = last_line.split_at(end_pos.col as usize - 1).0;
}
code_text.join("\n")
}
impl<'a, 'b> XmlNode<'a, 'b> {
pub fn as_text(self) -> Result<XmlText<'a, 'b>> {
pub fn get_sourcecode(&self) -> String {
let input_text = self.node().document().input_text();
let range = self.node().range();
let start_pos = self.node().document().text_pos_at(range.start);
let end_pos = self.node().document().text_pos_at(range.end);
get_text_from_text_range(input_text, (start_pos, end_pos))
}
pub fn as_text_or_sourcecode(&self) -> String {
self.as_text().map(|c| c.text()).unwrap_or_else(|_| self.get_sourcecode())
}
pub fn as_text(&self) -> Result<&XmlText<'a, 'b>> {
match self {
XmlNode::Text(text) => Ok(text),
_ => Err(anyhow!("'{}' is not a text node", self)),
}
}
pub fn as_element(self) -> Result<XmlElement<'a, 'b>> {
pub fn as_element(&self) -> Result<&XmlElement<'a, 'b>> {
match self {
XmlNode::Element(element) => Ok(element),
_ => Err(anyhow!("'{}' is not an element node", self)),
@ -62,7 +91,7 @@ impl<'a, 'b> XmlNode<'a, 'b> {
}
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct XmlText<'a, 'b>(roxmltree::Node<'a, 'b>);
impl<'a, 'b> fmt::Display for XmlText<'a, 'b> {
@ -83,7 +112,7 @@ impl<'a, 'b> XmlText<'a, 'b> {
}
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct XmlElement<'a, 'b>(roxmltree::Node<'a, 'b>);
impl<'a, 'b> fmt::Display for XmlElement<'a, 'b> {
@ -161,7 +190,7 @@ impl<'a, 'b> XmlElement<'a, 'b> {
pub fn only_child_element(&self) -> Result<XmlElement> {
with_text_pos_context! { self =>
self.only_child()?.as_element()?
self.only_child()?.as_element()?.clone()
}
}

View file

@ -146,18 +146,20 @@ fn build_gtk_literal(bargs: &mut BuilderArgs) -> Result<gtk::Frame> {
let widget_definitions = bargs.widget_definitions.clone();
resolve_block!(bargs, gtk_widget, {
prop(content: as_string) {
let document = roxmltree::Document::parse(&content)?;
let content_widget_use = config::element::WidgetUse::from_xml_node(document.root_element().into())?;
let child_widget = super::widget_use_to_gtk_widget(
&widget_definitions,
&mut eww_state::EwwState::default(),
&window_name,
&std::collections::HashMap::new(),
&content_widget_use,
)?;
gtk_widget.get_children().iter().for_each(|w| gtk_widget.remove(w));
gtk_widget.add(&child_widget);
child_widget.show();
if !content.is_empty() {
let document = roxmltree::Document::parse(&content)?;
let content_widget_use = config::element::WidgetUse::from_xml_node(document.root_element().into())?;
let child_widget = super::widget_use_to_gtk_widget(
&widget_definitions,
&mut eww_state::EwwState::default(),
&window_name,
&std::collections::HashMap::new(),
&content_widget_use,
)?;
gtk_widget.add(&child_widget);
child_widget.show();
}
}
});
Ok(gtk_widget)