1use super::Ui;
2use crate::theme;
3use std::io::{self, BufWriter, Write};
4use tracing::warn;
5
6#[derive(Default)]
7pub(crate) struct ConfigOverrides {
8 pub color: Option<bool>,
9 pub default_yes: Option<bool>,
10}
11
12pub struct UiBuilder<W: Write> {
13 out: W,
14 err: Box<dyn Write>,
15 color_enabled: Option<bool>,
16 default_yes: Option<bool>,
17 config_overrides: ConfigOverrides,
18 settings: super::UiSettings,
19}
20
21impl UiBuilder<io::Stdout> {
22 pub fn new(settings: super::UiSettings) -> Self {
23 UiBuilder {
24 out: io::stdout(),
25 err: Box::new(io::stderr()),
26 color_enabled: None,
27 default_yes: None,
28 config_overrides: ConfigOverrides::default(),
29 settings,
30 }
31 }
32}
33
34impl Default for UiBuilder<io::Stdout> {
35 fn default() -> Self {
36 UiBuilder {
37 out: io::stdout(),
38 err: Box::new(io::stderr()),
39 color_enabled: None,
40 default_yes: None,
41 config_overrides: ConfigOverrides::default(),
42 settings: super::UiSettings::default(),
43 }
44 }
45}
46
47impl<W: Write> UiBuilder<W> {
48 pub fn with_writer(out: W, settings: super::UiSettings) -> Self {
49 UiBuilder {
50 out,
51 err: Box::new(io::stderr()),
52 color_enabled: None,
53 default_yes: None,
54 config_overrides: ConfigOverrides::default(),
55 settings,
56 }
57 }
58
59 pub fn with_error_writer(mut self, err: Box<dyn Write>) -> Self {
60 self.err = err;
61 self
62 }
63
64 pub fn with_config(mut self, key: &str, value: bool) -> Self {
65 match key {
66 "color" => self.config_overrides.color = Some(value),
67 "default_yes" => self.config_overrides.default_yes = Some(value),
68 _ => {
69 warn!("unknown config key: {key}");
70 }
71 }
72 self
73 }
74
75 pub fn color_enabled(mut self, color: bool) -> Self {
76 self.color_enabled = Some(color);
77 self
78 }
79
80 pub fn default_yes(mut self, default_yes: bool) -> Self {
81 self.default_yes = Some(default_yes);
82 self
83 }
84
85 pub fn build(self) -> Ui<W> {
86 let no_color_env = std::env::var_os("NO_COLOR").is_some();
87
88 let config_color = self
89 .color_enabled
90 .or(self.config_overrides.color)
91 .or(Some(self.settings.color_enabled));
92
93 let color_enabled = if no_color_env {
94 false
95 } else {
96 config_color.unwrap_or(true)
97 };
98
99 let default_yes = self
100 .default_yes
101 .or(self.config_overrides.default_yes)
102 .or(Some(self.settings.default_yes))
103 .unwrap_or(false);
104
105 let spinner_style = theme::make_spinner_style(color_enabled);
106 let progress_style = theme::make_progress_style(color_enabled);
107
108 Ui {
109 out: BufWriter::new(self.out),
110 err: self.err,
111 color_enabled,
112 default_yes,
113 spinner_style,
114 progress_style,
115 }
116 }
117}