use unicode_width::UnicodeWidthChar;
use crate::escape::terminal_text;
#[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 frame = format!("\r{}\r", " ".repeat(self.last_width));
self.last_width = 0;
frame
}
fn render(&mut self, text: &str, newline: bool) -> String {
let text = terminal_text(text);
let width: usize = text.chars().map(|ch| ch.width().unwrap_or(0)).sum();
let padding = " ".repeat(self.last_width.saturating_sub(width));
let mut frame = format!("\r{text}{padding}");
if newline {
frame.push('\n');
}
self.last_width = if newline { 0 } else { width };
frame
}
}
#[cfg(test)]
mod tests;