Skip to main content

Progless

Struct Progless 

Source
pub struct Progless { /* private fields */ }
Available on crate feature progress only.
Expand description

§Progless.

This is a simple, thread-safe, steady-ticking CLI progress bar that can be used to entertain users while long jobs are running.

To use it, enable the progress crate flag.

§Examples

Initialize and use as follows:

use fyi_msg::Progless;

// You can use [`Progless::try_from`] for any unsigned integer type, or the
// infallible [`Progless::from`] on an [`std::num::NonZeroU32`].
let pbar = Progless::try_from(1001_u32).unwrap();

// Iterate your taskwork or whatever.
for i in 0..1001 {
    // Do some work.
    // ...

    // Increment the count.
    pbar.increment();
}

// Close it off.
pbar.finish();

Progless is thread-safe so can be called from parallel iterators like those from rayon without any special fuss.

When doing parallel work, many tasks might be “in progress” simultaneously. To that end, you may wish to use the Progless::task instead of manually incrementing the counts to let the user know what’s happening.

Doing this, a list of active tasks will be maintained and printed along with the numerical progress. Removing a task automatically increments the done count, so you should not call Progless::increment when using this feature.



// ... snip

// Iterate in Parallel.
(0..1001).into_par_iter().for_each(|i| {
    // Announce the new task at the start.
    let task = pbar.task(format!("Task #{}.", i));

    // Do some work.

    // Drop the guard when finished.
    drop(task);
});

// ... snip

Implementations§

Source§

impl Progless

Source

pub fn sigint_two_strike() -> &'static Arc<AtomicBool>

Available on crate feature signals_sigint only.
§Two-Strike SIGINT Handler.

Implement a two-strike SIGINT-handling policy, performing some cleanup if and when the first signal is received, but only dying if there’s a second.

The returned state variable can be used to check whether or not a SIGINT has come in, and change course accordingly.

§Warnings

SIGINT-handling strategies are mutually exclusive and custom bindings are not supported.

This library offers three different options — default, two-strike, and keepalive — and implements whichever happens to be registered first.

As such, this method should be called as early as possible, and before any Progless instances are created, otherwise you’ll be stuck with the default “immediate death” handling.

§Examples
use fyi_msg::Progless;
use std::sync::atomic::Ordering::SeqCst;

// Register a shutdown handler.
let killed = Progless::sigint_two_strike();

loop {
    // CTRL+C was pressed once. Clean up and apologize!
    if killed.load(SeqCst) {
        eprintln!("So long and thanks for the fish!");
        return;
    }

    // Do stuff as usual…
}
§Panics

This will panic if the handler cannot be registered for whatever reason. If another handler was already present, it will simply return its switch instead.

Source

pub fn sigint_keepalive() -> &'static Arc<AtomicBool>

Available on crate feature signals_sigint only.
§Keepalive SIGINT Handler.

Implement a keepalive SIGINT-handling policy, performing some cleanup if and when the first signal is received, without triggering any early exit. (The program will keep on keeping on.)

The returned state variable can be used to check whether or not a SIGINT has come in, and change course accordingly.

§Warnings

SIGINT-handling strategies are mutually exclusive and custom bindings are not supported.

This library offers three different options — default, two-strike, and keepalive — and implements whichever happens to be registered first.

As such, this method should be called as early as possible, and before any Progless instances are created, otherwise you’ll be stuck with the default “immediate death” handling.

§Examples
use fyi_msg::Progless;
use std::sync::atomic::Ordering::SeqCst;

// Register a non-shutdown shutdown handler.
let killed = Progless::sigint_keepalive();
let mut warned = false;

loop {
    // The first CTRL+C has arrived.
    if ! warned && killed.load(SeqCst) {
        warned = true;
        eprintln!("I hear you, but do not care!");
    }

    // Do stuff as usual…
}
§Panics

This will panic if the handler cannot be registered for whatever reason. If another handler was already present, it will simply return its switch instead.

Source§

impl Progless

§Constants.

Source

pub const CURSOR_HIDE: &str = "\x1b[?25l"

§ANSI Sequence: Hide Cursor.

Emit this sequence to STDERR to hide the terminal cursor.

§Examples
use fyi_msg::Progless;

// Hide the cursor.
eprint!("{}", Progless::CURSOR_HIDE);
Source

