Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HumanCount and template keys to print position and length with co… #340

Merged
merged 2 commits into from Dec 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 29 additions & 0 deletions src/format.rs
Expand Up @@ -30,6 +30,10 @@ pub struct DecimalBytes(pub u64);
#[derive(Debug)]
pub struct BinaryBytes(pub u64);

/// Formats counts for human readability using commas
#[derive(Debug)]
pub struct HumanCount(pub u64);

impl fmt::Display for FormattedDuration {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut t = self.0.as_secs();
Expand Down Expand Up @@ -125,6 +129,23 @@ impl fmt::Display for BinaryBytes {
}
}

impl fmt::Display for HumanCount {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use fmt::Write;

let num = self.0.to_string();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's almost certainly a more efficient implementation. Let me know if I should work on this or benchmark it

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, not sure there's an obviously more efficient implementation.

I do think the backwards counting loop variable is a little confusing, how about changing the loop to just use for (i, c) in num.chars().enumerate() and rename your current i to len (immutable), then maybe add a binding for let pos = len - i; or something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, I think the new version is a bit simpler. Another idea is to iterate in reverse, but then that requires reversing the output string

let len = num.len();
for (idx, c) in num.chars().enumerate() {
let pos = len - idx - 1;
f.write_char(c)?;
if pos > 0 && pos % 3 == 0 {
f.write_char(',')?;
}
}
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -250,4 +271,12 @@ mod tests {
assert_eq!("3 weeks", format!("{}", HumanDuration(3 * WEEK)));
assert_eq!("3 years", format!("{}", HumanDuration(3 * YEAR)));
}

#[test]
fn human_count() {
assert_eq!("42", format!("{}", HumanCount(42)));
assert_eq!("7,654", format!("{}", HumanCount(7654)));
assert_eq!("12,345", format!("{}", HumanCount(12345)));
assert_eq!("1,234,567,890", format!("{}", HumanCount(1234567890)));
}
}
12 changes: 10 additions & 2 deletions src/lib.rs
Expand Up @@ -23,6 +23,7 @@
//! * [`DecimalBytes`](struct.DecimalBytes.html) for formatting bytes using SI prefixes
//! * [`BinaryBytes`](struct.BinaryBytes.html) for formatting bytes using ISO/IEC prefixes
//! * [`HumanDuration`](struct.HumanDuration.html) for formatting durations
//! * [`HumanCount`](struct.HumanCount.html) for formatting large counts
//!
//! # Progress Bars and Spinners
//!
Expand Down Expand Up @@ -168,7 +169,11 @@
//! * `wide_msg`: like `msg` but always fills the remaining space and truncates. It should not be used
//! with `wide_bar`.
//! * `pos`: renders the current position of the bar as integer
//! * `human_pos`: renders the current position of the bar as an integer, with commas as the
//! thousands separator.
//! * `len`: renders the total length of the bar as integer
//! * `human_len`: renders the total length of the bar as an integer, with commas as the thousands
//! separator.
//! * `bytes`: renders the current position of the bar as bytes.
//! * `percent`: renders the current position of the bar as a percentage of the total length.
//! * `total_bytes`: renders the total length of the bar as bytes.
Expand All @@ -195,10 +200,11 @@
//!
//! ```rust
//! # use std::time::Duration;
//! use indicatif::{HumanDuration, HumanBytes};
//! use indicatif::{HumanBytes, HumanCount, HumanDuration};
//!
//! assert_eq!("3.00MiB", HumanBytes(3*1024*1024).to_string());
//! assert_eq!("8 seconds", HumanDuration(Duration::from_secs(8)).to_string());
//! assert_eq!("33,857,009", HumanCount(33857009).to_string());
//! ```
//!
//! # Feature Flags
Expand All @@ -216,7 +222,9 @@ mod state;
mod style;

pub use crate::draw_target::{MultiProgressAlignment, ProgressDrawTarget};
pub use crate::format::{BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanDuration};
pub use crate::format::{
BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanCount, HumanDuration,
};
pub use crate::iter::{ProgressBarIter, ProgressIterator};
pub use crate::progress_bar::{MultiProgress, ProgressBar, WeakProgressBar};
pub use crate::style::{ProgressFinish, ProgressStyle};
Expand Down
10 changes: 9 additions & 1 deletion src/style.rs
Expand Up @@ -7,7 +7,9 @@ use console::{measure_text_width, Style};
#[cfg(feature = "improved_unicode")]
use unicode_segmentation::UnicodeSegmentation;

use crate::format::{BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanDuration};
use crate::format::{
BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanCount, HumanDuration,
};
use crate::state::ProgressState;

/// Controls the rendering style of progress bars
Expand Down Expand Up @@ -267,7 +269,13 @@ impl ProgressStyle {
"msg" => buf.push_str(state.message()),
"prefix" => buf.push_str(state.prefix()),
"pos" => buf.write_fmt(format_args!("{}", state.pos)).unwrap(),
"human_pos" => buf
.write_fmt(format_args!("{}", HumanCount(state.pos)))
.unwrap(),
"len" => buf.write_fmt(format_args!("{}", state.len)).unwrap(),
"human_len" => buf
.write_fmt(format_args!("{}", HumanCount(state.len)))
.unwrap(),
"percent" => buf
.write_fmt(format_args!("{:.*}", 0, state.fraction() * 100f32))
.unwrap(),
Expand Down