modcli/output/
print.rs

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/// Prints a single line with optional delay (ms)
12#[inline(always)]
13pub fn line(text: &str) {
14    println!("{text}");
15}
16
17/// Prints text without newline
18#[inline(always)]
19pub fn write(text: &str) {
20    print!("{text}");
21}
22
23/// Prints just a newline
24#[inline(always)]
25pub fn newline() {
26    println!();
27}
28
29/// Prints just a newline
30#[inline(always)]
31pub fn end() {
32    println!();
33}
34
35/// Scrolls through a multi-line string with optional delay
36pub fn scroll(multiline: &[&str], delay_ms: u64) {
37    let delay = if delay_ms > 0 {
38        Some(Duration::from_millis(delay_ms))
39    } else {
40        None
41    };
42    for text_line in multiline {
43        line(text_line);
44        if let Some(d) = delay {
45            thread::sleep(d);
46        }
47    }
48}
49
50/// Prints each line from a file with optional delay.
51///
52/// Behavior:
53/// - On open/read failure, logs a themed error via `print::error` and returns (no panic).
54/// - `delay_ms` controls a fixed delay between lines.
55///
56/// Example (ignore in doctest):
57/// ```ignore
58/// use modcli::output::print;
59/// print::file("./examples/banner.txt", 0);
60/// ```
61pub fn file(path: &str, delay_ms: u64) {
62    if let Ok(lines) = read_lines(path) {
63        for text_line in lines.map_while(Result::ok) {
64            line(&text_line);
65            if delay_ms > 0 {
66                thread::sleep(Duration::from_millis(delay_ms));
67            }
68        }
69    } else {
70        error("Failed to open file");
71    }
72}
73
74// Reads lines from a file, returns an iterator
75fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
76where
77    P: AsRef<Path>,
78{
79    let file = File::open(filename)?;
80    Ok(io::BufReader::new(file).lines())
81}
82
83// --- Message Shortcodes ---
84
85pub fn debug(msg: &str) {
86    let theme = current_theme();
87    let styled = build()
88        .part("Debug:")
89        .color(theme.get_log_color("debug"))
90        .space()
91        .part(msg)
92        .get();
93    line(&styled);
94}
95
96pub fn info(msg: &str) {
97    let theme = current_theme();
98    let styled = build()
99        .part("Info:")
100        .color(theme.get_log_color("info"))
101        .bold()
102        .space()
103        .part(msg)
104        .get();
105    line(&styled);
106}
107
108pub fn warn(msg: &str) {
109    let theme = current_theme();
110    let styled = build()
111        .part("Warning:")
112        .color(theme.get_log_color("warn"))
113        .bold()
114        .space()
115        .part(msg)
116        .get();
117    line(&styled);
118}
119
120pub fn error(msg: &str) {
121    let theme = current_theme();
122    let styled = build()
123        .part("Error:")
124        .color(theme.get_log_color("error"))
125        .bold()
126        .space()
127        .part(msg)
128        .get();
129    line(&styled);
130}
131
132pub fn success(msg: &str) {
133    let theme = current_theme();
134    let styled = build()
135        .part("Success:")
136        .color(theme.get_log_color("success"))
137        .bold()
138        .space()
139        .part(msg)
140        .get();
141    line(&styled);
142}
143
144pub fn status(msg: &str) {
145    let theme = current_theme();
146    let styled = build()
147        .part("Status:")
148        .color(theme.get_log_color("status"))
149        .bold()
150        .space()
151        .part(msg)
152        .get();
153    line(&styled);
154}
155
156pub fn deprecated(msg: &str) {
157    let theme = current_theme();
158    let styled = build()
159        .part("Deprecated:")
160        .color(theme.get_log_color("notice"))
161        .bold()
162        .space()
163        .part(msg)
164        .get();
165    line(&styled);
166}
167
168pub fn unknown(msg: &str) {
169    let theme = current_theme();
170    let styled = build()
171        .part("Unknown Command:")
172        .color(theme.get_log_color("notice"))
173        .bold()
174        .space()
175        .part(msg)
176        .get();
177    line(&styled);
178}