use crate::{escape::terminal_text, width::display_width};
#[derive(Debug, Default)]
pub struct ProgressLine {
last_width: usize,
}
impl ProgressLine {
#[must_use]
pub const fn new() -> Self {
Self { last_width: 0 }
}
#[must_use]
pub fn update(&mut self, text: &str) -> String {
self.render(text, false)
}
#[must_use]
pub fn finish(&mut self, text: &str) -> String {
self.render(text, true)
}
#[must_use]
pub fn clear(&mut self) -> String {
if self.last_width == 0 {
return String::new();
}
let mut frame = String::from("\r");
frame.extend(std::iter::repeat_n(' ', self.last_width));
frame.push('\r');
self.last_width = 0;
frame
}
fn render(&mut self, text: &str, newline: bool) -> String {
let text = terminal_text(text);
let width = display_width(&text);
let mut frame = String::from("\r");
frame.push_str(&text);
frame.extend(std::iter::repeat_n(
' ',
self.last_width.saturating_sub(width),
));
if newline {
frame.push('\n');
}
self.last_width = if newline { 0 } else { width };
frame
}
}
#[cfg(test)]
mod tests;