upgate_presentation/
theme.rs1use std::io::IsTerminal;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4enum OutputMode {
5 Plain,
6 Styled { color: bool },
7}
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct OutputTheme {
11 mode: OutputMode,
12 pub verbose: bool,
13}
14
15impl OutputTheme {
16 pub fn from_environment(options: ThemeOptions) -> Self {
17 Self::from_terminal(
18 options,
19 TerminalCapabilities {
20 stdout_is_tty: std::io::stdout().is_terminal(),
21 no_color_env: std::env::var_os("NO_COLOR").is_some_and(|value| !value.is_empty()),
22 term_is_dumb: std::env::var_os("TERM").is_some_and(|value| value == "dumb"),
23 },
24 )
25 }
26 pub const fn from_terminal(options: ThemeOptions, capabilities: TerminalCapabilities) -> Self {
27 let plain = options.plain || !capabilities.stdout_is_tty;
28 let mode = if plain {
29 OutputMode::Plain
30 } else {
31 OutputMode::Styled {
32 color: !options.no_color
33 && !capabilities.no_color_env
34 && !capabilities.term_is_dumb,
35 }
36 };
37
38 Self {
39 mode,
40 verbose: options.verbose,
41 }
42 }
43 pub const fn is_plain(self) -> bool {
44 matches!(self.mode, OutputMode::Plain)
45 }
46 pub const fn color(self) -> bool {
47 match self.mode {
48 OutputMode::Plain => false,
49 OutputMode::Styled { color } => color,
50 }
51 }
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
55pub struct ThemeOptions {
56 pub plain: bool,
57 pub no_color: bool,
58 pub verbose: bool,
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62pub struct TerminalCapabilities {
63 pub stdout_is_tty: bool,
64 pub no_color_env: bool,
65 pub term_is_dumb: bool,
66}