Skip to content

Commit 218e6d4

Browse files
committed
feat(progress): Add TermProgress
1 parent 9f2df72 commit 218e6d4

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

crates/anstyle-progress/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
#![warn(clippy::print_stderr)]
1212
#![warn(clippy::print_stdout)]
1313

14+
mod progress;
15+
16+
pub use progress::TermProgress;
17+
pub use progress::TermProgressStatus;
18+
1419
#[doc = include_str!("../README.md")]
1520
#[cfg(doctest)]
1621
pub struct ReadmeDoctests;
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/// Terminal progress formatter
2+
///
3+
/// # Example
4+
///
5+
/// ```rust
6+
/// # use anstyle_progress::TermProgress;
7+
/// # use anstyle_progress::TermProgressStatus;
8+
/// let mut progress = anstyle_progress::TermProgress::none()
9+
/// .status(TermProgressStatus::Normal);
10+
///
11+
/// let progress = progress.percent(Some(0));
12+
/// println!("{progress}");
13+
///
14+
/// let progress = progress.percent(Some(50));
15+
/// println!("{progress}");
16+
///
17+
/// let progress = progress.percent(Some(100));
18+
/// println!("{progress}");
19+
///
20+
/// println!("{progress:#}");
21+
/// ```
22+
#[derive(Copy, Clone)]
23+
pub struct TermProgress {
24+
status: Option<TermProgressStatus>,
25+
percent: Option<u8>,
26+
}
27+
28+
impl TermProgress {
29+
/// No progress to display
30+
pub fn none() -> Self {
31+
Self {
32+
status: None,
33+
percent: None,
34+
}
35+
}
36+
37+
/// Change the reported status
38+
pub fn status(mut self, status: TermProgressStatus) -> Self {
39+
self.status = Some(status);
40+
self
41+
}
42+
43+
/// Between `0..=100`
44+
pub fn percent(mut self, percent: Option<u8>) -> Self {
45+
assert!(matches!(percent, Some(0..=100) | None));
46+
self.percent = percent;
47+
self
48+
}
49+
}
50+
51+
impl Default for TermProgress {
52+
fn default() -> Self {
53+
Self::none()
54+
}
55+
}
56+
57+
/// Reported status along with progress
58+
#[allow(missing_docs)]
59+
#[derive(Copy, Clone)]
60+
pub enum TermProgressStatus {
61+
Normal,
62+
Paused,
63+
Error,
64+
}
65+
66+
impl core::fmt::Display for TermProgress {
67+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
68+
let Some(status) = self.status else {
69+
return Ok(());
70+
};
71+
let st = match (f.alternate(), status, self.percent) {
72+
(true, _, _) => 0,
73+
(false, TermProgressStatus::Normal, Some(_)) => 1,
74+
(false, TermProgressStatus::Error, _) => 2,
75+
(false, TermProgressStatus::Normal, None) => 3,
76+
(false, TermProgressStatus::Paused, _) => 4,
77+
};
78+
let pr = self.percent.unwrap_or(0);
79+
write!(f, "\x1b]9;4;{st};{pr}\x1b\\")
80+
}
81+
}

0 commit comments

Comments
 (0)