roffman/
text.rs

1use crate::_macro::{BOLD, FONT_END, ITALIC};
2use crate::{escape, RoffError, Roffable};
3
4use std::io::Write;
5
6#[derive(Copy, Clone, Debug, PartialEq)]
7/// Style that can be applied to [`RoffText`](RoffText).
8pub enum FontStyle {
9    Bold,
10    Italic,
11    Roman,
12}
13
14impl Default for FontStyle {
15    fn default() -> Self {
16        FontStyle::Roman
17    }
18}
19
20#[derive(Clone, Debug, Default, PartialEq)]
21/// Wrapper type for styled text in ROFF. The most basic unit of text used in the document. It can
22/// be styled with various [`FontStyle`s](FontStyle) and will escape it's contents on creation so
23/// that they are safe to render and will be correctly displayed on various viewers.
24pub struct RoffText {
25    content: String,
26    style: FontStyle,
27}
28
29impl RoffText {
30    /// Create a new `RoffText` with `content` and optional font `style`. The text will automatically
31    /// be escaped on initialization.
32    pub fn new<C: AsRef<str>>(content: C, style: Option<FontStyle>) -> Self {
33        Self {
34            content: escape(content),
35            style: style.unwrap_or_default(),
36        }
37    }
38
39    /// Set the style of this text to bold.
40    pub fn bold(mut self) -> Self {
41        self.style = FontStyle::Bold;
42        self
43    }
44
45    /// Set the style of this text to italic.
46    pub fn italic(mut self) -> Self {
47        self.style = FontStyle::Italic;
48        self
49    }
50
51    /// Return the underlying escaped text.
52    pub(crate) fn content(&self) -> &str {
53        &self.content
54    }
55
56    pub(crate) fn render<W: Write>(&self, writer: &mut W) -> Result<(), RoffError> {
57        let styled = match self.style {
58            FontStyle::Bold => {
59                writer.write_all(BOLD)?;
60                true
61            }
62            FontStyle::Italic => {
63                writer.write_all(ITALIC)?;
64                true
65            }
66            FontStyle::Roman => false,
67        };
68
69        writer.write_all(self.content.as_bytes())?;
70        if styled {
71            writer.write_all(FONT_END)?;
72        }
73
74        Ok(())
75    }
76}
77
78impl Roffable for RoffText {
79    fn roff(&self) -> RoffText {
80        self.clone()
81    }
82}