cargo_whatfeatures/printer/
version.rs

1use crate::{client::Version, Options, Theme, YankStatus};
2use std::io::Write;
3
4/// Output for the program
5pub struct VersionPrinter<'a, W: ?Sized> {
6    writer: &'a mut W,
7    theme: Theme,
8    options: Options,
9}
10
11impl<'a, W: Write + ?Sized> VersionPrinter<'a, W> {
12    /// Create a new printer with this writer
13    pub fn new(writer: &'a mut W, options: Options) -> Self {
14        Self {
15            writer,
16            theme: options.theme,
17            options,
18        }
19    }
20
21    /// Write out all of the versions, filtered by the `YankStatus`
22    pub fn write_versions(
23        &mut self,
24        versions: &[Version],
25        yank: YankStatus,
26        verbose: bool,
27    ) -> std::io::Result<()> {
28        use YankStatus::*;
29        let output = versions
30            .iter()
31            .filter(|ver| match (yank, ver.yanked) {
32                (Exclude, true) | (Only, false) => false,
33                _ => true,
34            })
35            .map(|version| match yank {
36                Exclude => self.write_latest(version, verbose),
37                Only => self.write_yanked(version, verbose),
38                Include if version.yanked => self.write_yanked(version, verbose),
39                Include => self.write_latest(version, verbose),
40            })
41            .collect::<Vec<_>>();
42
43        let left_max = output
44            .iter()
45            .map(|&VersionOutput { left_len, .. }| left_len)
46            .max()
47            .unwrap_or_default();
48
49        let padding = " ".repeat(left_max);
50
51        output
52            .iter()
53            .map(|v| {
54                writeln!(
55                    self.writer,
56                    "{}{} # {}",
57                    v.left,
58                    &padding[v.left_len..],
59                    v.right
60                )
61            })
62            .collect()
63    }
64
65    /// Writes many 'name = version' pairs with column alignment
66    pub fn write_many_versions(
67        &mut self,
68        list: Vec<(&String, &String, bool)>,
69    ) -> std::io::Result<()> {
70        let max = list.iter().map(|(s, ..)| s.len()).max().unwrap();
71
72        let theme = self.theme;
73        for (name, version, published) in list {
74            let header = if published {
75                format!(
76                    "{: <max$} = \"{}\"",
77                    theme.name.paint(&name),
78                    theme.version.paint(&version),
79                    max = max,
80                )
81            } else if self.options.show_private {
82                format!(
83                    "{: <max$} = \"{}\" {}",
84                    theme.name.paint(&name),
85                    theme.version.paint(&version),
86                    theme.is_not_published.paint("(restricted)"),
87                    max = max,
88                )
89            } else {
90                continue;
91            };
92
93            writeln!(self.writer, "{}", header)?;
94        }
95
96        Ok(())
97    }
98
99    pub fn write_latest_version(
100        &mut self,
101        version: &Version,
102        verbose: bool,
103    ) -> std::io::Result<()> {
104        let VersionOutput { left, right, .. } = self.write_latest(version, verbose);
105        writeln!(self.writer, "{} # {}", left, right)
106    }
107
108    fn write_yanked(&mut self, version: &Version, verbose: bool) -> VersionOutput {
109        let left = format!(
110            "{} = \"{}\"",
111            self.theme.yanked.paint(&version.name),
112            self.theme.yanked.paint(&version.version),
113        );
114
115        let right = if !verbose {
116            format!(
117                "{} -- yanked",
118                self.theme
119                    .created_at
120                    .paint(&version.format_approx_time_span()),
121            )
122        } else {
123            format!(
124                "{} -- yanked",
125                self.theme.created_at.paint(&version.format_verbose_time()),
126            )
127        };
128
129        VersionOutput {
130            left_len: version.name.len() + version.version.len() + 3,
131            left,
132            right,
133        }
134    }
135
136    fn write_latest(&mut self, version: &Version, verbose: bool) -> VersionOutput {
137        let left = format!(
138            "{} = \"{}\"",
139            self.theme.name.paint(&version.name),
140            self.theme.version.paint(&version.version),
141        );
142
143        let right = if !verbose {
144            format!(
145                "{}",
146                self.theme
147                    .created_at
148                    .paint(&version.format_approx_time_span()),
149            )
150        } else {
151            format!(
152                "{}",
153                self.theme.created_at.paint(&version.format_verbose_time()),
154            )
155        };
156
157        VersionOutput {
158            left_len: version.name.len() + version.version.len() + 3,
159            left,
160            right,
161        }
162    }
163}
164
165pub struct VersionOutput {
166    left_len: usize,
167    left: String,
168    right: String,
169}