Skip to main content

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))]
22#[cfg_attr(
23    feature = "rkyv",
24    derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
25)]
26pub struct Prefix {
27    /// The prefix lines to output
28    pub(crate) lines: Vec<String>,
29    /// The [`Style`] to apply to the output lines
30    #[cfg(feature = "color")]
31    #[cfg_attr(feature = "serde", serde(skip))]
32    #[cfg_attr(feature = "rkyv", rkyv(with = rkyv::with::Map<crate::pretty::feature::rkyv_support::StyleWith>))]
33    pub(crate) style: Option<Style>,
34    /// The tracing [`Level`] to output the prefix at
35    #[cfg(feature = "trace")]
36    #[builder(default = Level::INFO)]
37    #[cfg_attr(feature = "serde", serde(skip, default = "default_level"))]
38    #[cfg_attr(
39        feature = "rkyv",
40        rkyv(with = crate::pretty::feature::rkyv_support::LevelWith)
41    )]
42    pub(crate) level: Level,
43}
44
45impl Prefix {
46    /// Output the `vergen` environment variables that are set in table format
47    ///
48    /// # Errors
49    /// * The [`writeln!`](std::writeln!) macro can throw a [`std::io::Error`]
50    ///
51    pub(crate) fn display<T>(&self, writer: &mut T) -> Result<()>
52    where
53        T: Write + ?Sized,
54    {
55        self.inner_display(writer)?;
56        writeln!(writer)?;
57        Ok(())
58    }
59
60    #[cfg(not(feature = "color"))]
61    fn inner_display<T>(&self, writer: &mut T) -> Result<()>
62    where
63        T: Write + ?Sized,
64    {
65        for line in &self.lines {
66            writeln!(writer, "{line}")?;
67        }
68        Ok(())
69    }
70}
71
72#[cfg(all(feature = "serde", feature = "trace"))]
73fn default_level() -> Level {
74    Level::INFO
75}
76
77#[cfg(test)]
78mod test {
79    use crate::{Prefix, Pretty, utils::test_utils::TEST_PREFIX_SUFFIX, vergen_pretty_env};
80    use anyhow::Result;
81    use std::io::Write;
82
83    #[test]
84    #[allow(clippy::clone_on_copy, clippy::redundant_clone)]
85    fn prefix_clone_works() {
86        let prefix = Prefix::builder()
87            .lines(TEST_PREFIX_SUFFIX.lines().map(str::to_string).collect())
88            .build();
89        let another = prefix.clone();
90        assert_eq!(prefix, another);
91    }
92
93    #[test]
94    fn prefix_debug_works() -> Result<()> {
95        let prefix = Prefix::builder()
96            .lines(TEST_PREFIX_SUFFIX.lines().map(str::to_string).collect())
97            .build();
98        let mut buf = vec![];
99        write!(buf, "{prefix:?}")?;
100        assert!(!buf.is_empty());
101        Ok(())
102    }
103
104    #[test]
105    fn display_prefix_works() -> Result<()> {
106        let mut stdout = vec![];
107        let map = vergen_pretty_env!();
108        let prefix = Prefix::builder()
109            .lines(TEST_PREFIX_SUFFIX.lines().map(str::to_string).collect())
110            .build();
111        let fmt = Pretty::builder().env(map).prefix(prefix).build();
112        fmt.display(&mut stdout)?;
113        assert!(!stdout.is_empty());
114        Ok(())
115    }
116}