A command line progress reporting library for Rust

Overview
Comments
  • Stateful Formatters

    Stateful Formatters

    Very much a janky WIP, and some of the objects I introduced could use better naming though I avoided doing so in the interest of retaining compatibility with existing code. Haven't tested this against older rustc, but as of my current rustc version (latest stable) there are no lints from either regular check or clippy. But let me know if this seems like an ok direction and I'll revise it further.

    ~~Somewhen I'll modify that example to show what a more bumpy file transfer looks like, and the advantage of averaging it by the method I used.~~ done

    opened by 1Dragoon 45
  • rework Ticker (fix #416)

    rework Ticker (fix #416)

    Here's a first draft of how I think Ticker should work.

    So far the only testing I've done is to confirm that the long-spinner example works OK. I have not yet tested the modified version of it (which uses the Barriers).

    Fixes #416.

    TODO:

    • [ ] Write tests
    opened by chris-laplante 28
  • MultiProgress: add println and suspend implementation

    MultiProgress: add println and suspend implementation

    Work-in-progress pull request for implementing println. This does not currently work as nothing is printed for some reason. I have reason to believe it is due to an interaction with e46ca83e, since if you change the line below to m.println("Starting...\n\n") it works.

    opened by chris-laplante 22
  • A newline character should be printed after completion

    A newline character should be printed after completion

    This code used to print the progress bar, and then "Something" on the next line:

    use std::thread;
    use std::time::Duration;
    
    use indicatif::ProgressBar;
    
    fn main() {
        let pb = ProgressBar::new(1024);
        for _ in 0..1024 {
            pb.inc(1);
            thread::sleep(Duration::from_millis(5));
        }
        pb.finish_with_message("done");
        println!("Something");
    }
    
    

    However after #338 it prints the progress bar and the first character of what should be the next line ("S") on the same line, and then "omething" on the next line, like so:

    ██████████████████ 1024/1024S
    omething
    
    opened by redzic 19
  • Implement multi-line progress message support

    Implement multi-line progress message support

    This PR adds support for multi-line progress messages, following #442.

    The changes mostly update the drawing functions to split progress messages before counting them, so that the correct number of lines are cleared when they are redrawn. I'm not sure I 100% understood how orphan lines work, so I'd appreciate if someone could take a closer look at how I handle them.

    The existing examples all run as they did previously, and I've added a new example (multi-log) showing the style I was trying to implement when I opened the issue.

    One thing I noticed is that calling clear on a multiline progress doesn't always seem to clear all progress messages, a random amount stays on the screen even when a message is printed afterwards. I first thought that I introduced that bug, but switching back to main it still appeared in the examples I tried (yarnish and multi). Is this a known bug?

    opened by happenslol 18
  • 0.17.0 release planning

    0.17.0 release planning

    There have been a lot of changes since 0.16.2 was released in May 2021.

    https://github.com/mitsuhiko/indicatif/compare/0.16.2...main

    Thanks for this awesome library!

    opened by jqnatividad 17
  • Fix Ticker issue #397

    Fix Ticker issue #397

    I think there are two parts to #397:

    1. In addition to dropping the MutexGuard<BarState>, we also need to drop the Arc<Mutex<BarState>>, otherwise the reference count will never drop to 0 while the thread sleeps. The main thread will exit, but the destructor (on the Ticker thread's stack) will not run.
    2. Even with (1) in place (which seems to fix the issue), I think to be safe we also need to join the JoinHandle. Trouble is I am not yet sure where to put the join. It can't go in the Drop impl for BarState since then the thread would probably try to join itself. Perhaps we need to move the ticker state into an Arc<Mutex<Option<TickerState>>> in ProgressBar or something. Then we could rewrite Ticker::run to use, e.g. CondVar::wait_timeout instead of thread::sleep(self.interval).

    So more experimenting is necessary.

    opened by chris-laplante 16
  • wide_msg can't be used with wide_bar

    wide_msg can't be used with wide_bar

    Here is an example of the issue https://github.com/ouch-org/ouch/pull/214

    I think this line https://github.com/mitsuhiko/indicatif/blob/c43d7b3d8789027835771888310f2a1416665de1/src/style.rs#L293 only expects one wide element

    If this is an intended behavior, I can open a pr to document this

    opened by sigmaSd 16
  • Replacement for set_draw_delta()?

    Replacement for set_draw_delta()?

    With 0.17.0-rc.6, set_draw_delta is no longer.

    In my application using 0.16.2, I used it effectively to limit updates to every 1% of progress with an inc(1) inside a loop with millions of iterations by doing set_draw_delta( record_count / 100);.

    I understand that with 0.17, a lot of refactoring was done to improve performance.

    Is it no longer necessary to use set_draw_delta then and I can just do inc(1) for a loop with millions of rows and the indicatif overhead will be minimal?

    opened by jqnatividad 12
  • Implement ProgressBar::suspend

    Implement ProgressBar::suspend

    This function hides the progress bar temporarily, execute f, then redraws the progress bar, which is useful for external code that writes to the standard output.

    The idea is originally raised in #92.

    It is planned to eventually create a global function like ProgressBar::instance that allows calling suspend from e.g. a log handler, but this currently doesn't generalize to MultiProgressBar which could be an obstacle.

    opened by ishitatsuyuki 12
  • How to combine `inc` and `set_message` so that `pos` and `msg` are in sync ?

    How to combine `inc` and `set_message` so that `pos` and `msg` are in sync ?

    Following code gives this output (using current main branch, and also in 0.16.2 so this behaviour hasn't changed):

    0/3 Step 1
    1/3 Step 2
    2/3 Step 3
    3/3 Step 3
    

    If I move progress.inc(1); before set_message then I get this output instead:

    1/3
    2/3 Step 1
    3/3 Step 2
    3/3 Step 3
    

    But what I want is to have pos and msg in sync like this:

    1/3 Step 1
    2/3 Step 2
    3/3 Step 3
    

    Code:

    fn main() {
        let progress = ProgressBar::new(3);
        progress.set_style(ProgressStyle::default_bar().template("{pos}/{len} {msg}"));
        for n in 1..=3 {
    	progress.set_message(format!("Step {}", n));
            progress.inc(1);
            std::thread::sleep(Duration::from_secs(2));
        }
        progress.finish();
    }
    
    opened by malaire 11
  • Dead lock if adding the same ProgressBar to MultiProgress more than once

    Dead lock if adding the same ProgressBar to MultiProgress more than once

    Build pass but dead lock while running. Tested with indicatif == 0.17.2.

    use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
    
    fn main() {
        let mp = MultiProgress::new();
        let pb = ProgressBar::new(0);
        let style = ProgressStyle::with_template("{msg}").unwrap();
        pb.set_style(style);
        mp.add(pb.clone());
        mp.add(pb.clone());
        pb.set_message("Boom!");
        pb.finish();
    }
    

    Output while running:

    thread 'main' panicked at 'rwlock write lock would result in deadlock', /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/sys/unix/locks/pthread_rwlock.rs:111:13
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: PoisonError { .. }', /Users/kaizhao/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/indicatif-0.17.2/src/draw_target.rs:114:65
    stack backtrace:
       0:        0x10580b682 - std::backtrace_rs::backtrace::libunwind::trace::h74d17ea919046bae
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/../../backtrace/src/backtrace/libunwind.rs:93:5
       1:        0x10580b682 - std::backtrace_rs::backtrace::trace_unsynchronized::h2fc77fd5a14165ac
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
       2:        0x10580b682 - std::sys_common::backtrace::_print_fmt::h2687aa7717781133
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/sys_common/backtrace.rs:65:5
       3:        0x10580b682 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hdc69a6f447628e71
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/sys_common/backtrace.rs:44:22
       4:        0x1058245aa - core::fmt::write::hb9e764fa47ae8444
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/fmt/mod.rs:1209:17
       5:        0x10580933c - std::io::Write::write_fmt::h8fc98987ed860a54
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/io/mod.rs:1682:15
       6:        0x10580b44a - std::sys_common::backtrace::_print::h882e8250b822b8b0
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/sys_common/backtrace.rs:47:5
       7:        0x10580b44a - std::sys_common::backtrace::print::h488fe4c0b1fb9d50
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/sys_common/backtrace.rs:34:9
       8:        0x10580cb16 - std::panicking::default_hook::{{closure}}::h5618ea3156b8b833
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:267:22
       9:        0x10580c867 - std::panicking::default_hook::h0421c26a8a92801c
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:286:9
      10:        0x10580d25d - std::panicking::rust_panic_with_hook::h57383cd32463c250
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:688:13
      11:        0x10580d013 - std::panicking::begin_panic_handler::{{closure}}::h1d1f7305cfe67fdd
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:579:13
      12:        0x10580bb18 - std::sys_common::backtrace::__rust_end_short_backtrace::hd8e12e82ff026bae
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/sys_common/backtrace.rs:137:18
      13:        0x10580ccdd - rust_begin_unwind
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:575:5
      14:        0x10582cd23 - core::panicking::panic_fmt::h7894cd1015cfee41
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/panicking.rs:65:14
      15:        0x10582cf75 - core::result::unwrap_failed::h3077b600131e58d4
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/result.rs:1791:5
      16:        0x1057c7a3c - core::result::Result<T,E>::unwrap::h3324c50c72235e7b
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/result.rs:1113:23
      17:        0x1057b5245 - indicatif::draw_target::ProgressDrawTarget::width::h10f484b78fe41f38
                                   at /Users/kaizhao/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/indicatif-0.17.2/src/draw_target.rs:114:52
      18:        0x1057bffe9 - indicatif::state::BarState::draw::hef0a6bd659ade04e
                                   at /Users/kaizhao/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/indicatif-0.17.2/src/state.rs:164:21
      19:        0x1057bfaa1 - indicatif::state::BarState::finish_using_style::h9e86e00fe3c32e82
                                   at /Users/kaizhao/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/indicatif-0.17.2/src/state.rs:64:17
      20:        0x1057c0304 - <indicatif::state::BarState as core::ops::drop::Drop>::drop::h5500f1a4ff546e95
                                   at /Users/kaizhao/.cargo/registry/src/mirrors.ustc.edu.cn-61ef6e0cd06fb9b8/indicatif-0.17.2/src/state.rs:195:9
      21:        0x1057aba55 - core::ptr::drop_in_place<indicatif::state::BarState>::ha76e737d2a9b1c57
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ptr/mod.rs:490:1
      22:        0x1057acca1 - core::ptr::drop_in_place<core::cell::UnsafeCell<indicatif::state::BarState>>::hae90256bc4473fc8
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ptr/mod.rs:490:1
      23:        0x1057acda1 - core::ptr::drop_in_place<std::sync::mutex::Mutex<indicatif::state::BarState>>::he96c415f95f3be34
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ptr/mod.rs:490:1
      24:        0x1057a26b4 - alloc::sync::Arc<T>::drop_slow::h58937141ea099b10
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/alloc/src/sync.rs:1114:18
      25:        0x1057a2e14 - <alloc::sync::Arc<T> as core::ops::drop::Drop>::drop::h19ccb4630bd85572
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/alloc/src/sync.rs:1711:13
      26:        0x1057ab461 - core::ptr::drop_in_place<alloc::sync::Arc<std::sync::mutex::Mutex<indicatif::state::BarState>>>::h3fbcd49dd933d568
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ptr/mod.rs:490:1
      27:        0x1057ac465 - core::ptr::drop_in_place<indicatif::progress_bar::ProgressBar>::h70a0273cf2185db7
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ptr/mod.rs:490:1
      28:        0x10579e0ae - dead_lock_multiprogress_add_same_progressbar::main::hc8c00eaea5f96442
                                   at /Users/kaizhao/lab/rust/indicatif/dead-lock-multiprogress-add-same-progressbar/src/main.rs:20:1
      29:        0x10579e21e - core::ops::function::FnOnce::call_once::h4f1d6e4dbc09e830
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ops/function.rs:251:5
      30:        0x10579e7d1 - std::sys_common::backtrace::__rust_begin_short_backtrace::h9302ea09b14b2009
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/sys_common/backtrace.rs:121:18
      31:        0x10579e024 - std::rt::lang_start::{{closure}}::he04aac1f5b3f6d23
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/rt.rs:166:18
      32:        0x105806834 - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h61195f273fbb2744
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/core/src/ops/function.rs:286:13
      33:        0x105806834 - std::panicking::try::do_call::h742c41daae50fa78
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:483:40
      34:        0x105806834 - std::panicking::try::h289fd06090f9252d
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:447:19
      35:        0x105806834 - std::panic::catch_unwind::h442e40ac2db064f5
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panic.rs:137:14
      36:        0x105806834 - std::rt::lang_start_internal::{{closure}}::haebd6112c3b7ec52
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/rt.rs:148:48
      37:        0x105806834 - std::panicking::try::do_call::h5621965127b9aadb
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:483:40
      38:        0x105806834 - std::panicking::try::h55c66b03bc020b32
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panicking.rs:447:19
      39:        0x105806834 - std::panic::catch_unwind::hf00d6becf2cfdae2
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/panic.rs:137:14
      40:        0x105806834 - std::rt::lang_start_internal::h9ca2efac34d80f78
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/rt.rs:148:20
      41:        0x10579dff7 - std::rt::lang_start::hd9833a935556224b
                                   at /rustc/69f9c33d71c871fc16ac445211281c6e7a340943/library/std/src/rt.rs:165:17
      42:        0x10579e1e8 - _main
    thread panicked while panicking. aborting.
    
    opened by zhangkaizhao 2
  • Second ProgressBar can't be cleared if set_position before added to MultiProgress

    Second ProgressBar can't be cleared if set_position before added to MultiProgress

    I have no idea if this is a bug. Tested with indicatif == 0.17.2.

    The good one which can be cleared when set_position after added to MultiProgress:

    use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
    
    fn main() {
        let mp = MultiProgress::new();
        let pb = ProgressBar::new(0);
        let style = ProgressStyle::with_template("{msg}").unwrap();
        pb.set_style(style);
        mp.add(pb.clone());
    
        let pb2 = ProgressBar::new(100);
        let style2 = ProgressStyle::with_template("{bar}").unwrap();
        pb2.set_style(style2);
        mp.add(pb2.clone());
        pb2.set_position(0);
        pb2.finish_and_clear();
    
        pb.set_message("Good!");
        pb.finish();
    }
    

    Output:

    Good!
    

    The bad one which can't be cleared when set_position before added to MultiProgress:

    use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
    
    fn main() {
        let mp = MultiProgress::new();
        let pb = ProgressBar::new(0);
        let style = ProgressStyle::with_template("{msg}").unwrap();
        pb.set_style(style);
        mp.add(pb.clone());
    
        let pb2 = ProgressBar::new(100);
        let style2 = ProgressStyle::with_template("{bar}").unwrap();
        pb2.set_style(style2);
        pb2.set_position(0);
        mp.add(pb2.clone());
        pb2.finish_and_clear();
    
        pb.set_message("Bad!");
        pb.finish();
    }
    

    Output:

    ░░░░░░░░░░░░░░░░░░░░
    Bad!
    
    opened by zhangkaizhao 2
  • ProgressBar scrolls instead of redraws when `◎` character is present

    ProgressBar scrolls instead of redraws when `◎` character is present

    I am experiencing my ProgressBar scrolling instead of truncating/redrawing when I shrink my terminal's window.

    I am running on a remote Ubuntu server. Terminal is Mac's iTerm2, with and without tmux. The ProgressBar's template uses {wide_msg}, so I expect the progress bar to truncate text as the window sizes decreases.

    This only manifests when I shrink my past the character. If this character is not present in the message, the progress bar works as expected regardless of how small I shrink my terminal's window.

    Also, version v0.16.2 does not exhibit this behavior; it works as expected.

    I've tried v0.17.1 and v0.17.2. With v0.17.2 I also tried using the "improved_unicode" feature. None of these resulted in correct behavior.

    Here's more information in an issue I have against my repo where I debugged this: https://github.com/solana-labs/solana/issues/29158

    If it's helpful, I can get a screen capture and/or a set of steps to reproduce the issue (may be slightly involved though). Thanks in advance!

    opened by brooksprumo 9
  • If the number of progress bar exceed terminal height, newlines appears instead of clearing itself.

    If the number of progress bar exceed terminal height, newlines appears instead of clearing itself.

    Similar to #144 , if progress bars exceeds terminal's height i.e if there are more progress bars than it is able fit in visible at once, newlines are created. Fix provided in #144 doesn't help either.

    Reproduction steps:

    indicatif = "0.17.2"
    
    use std::thread;
    use std::time::Duration;
    
    use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
    
    fn main() {
        let m = MultiProgress::new();
        let sty = ProgressStyle::with_template(
            "[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}",
        )
        .unwrap()
        .progress_chars("##-");
    
        m.println("starting!").unwrap();
    
        let mut h = vec![];
    
        for _ in 0..50 {
            let pb = m.add(ProgressBar::new(128));
            pb.set_style(sty.clone());
    
            let m_clone = m.clone();
            let h1 = thread::spawn(move || {
                for i in 0..128 {
                    pb.set_message(format!("item #{}", i + 1));
                    pb.inc(1);
                    thread::sleep(Duration::from_millis(50));
                }
                m_clone.println("pb1 is done!").unwrap();
                pb.finish_with_message("done");
            });
    
            h.push(h1);
        }
    
        for k in h {
            k.join().unwrap();
        }
    
        // m.clear().unwrap();
    }
    

    Use this code and run it

    • in a terminal with height tall enough that it is able to display all progress bars at once, no issues.
    • in a terminal with reduced height so that all progress bars are not visible at once, newlines occurs.

    Example

    opened by pombadev 2
  • per_sec and eta values fluctuate wildly from one tick to the next

    per_sec and eta values fluctuate wildly from one tick to the next

    It seems that this originated in 71e7eaab9070f2cc34e9002074fe28c9f3fb371f.

    The previous behavior was that the per_sec and eta values would be relatively steady throughout the life of the progress bar, as they simply calculated pos / (now - start_time).

    The new behavior instead calculates (pos - prev_pos) / (now - prev_time). Since this no longer has the effect of averaging out fast and slow spikes since the start of the progress bar, it causes the values in per_sec and eta to fluctuate wildly between each tick. In my opinion, this is undesirable.

    opened by shssoichiro 1
Releases(0.17.2)
  • 0.17.2(Nov 8, 2022)

    A small maintenance release which makes indicatif more portable and fixes some minor regressions.

    • Use portable-atomic to fix build on some 32-bit platforms (#484, thanks to @messense)
    • Implement multi-line progress message support (#443, thanks to @happenslol)
    • Reset estimator of progress rate on backwards movement (#483, thanks to @rlee287)
    • Fix percent initial value when there is no length (#491, thanks to @devmatteini)
    • Bumped the MSRV to 1.56 (#482)

    On behalf of @djc and @chris-laplante, thanks to all contributors!

    Source code(tar.gz)
    Source code(zip)
  • 0.17.1(Sep 14, 2022)

    2.5 months after the large 0.17 release, we (finally) have a release that addresses most of the regressions found in 0.17. There is ongoing work on changes in the estimation algorithm, tracked in #394, which has regressed for some users.

    Note that we made some technically semver-breaking change of adding a missing Sync bound to the ProgressTracker bounds (#471). We're assuming that most users don't (yet) have custom ProgressTracker impls, and that users who do have probably built one that is Sync anyway.

    Fixed regressions

    • Fixed unicode-width feature spelling (#456)
    • Only tick if the ticker is disabled (#458)
    • Rework MultiProgress zombie line handling (#460)
    • Fix incorrect link in documentation (#469, thanks to @Jedsek)
    • Take a reference for ProgressBar::style() (#476, thanks to @andrewchambers)

    Other changes

    • Add HumanFloatCount formatting option (#453, thanks to @jqnatividad)
    • Add Sync bound to ProgressTracker (#471)
    • Update ProgressDrawTarget documentation (#472, thanks to @AronParker)
    • Correct mis-naming of variables in wrap_async_read (#473, thanks to @octylFractal)
    • Remove write_all() impl from ProgressBarIter's Write impl (#478, thanks to @hexagonal-sun)
    • Document last char/string in tick style being the "final" state (#479, thanks to @MarijnS95)

    Thanks from @djc and @chris-laplante to all contributors!

    Source code(tar.gz)
    Source code(zip)
  • 0.17.0(Jul 30, 2022)

    indicatif is one of the most popular terminal progress bar libraries in the Rust ecosystem. More than a year after the 0.16.0 release, we're happy to finally release 0.17. In the past year, the indicatif team has grown to two maintainers, since @chris-laplante joined @djc as a maintainer. We also now have a Discord channel.

    Apart from many small API additions and fixes, particular effort has gone into reducing the overhead for reporting progress. To this end, we've removed some of the explicit rate limiting APIs in favor of a single refresh rate in the ProgressDrawTarget. We now set a rate limit by default (50ms) that should drastically reduce overhead for most applications while being more than enough for most terminal applications. Additionally, position updates are now synchronized by using atomic integer APIs instead of a mutex. In a basic test the simplest possible progress bar is about 95x faster on 0.17.0 compared to 0.16.2.

    We've made many changes to the way MultiProgress collections work. You no longer need to explicitly join() the MultiProgress, there are more ways to insert new progress bars into the collection, and many correctness improvements have been made, in part to more effort having gone into testing the crate.

    Additionally, we've reduced our dependency footprint, removing lazy_static and regex from our required dependencies.

    Additions

    • Add ability to add custom template keys (#301, thanks to @redzic)
    • Allow custom template keys to maintain state (#420, thanks to @1Dragoon)
    • Add HumanCount and template keys to print more humane position/length (#340, thanks to @dabreegster)
    • Remove extra new line after progress bar (#338 with fixes in #343, #350 and #356, thanks to @sigmaSd)
    • Implement ProgressBar::suspend() (#333, thanks to @ishitatsuyuki)
    • Add ProgressIterator::progress_with_style() (#306, thanks to @LeCyberDucky)
    • Pass through stream_position() in ProgressBarIter (#309, thanks to @rlee287)
    • Add AsyncRead/AsyncWrite support for ProgressBar (#308, thanks to @x0f5c3)
    • Add AsyncBufRead implementation for ProgressBarIterator (#315, thanks to @x0f5c3)
    • Add builder methods for ProgressBarIter (#337, thanks to @chubei-oppen)
    • Allow overriding ProgressBar elapsed time (#325, thanks to @zhaofengli)
    • Add a space between numbers and their units (#345, thanks to @firasuke)
    • Add ProgressBar::style() to enable access to the current style (#396, thanks to @andrewchambers)
    • Account for alignment when truncating (#402)

    Performance

    • Use atomics to track the current position (#390 with follow up in #404, #406, #414)
    • Faster template expansion (without the regex dependency; #319)
    • Draw progress bars into draw states (#361, with follow up in #371)
    • Remove draw limiting from the progress bar state (#380)
    • Simplify ProgressDrawTarget to reduce in-memory size (#277, thanks to @mibac138)

    MultiProgress changes

    • Run MultiProgress drawing on the main thread (#231 and #284, thanks to @marienz and @aj-bagwell)
    • Enable inserting progress bars at the end in MultiProgress (#326, thanks to @omjadas)
    • Add insert_after()/insert_before() methods on MultiProgress (#331, with follow up in #424)
    • MultiProgress: add println() and suspend() methods (#351)
    • MultiProgress: prune zombie progress bars (#438, with follow up in #446)
    • Make is_hidden() work for MultiProgress (#430)
    • Allow vertical alignment in MultiProgress bars (#295, thanks to @nlinker)

    Fixes

    • Expand tabs to spaces to fix formatting (#150)
    • Enable 256 color support in template strings (#283, thanks to @MoSal)
    • Fix potential panic for hidden draw targets (#286, thanks to @matthiasbeyer)
    • ProgressFolder shouldn't finish progress bars on completion (#290, thanks to @mibac138)
    • Improve precision of estimates for high progress rates (#293, thanks to @kayru)
    • Reduce precision in per_sec values to make them more readable (#312)
    • Fix time rounding for HumanDuration values (#296, thanks to @Armavica)
    • Make unicode-width dependency actually optional (#281, thanks to @Shnatsel)
    • Fix progress bar width in the presence of ANSI formatting codes (#316, thanks to @redzic)
    • Fix wide element styling to work with improved unicode feature (#357)
    • WeakProgressBar::new() should not take self (#359, thanks to @ishitatsuyuki)
    • Fix panic when calculating padding spaces (#364, thanks to @sigmaSd)
    • Use final values when showing speed after finishing (#381, thanks to @Yatekii)
    • Fix panic in the estimator (#403, thanks to @arxanas)
    • Resolve potential deadlock when ticker is enabled (#417, #437)
    • Fix issue with spinners when the ticker is enabled (#407)
    • Make sure we use the first style for wide elements (#441)

    Non-functional improvements

    • Use once_cell instead of lazy_static (#324, thanks to @sigmaSd)
    • Document interaction between wide_bar and wide_msg (#329, thanks to @sigmaSd)
    • Use doc(cfg) to improve docs.rs documentation (#399)
    • Add categories in Cargo metadata (#330, thanks to @jqnatividad)
    • Introduce in-memory testing interface (#354, with follow up in #378 and #379)
    • Simplify how drawing is planned internally (#374, #382, #383, #384, #385, #386)
    • Add sleep in iterator example to see progress bars (#314, thanks to @bidoubiwa)
    • Don't conflate ticking with updating estimates (#434)
    • Store length as an Option (#415)
    Source code(tar.gz)
    Source code(zip)
Owner
Armin Ronacher
Software developer and Open Source nut. Creator of the Flask framework. Engineering at @getsentry. Other things of interest: @pallets and @rust-lang
Armin Ronacher
Rust CLI utility library. Error handling, status reporting, and exit codes.

narrate This library provides CLI application error and status reporting utilities. The coloured output formatting aims to be similar to Cargo. Error

Christopher Morton 5 Nov 2, 2022
A Reporting library for for Ara Programming Language 📃

Ara Reporting A Reporting library for Ara Programming Language ?? Internally, Ara reporting uses the codespan-reporting library to build a report of t

Ara Programming Language 4 Jan 7, 2023
Rust implementation of Python command line progress bar tool tqdm.

tqdm Rust implementation of Python command line progress bar tool tqdm. From original documentation: tqdm derives from the Arabic word taqaddum (تقدّم

Yiheng Du 8 Dec 7, 2022
Small command-line tool to switch monitor inputs from command line

swmon Small command-line tool to switch monitor inputs from command line Installation git clone https://github.com/cr1901/swmon cargo install --path .

William D. Jones 5 Aug 20, 2022
Command-line HTTP client for sending a POST request to specified URI on each stdin line.

line2httppost Simple tool to read lines from stdin and post each line as separate POST request to a specified URL (TCP connection is reused though). G

Vitaly Shukela 3 Jan 3, 2023
Pink is a command-line tool inspired by the Unix man command.

Pink is a command-line tool inspired by the Unix man command. It displays custom-formatted text pages in the terminal using a subset of HTML-like tags.

null 3 Nov 2, 2023
Console progress bar for Rust

Terminal progress bar for Rust Console progress bar for Rust Inspired from pb, support and tested on MacOS, Linux and Windows Documentation Examples s

Ariel Mashraki 507 Dec 22, 2022
Rust crate that allows you to display status & progress information in a terminal

status-line This crate allows you to display status & progress information in a terminal This crate handles the problem of displaying a small amount o

Piotr Kołaczkowski 20 Dec 27, 2022
Work-in-progress Rust application that converts C++ header-only libraries to single self-contained headers.

unosolo Work-in-progress Rust application that converts C++ header-only libraries to single self-contained headers. Disclaimer This is my first Rust p

Vittorio Romeo 26 Jul 9, 2021
A toy example showing how to run Rust code in Python for speed and progress.

PoC: Integrating Rust in Python A toy example showing how to run Rust code in Python for speed and progress. Requirements Python 3.6+ Rust 1.44+ Cargo

Emil Thorenfeldt 2 Feb 7, 2022
An experimental, work-in-progress PAM module for Tailscale

Experimental Tailscale PAM Module This is a very very experimental Tailscale PAM module that allows you to SSH using your Tailscale credentials. This

Tailscale 129 Nov 20, 2022
zman is a CLI year (time) progress that small, fast, and just one single binary.

zman zman is a CLI year (time) progress that small, fast, and just one single binary. Features Show year progress Show month, and week progress Show r

azzamsa 17 Dec 21, 2022
Work-in-progress software for managing the Azeron keypad on any operating system.

azeron-cli A small, unfinished CLI application intended to manage the Azeron Cyborg. The code is still in a very messy state and doesn't look very rus

cozyGalvinism 5 Nov 24, 2022
Work in progress NCBI's Common Tree alternative in the terminal

Lomanai Usage lomanai --species 'Mus musculus' --species 'Homo sapiens' #> Mammalia #> ++Rodentia #> | \-Mus musculus #> \+Primates #> \-Homo sapien

Jean Manguy 3 Dec 20, 2022
A work-in-progress static analyser.

Statan Statan is an early-stage static analyser for PHP and PXP projects. It is being developed in public and the journey is documented on my blog. Th

PXP 12 Jan 30, 2023
Generate progress bars from cron expressions.

jalm Generate Progress Bars from Cron Expressions Installation and Usage Grab the latest binary from the Github Actions tab. Alternatively, to build f

iamkneel 22 Oct 30, 2022
Tracing layer that automatically creates and manages progress bars for active spans.

tracing-indicatif A tracing layer that automatically creates and manages indicatif progress bars for active spans. Progress bars are a great way to ma

Emerson Ford 95 Feb 22, 2023
A Content Discovery Tool insipired from Feroxbuster. Work In Progress

monologue A Content Discovery Tool written in Rust, insipired from Feroxbuster. Installation Dependencies OpenSSL (If You are on linux). Rust programm

Voyage 3 Jul 20, 2023
A high level DSL for Simplicity. This is a work in progress and is not yet ready for production use

A high level DSL for Simplicity. This is a work in progress and is not yet ready for production use. The language is designed to be simple and easy to use. It is inspired by rust syntax and is statically typed. The syntax will be extended in the future to support more features.

null 13 Oct 28, 2023