timelog/
macros.rs

1//! Macro simplification for emitting XML.
2
3#[allow(unused_imports)]
4use xml::writer::XmlEvent;
5
6/// Write [`XmlEvent`]s to the supplied writer.
7///
8/// The first argument to the macro is always the writer object.
9/// When writing elements, the second argument is the tag name, followed by an
10/// optional list of `attr: "value"` pairs, separated by commas.
11///
12/// If the content of the element is just text, the above will be followed by a `;`
13/// and an expression giving the text.
14///
15/// If the content is more XML, the start definition will be followed by `=>` and
16/// a block. The block contains further XML writing code must return a [`Result`];
17///
18/// If you want to just send text to the XML, the only thing following the writer
19/// should be a `;` and and expression giving the text.
20///
21/// ## Examples
22///
23/// ```rust, no_run
24/// # use std::fs::File;
25/// use xml::writer::{EmitterConfig, XmlEvent};
26/// use timelog::emit_xml;
27/// use timelog::Result;
28///
29/// # fn main() -> Result<()> {
30/// let mut file = File::create("output.html").expect("Can't open file");
31/// let mut w = EmitterConfig::new()
32///     .perform_indent(true)
33///     .write_document_declaration(false)
34///     .create_writer(&mut file);
35///
36///     emit_xml!(w, html => {
37///         emit_xml!(w, head => {
38///             emit_xml!(w, title; "This is the page")
39///         })?;
40///         emit_xml!(w, body => {
41///             emit_xml!(w, div, class: "group" => {
42///                 emit_xml!(w, h1; &format!("Page for {}", "me"))?;
43///                 emit_xml!(w, p, class: "stuff"; "Useless text")?;
44///                 emit_xml!(w, br)
45///             })?;
46///             emit_xml!(w, p => {
47///                 emit_xml!(w; "This is some random text.")?;
48///                 emit_xml!(w, em; "That is part of more formatted text.")
49///             })
50///         })
51///     })?;
52///
53/// # Ok(())
54/// # }
55/// ```
56#[macro_export]
57macro_rules! emit_xml {
58    ($target:expr; $text:expr) => {
59        {
60            $target.write(XmlEvent::from(XmlEvent::characters($text)))?;
61            $crate::Result::Ok(())
62        }
63    };
64    ($target:expr, $tag:ident; $text:expr) => {
65        {
66            $target.write(XmlEvent::from(XmlEvent::start_element(stringify!($tag))))?;
67            $target.write(XmlEvent::from(XmlEvent::characters($text)))?;
68            $target.write(XmlEvent::from(XmlEvent::end_element().name(stringify!($tag))))?;
69            $crate::Result::Ok(())
70        }
71    };
72    ($target:expr, $tag:ident, $($attr:ident: $val:expr),+; $text:expr) => {
73        {
74            $target.write(XmlEvent::from(XmlEvent::start_element(stringify!($tag))
75                $(
76                    .attr(stringify!($attr), $val)
77                )+
78            ))?;
79            $target.write(XmlEvent::from(XmlEvent::characters($text)))?;
80            $target.write(XmlEvent::from(XmlEvent::end_element().name(stringify!($tag))))?;
81            $crate::Result::Ok(())
82        }
83    };
84    ($target:expr, $tag:ident => $block:block) => {
85        {
86            $target.write(XmlEvent::from(XmlEvent::start_element(stringify!($tag))))?;
87            $block?;
88            $target.write(XmlEvent::from(XmlEvent::end_element().name(stringify!($tag))))?;
89            $crate::Result::Ok(())
90        }
91    };
92    ($target:expr, $tag:ident, $($attr:ident: $val:expr),+ => $block:block) => {
93        {
94            $target.write(XmlEvent::from(XmlEvent::start_element(stringify!($tag))
95                $(
96                    .attr(stringify!($attr), $val)
97                )+
98            ))?;
99            let result: $crate::Result<()> = $block;
100            result?;
101            $target.write(XmlEvent::from(XmlEvent::end_element().name(stringify!($tag))))?;
102            $crate::Result::Ok(())
103        }
104    };
105    ($target:expr, $tag:ident) => {
106        {
107            $target.write(XmlEvent::from(XmlEvent::start_element(stringify!($tag))))?;
108            $target.write(XmlEvent::from(XmlEvent::end_element().name(stringify!($tag))))?;
109            $crate::Result::Ok(())
110        }
111    };
112    ($target:expr, $tag:ident, $($attr:ident: $val:expr),+) => {
113        {
114            $target.write(XmlEvent::from(XmlEvent::start_element(stringify!($tag))
115                $(
116                    .attr(stringify!($attr), $val)
117                )+
118            ))?;
119            $target.write(XmlEvent::from(XmlEvent::end_element().name(stringify!($tag))))?;
120            $crate::Result::Ok(())
121        }
122    };
123}