pub const CURSOR_UNHIDE: &str = "\x1b[?25h"

§ANSI Sequence: Unhide Cursor.

Emit this sequence to STDERR to restore the terminal cursor.

§Examples
use fyi_msg::Progless;

// Hide the cursor.
eprint!("{}", Progless::CURSOR_HIDE);

// Do some stuff.

// Bring the cursor back.
eprint!("{}", Progless::CURSOR_UNHIDE);
Source

pub const MAX_TOTAL: usize = 4_294_967_295

Available on non-16-bit only.
§Max Total.

A Progless instance cannot have a total higher than this value. This is technically u32::MAX, but in practice usize is used more often, so this value reflects whichever of the two is smaller. Regardless, it’s an awful lot of tasks to try to visualize. Haha.

Source

pub const MAX_TOTAL_ERROR: ProglessError = ProglessError::TotalOverflow

§Total Error.

This is the error message that is returned when a total is too high for a Progless instance.

Source§

impl Progless

§Construction/Destruction.

Source

pub fn with_title<S>(self, title: Option<S>) -> Self
where S: Into<Msg>,

§With Title.

Add a title to the progress bar. When present, this will print on its own line immediately before the progress line.

Titles are formatted as Msg objects. You can pass a Msg directly, or something that can be converted to one, like a string slice.

Pass None to remove the title entirely.

Note: titles cannot have line breaks; this will automatically replace any non-space whitespace with regular horizontal spaces.

§Examples
use fyi_msg::{Msg, Progless};

// Initialize with a `u32` total.
let pbar = Progless::try_from(1001_u32).unwrap()
    .with_title(Some(Msg::info("Doing things!")));

// Iterate your taskwork or whatever.
for i in 0..1001 {
    // Do some work.
    // ...

    // Increment the done count.
    pbar.increment();
}

pbar.finish();
Source

pub fn with_reticulating_splines<S>(self, app: S) -> Self
where S: AsRef<str>,

§Set Title As X: Reticulating Splines…

This is simply shorthand for generating a “Reticulating Splines…” title, where X is the value passed in (usually the app name).

It’s a sort of default…

Source

pub fn finish(&self) -> Duration

§Stop.

Finish the progress bar, shut down the steady ticker, and return the time elapsed.

Calling this method will also erase any previously-printed progress information from the CLI screen.

§Examples
use fyi_msg::Progless;

// Initialize with a `u32` total.
let pbar = Progless::try_from(1001_u32).unwrap();

// Iterate your taskwork or whatever.
for i in 0..1001 {
    // Do some work.
    // ...

    // Increment the done count.
    pbar.increment();
}

// Finish it off!
pbar.finish();
Source

pub fn summary<S>(&self, kind: MsgKind, singular: S, plural: S) -> Msg
where S: AsRef<str>,

§Summarize.

Generate a formatted Msg summary of the (finished) progress using the supplied verb and noun.

If you just want a generic “Finished in X.” message, use Msg::from instead.

Note: if you called Progless::reset anywhere along the way, this won’t include totals from the previous run(s). (The duration is the only constant.)

§Examples
use fyi_msg::{MsgKind, Progless};

// Initialize with a `u32` total.
let pbar = Progless::try_from(1001_u32).unwrap();

// Iterate your taskwork or whatever.
for i in 0..1001 {
    // Do some work.
    // ...

    // Increment the done count.
    pbar.increment();
}

pbar.finish();

// Print something like "Crunched X files in Y seconds."
pbar.summary(MsgKind::Crunched, "file", "files").print();
Source§

impl Progless

§Passthrough Setters.

Source

pub fn increment(&self)

§Increment Done.

Increase the completed count by exactly one. This is safer to use than set_done() in cases where multiple tasks are happening at once as it will not accidentally decrease the value, etc.

See the various examples all over this page for more information.

Source

pub fn increment_n(&self, n: u32)

§Increment Done by N.

Increase the completed count by n. This is safer to use than set_done() and more efficient than calling increment() a million times in a row.

Source

pub fn task<S>(&self, txt: S) -> Option<ProglessTaskGuard<'_>>
where S: AsRef<str>,

§Add (Named) Task.

This method can be used to add an active “task” to the Progless output, letting the user know what, specifically, is being worked on at any given moment.

