1use crate::output::style::build;
2use crate::output::themes::current_theme;
3use std::{
4 fs::File,
5 io::{self, BufRead},
6 path::Path,
7 thread,
8 time::Duration,
9};
10
11#[inline(always)]
13pub fn line(text: &str) {
14 println!("{text}");
15}
16
17pub fn link(text: &str, url: &str) {
29 let osc8_enabled = osc8_supported();
30 if osc8_enabled {
31 print!("\x1b]8;;{url}\x07{text}\x1b]8;;\x07");
34 println!();
35 } else {
36 println!("{text} ({url})");
37 }
38}
39
40fn osc8_supported() -> bool {
46 if let Ok(val) = std::env::var("ENABLE_OSC8") {
47 let v = val.to_ascii_lowercase();
48 if v == "true" || v == "1" {
49 return true;
50 }
51 if v == "false" || v == "0" {
52 return false;
53 }
54 }
55
56 let has = |k: &str| std::env::var_os(k).is_some();
58 let term_program = std::env::var("TERM_PROGRAM")
59 .unwrap_or_default()
60 .to_ascii_lowercase();
61 let term = std::env::var("TERM")
62 .unwrap_or_default()
63 .to_ascii_lowercase();
64
65 if has("WEZTERM_EXECUTABLE") || term_program.contains("wezterm") {
67 return true;
68 }
69 if term_program.contains("iterm") {
71 return true;
72 }
73 if has("KITTY_WINDOW_ID") || term.contains("kitty") {
75 return true;
76 }
77 if has("VTE_VERSION") {
79 return true;
80 }
81 if has("WT_SESSION") {
83 return true;
84 }
85
86 false
87}
88
89#[inline(always)]
91pub fn write(text: &str) {
92 print!("{text}");
93}
94
95#[inline(always)]
97pub fn newline() {
98 println!();
99}
100
101#[inline(always)]
103pub fn end() {
104 println!();
105}
106
107pub fn scroll(multiline: &[&str], delay_ms: u64) {
109 let delay = if delay_ms > 0 {
110 Some(Duration::from_millis(delay_ms))
111 } else {
112 None
113 };
114 for text_line in multiline {
115 line(text_line);
116 if let Some(d) = delay {
117 thread::sleep(d);
118 }
119 }
120}
121
122pub fn file(path: &str, delay_ms: u64) {
134 if let Ok(lines) = read_lines(path) {
135 for text_line in lines.map_while(Result::ok) {
136 line(&text_line);
137 if delay_ms > 0 {
138 thread::sleep(Duration::from_millis(delay_ms));
139 }
140 }
141 } else {
142 error("Failed to open file");
143 }
144}
145
146fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
148where
149 P: AsRef<Path>,
150{
151 let file = File::open(filename)?;
152 Ok(io::BufReader::new(file).lines())
153}
154
155pub fn debug(msg: &str) {
158 let theme = current_theme();
159 let styled = build()
160 .part("Debug:")
161 .color(theme.get_log_color("debug"))
162 .space()
163 .part(msg)
164 .get();
165 line(&styled);
166}
167
168pub fn info(msg: &str) {
169 let theme = current_theme();
170 let styled = build()
171 .part("Info:")
172 .color(theme.get_log_color("info"))
173 .bold()
174 .space()
175 .part(msg)
176 .get();
177 line(&styled);
178}
179
180pub fn warn(msg: &str) {
181 let theme = current_theme();
182 let styled = build()
183 .part("Warning:")
184 .color(theme.get_log_color("warn"))
185 .bold()
186 .space()
187 .part(msg)
188 .get();
189 line(&styled);
190}
191
192pub fn error(msg: &str) {
193 let theme = current_theme();
194 let styled = build()
195 .part("Error:")
196 .color(theme.get_log_color("error"))
197 .bold()
198 .space()
199 .part(msg)
200 .get();
201 line(&styled);
202}
203
204pub fn success(msg: &str) {
205 let theme = current_theme();
206 let styled = build()
207 .part("Success:")
208 .color(theme.get_log_color("success"))
209 .bold()
210 .space()
211 .part(msg)
212 .get();
213 line(&styled);
214}
215
216pub fn status(msg: &str) {
217 let theme = current_theme();
218 let styled = build()
219 .part("Status:")
220 .color(theme.get_log_color("status"))
221 .bold()
222 .space()
223 .part(msg)
224 .get();
225 line(&styled);
226}
227
228pub fn deprecated(msg: &str) {
229 let theme = current_theme();
230 let styled = build()
231 .part("Deprecated:")
232 .color(theme.get_log_color("notice"))
233 .bold()
234 .space()
235 .part(msg)
236 .get();
237 line(&styled);
238}
239
240pub fn unknown(msg: &str) {
241 let theme = current_theme();
242 let styled = build()
243 .part("Unknown Command:")
244 .color(theme.get_log_color("notice"))
245 .bold()
246 .space()
247 .part(msg)
248 .get();
249 line(&styled);
250}