vergen_pretty/pretty/
prefix.rs

1// Copyright (c) 2022 vergen developers
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9use anyhow::Result;
10use bon::Builder;
11#[cfg(feature = "color")]
12use console::Style;
13#[cfg(feature = "serde")]
14use serde::{Deserialize, Serialize};
15use std::io::Write;
16#[cfg(feature = "trace")]
17use tracing::Level;
18
19/// Configure prefix output for [`Pretty`](crate::Pretty)
20#[derive(Builder, Clone, Debug, PartialEq)]
21#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
22pub struct Prefix {
23    /// The prefix lines to output
24    pub(crate) lines: Vec<String>,
25    /// The [`Style`] to apply to the output lines
26    #[cfg(feature = "color")]
27    #[cfg_attr(feature = "serde", serde(skip))]
28    pub(crate) style: Option<Style>,
29    /// The tracing [`Level`] to output the prefix at
30    #[cfg(feature = "trace")]
31    #[builder(default = Level::INFO)]
32    #[cfg_attr(feature = "serde", serde(skip, default = "default_level"))]
33    pub(crate) level: Level,
34}
35
36impl Prefix {
37    /// Output the `vergen` environment variables that are set in table format
38    ///
39    /// # Errors
40    /// * The [`writeln!`](std::writeln!) macro can throw a [`std::io::Error`]
41    ///
42    pub(crate) fn display<T>(&self, writer: &mut T) -> Result<()>
43    where
44        T: Write + ?Sized,
45    {
46        self.inner_display(writer)?;
47        writeln!(writer)?;
48        Ok(())
49    }
50
51    #[cfg(not(feature = "color"))]
52    fn inner_display<T>(&self, writer: &mut T) -> Result<()>
53    where
54        T: Write + ?Sized,
55    {
56        for line in &self.lines {
57            writeln!(writer, "{line}")?;
58        }
59        Ok(())
60    }
61}
62
63#[cfg(all(feature = "serde", feature = "trace"))]
64fn default_level() -> Level {
65    Level::INFO
66}
67
68#[cfg(test)]
69mod test {
70    use crate::{Prefix, Pretty, utils::test_utils::TEST_PREFIX_SUFFIX, vergen_pretty_env};
71    use anyhow::Result;
72    use std::io::Write;
73
74    #[test]
75    #[allow(clippy::clone_on_copy, clippy::redundant_clone)]
76    fn prefix_clone_works() {
77        let prefix = Prefix::builder()
78            .lines(TEST_PREFIX_SUFFIX.lines().map(str::to_string).collect())
79            .build();
80        let another = prefix.clone();
81        assert_eq!(prefix, another);
82    }
83
84    #[test]
85    fn prefix_debug_works() -> Result<()> {
86        let prefix = Prefix::builder()
87            .lines(TEST_PREFIX_SUFFIX.lines().map(str::to_string).collect())
88            .build();
89        let mut buf = vec![];
90        write!(buf, "{prefix:?}")?;
91        assert!(!buf.is_empty());
92        Ok(())
93    }
94
95    #[test]
96    fn display_prefix_works() -> Result<()> {
97        let mut stdout = vec![];
98        let map = vergen_pretty_env!();
99        let prefix = Prefix::builder()
100            .lines(TEST_PREFIX_SUFFIX.lines().map(str::to_string).collect())
101            .build();
102        let fmt = Pretty::builder().env(map).prefix(prefix).build();
103        fmt.display(&mut stdout)?;
104        assert!(!stdout.is_empty());
105        Ok(())
106    }
107}