The “task” is bound to the lifetime of the returned guard. When (the guard is) dropped, the “task” will automatically vanish from the Progless output, and the done count will increase by one.

Multiple active “tasks” can exist simultaneously — parallelization, etc. — but there has to be enough room on the screen for the set or it won’t be displayed.

In practice, this works best for progressions that step one or a dozen or so items at a time.

See Progless::increment as an alternative that avoids the whole “task” concept.

§Examples
use fyi_msg::Progless;

// Download stuff from the internet?
let pbar = Progless::try_from(urls.len()).unwrap();
for url in &urls {
    // Add the URL to the progress output so the user knows who to
    // blame for major slowdowns, etc.
    let task = pbar.task(url);

    // Do some work that might take a while.
    if let Some(raw) = download(url) {
        // …
    }

    // One down, N to go!
    drop(task);
}

// Progress is done!
pbar.finish();
Source

pub fn push_msg(&self, msg: Msg) -> Result<(), Msg>

§Push Message.

“Insert” (print) a line (to STDERR) above the running progress bar, useful for realtime debug logs, warnings, etc., that would otherwise have to wait for the Progless instance to finish hogging the display.

§Errors

In practice this should never fail, but if for some reason STDERR is tied up the original message is passed back as an error in case you want to try to deal with it yourself.

Source

pub fn reset(&self, total: NonZeroU32)

§Reset.

Stop the current run (if any), clear the done/doing metrics, and assign a new total so you can re-use the Progless instance for a new set of tasks.

Note: the start/elapsed times for a given Progless instance are continuous. If you need the time counter to reset to [00:00:00], you need start a brand new instance instead of resetting an existing one.

Source

pub fn try_reset(&self, total: u32) -> Result<(), ProglessError>

§Reset (Fallible).

Same as Progless::reset, but will fail if total is zero.

§Errors

This will return an error if the new total is zero.

Source

pub fn done(&self) -> Option<NonZeroU32>

§Current Done.

Return the current “done” amount, if any and the instance is running.

Source

pub fn set_done(&self, done: u32)

§Set Done.

Set the done count to a specific (absolute) value.

In general, relative adjustments should be preferred for consistency. Consider Progless::increment or Progless::task instead.

Source

pub fn set_title<S>(&self, title: Option<S>)
where S: Into<Msg>,

§Set Title.

Give the progress bar a title, which will be shown above the progress bits while progress is progressing, and removed afterward with everything else.

See Progless::with_title for more details.

Source

pub fn set_title_msg(&self, msg: &str)

§Set Title Message.

Change (only) the message part — what follows the prefix — of the title to something else.

Note: this has no effect for instances without a title component.

Source

pub fn set_reticulating_splines<S>(&self, app: S)
where S: AsRef<str>,

§Set Title As X: Reticulating Splines…

This is simply shorthand for generating a “Reticulating Splines…” title, where X is the value passed in (usually the app name).

It’s a sort of default…

Trait Implementations§

Source§

impl Clone for Progless

Source§

fn clone(&self) -> Progless

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Progless

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Progless

Source§

fn default() -> Progless

Returns the “default value” for a type. Read more
Source§

impl From<Progless> for Msg

Source§

fn from(src: Progless) -> Self

§Into Msg

This provides a simple way to convert a (finished) Progless instance into a generic summary Msg that can e.g. be printed.

For a more advanced summary, use the Progless::summary method.

Source§

impl<T> From<T> for Progless
where ProglessInner: From<T>,

Source§

fn from(total: T) -> Self

Converts to this type from the input type.
Source§

impl TryFrom<NonZero<u128>> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: NonZeroU128) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<NonZero<u64>> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: NonZeroU64) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<NonZero<usize>> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: NonZeroUsize) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<i128> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: i128) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<i16> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: i16) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<i32> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: i32) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<i64> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: i64) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<i8> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: i8) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<isize> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: isize) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<u128> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: u128) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<u16> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: u16) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<u32> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: u32) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<u64> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: u64) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<u8> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: u8) -> Result<Self, Self::Error>

Performs the conversion.
Source§

impl TryFrom<usize> for Progless

Source§

type Error = ProglessError

The type returned in the event of a conversion error.
Source§

fn try_from(total: usize) -> Result<Self, Self::Error>

Performs the conversion.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.