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}