1use crate::_macro::{ENDL, SECTION_HEADER, SPACE, SUB_HEADER};
2use crate::{
3 node::RoffNodeInner, write_quoted_if_whitespace, IntoRoffNode, RoffError, RoffText, Roffable,
4};
5
6use std::io::Write;
7
8#[derive(Clone, Debug)]
9pub struct Section {
11 title: RoffText,
12 subtitle: Option<RoffText>,
13 nodes: Vec<RoffNodeInner>,
14}
15
16impl Section {
17 pub fn new<I, R>(title: impl Roffable, content: I) -> Self
19 where
20 I: IntoIterator<Item = R>,
21 R: IntoRoffNode,
22 {
23 Self {
24 title: title.roff(),
25 subtitle: None,
26 nodes: content
27 .into_iter()
28 .map(|r| r.into_roff().into_inner())
29 .collect(),
30 }
31 }
32
33 pub fn subtitle(mut self, subtitle: impl Roffable) -> Self {
35 self.subtitle = Some(subtitle.roff());
36 self
37 }
38
39 pub(crate) fn render<W: Write>(
40 &self,
41 writer: &mut W,
42 was_text: bool,
43 ) -> Result<bool, RoffError> {
44 if was_text {
45 writer.write_all(ENDL)?;
46 }
47 writer.write_all(SECTION_HEADER)?;
48 writer.write_all(SPACE)?;
49 write_quoted_if_whitespace(&self.title, writer)?;
50 writer.write_all(ENDL)?;
51 if let Some(subtitle) = &self.subtitle {
52 writer.write_all(SUB_HEADER)?;
53 writer.write_all(SPACE)?;
54 write_quoted_if_whitespace(subtitle, writer)?;
55 writer.write_all(ENDL)?;
56 }
57
58 let mut was_text = false;
59 for node in &self.nodes {
60 was_text = node.render(writer, was_text)?;
61 }
62
63 Ok(was_text)
64 }
65}