Skip to content

Commit

Permalink
Merge branch 'console-rs:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
djugei authored Aug 24, 2024
2 parents ddd70b0 + fde06b7 commit b27346e
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 28 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ on:
schedule:
- cron: "43 6 * * 5"

env:
CLICOLOR_FORCE: 1

jobs:
test:
strategy:
Expand Down Expand Up @@ -58,7 +61,7 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.63"
toolchain: "1.70"
- run: cargo check --lib --all-features
lint:
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "indicatif"
version = "0.17.8"
edition = "2021"
rust-version = "1.63"
rust-version = "1.70"
description = "A progress bar and cli reporting library for Rust"
keywords = ["cli", "progress", "pb", "colors", "progressbar"]
categories = ["command-line-interface"]
Expand Down
3 changes: 1 addition & 2 deletions deny.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
[licenses]
allow-osi-fsf-free = "either"
copyleft = "deny"
allow = ["Apache-2.0", "BSD-3-Clause", "MIT", "Unicode-DFS-2016"]
13 changes: 12 additions & 1 deletion src/draw_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ impl ProgressDrawTarget {
}
}

/// Set whether or not to just move cursor instead of clearing lines
pub(crate) fn set_move_cursor(&mut self, move_cursor: bool) {
match &mut self.kind {
TargetKind::Term { draw_state, .. } => draw_state.move_cursor = move_cursor,
TargetKind::TermLike { draw_state, .. } => draw_state.move_cursor = move_cursor,
_ => {}
}
}

/// Apply the given draw state (draws it).
pub(crate) fn drawable(&mut self, force_draw: bool, now: Instant) -> Option<Drawable<'_>> {
match &mut self.kind {
Expand Down Expand Up @@ -473,7 +482,9 @@ impl DrawState {
}

if !self.lines.is_empty() && self.move_cursor {
term.move_cursor_up(last_line_count.as_usize())?;
// Move up to first line (assuming the last line doesn't contain a '\n') and then move to then front of the line
term.move_cursor_up(last_line_count.as_usize().saturating_sub(1))?;
term.write_str("\r")?;
} else {
// Fork of console::clear_last_lines that assumes that the last line doesn't contain a '\n'
let n = last_line_count.as_usize();
Expand Down
11 changes: 5 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,20 +176,19 @@
//! * `bar`: renders a progress bar. By default 20 characters wide. The
//! style string is used to color the elapsed part, the alternative
//! style is used for the bar that is yet to render.
//! * `wide_bar`: like `bar` but always fills the remaining space. It should not be used with
//! `wide_msg`.
//! * `wide_bar`: like `bar` but always fills the remaining space. It should not be used with `wide_msg`.
//! * `spinner`: renders the spinner (current tick string). Note that spinners do not automatically tick by default. You either
//! need to call `enable_steady_tick` or manually call `tick`.
//! need to call `enable_steady_tick` or manually call `tick`.
//! * `prefix`: renders the prefix set on the progress bar.
//! * `msg`: renders the currently set message on the progress bar.
//! * `wide_msg`: like `msg` but always fills the remaining space and truncates. It should not be used
//! with `wide_bar`.
//! 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.
//! thousands separator.
//! * `len`: renders the amount of work to be done as an integer
//! * `human_len`: renders the total length of the bar as an integer, with commas as the thousands
//! separator.
//! separator.
//! * `percent`: renders the current position of the bar as a percentage of the total length (as an integer).
//! * `percent_precise`: renders the current position of the bar as a percentage of the total length (with 3 fraction digits).
//! * `bytes`: renders the current position of the bar as bytes (alias of `binary_bytes`).
Expand Down
14 changes: 6 additions & 8 deletions src/multi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ impl MultiProgress {
/// This can reduce flickering, but do not enable it if you intend to change the number of
/// progress bars.
pub fn set_move_cursor(&self, move_cursor: bool) {
self.state.write().unwrap().move_cursor = move_cursor;
self.state
.write()
.unwrap()
.draw_target
.set_move_cursor(move_cursor);
}

/// Set alignment flag
Expand Down Expand Up @@ -209,8 +213,6 @@ pub(crate) struct MultiState {
ordering: Vec<usize>,
/// Target for draw operation for MultiProgress
draw_target: ProgressDrawTarget,
/// Whether or not to just move cursor instead of clearing lines
move_cursor: bool,
/// Controls how the multi progress is aligned if some of its progress bars get removed, default is `Top`
alignment: MultiProgressAlignment,
/// Lines to be drawn above everything else in the MultiProgress. These specifically come from
Expand All @@ -227,7 +229,6 @@ impl MultiState {
free_set: vec![],
ordering: vec![],
draw_target,
move_cursor: false,
alignment: MultiProgressAlignment::default(),
orphan_lines: Vec::new(),
zombie_lines_count: VisualLines::default(),
Expand Down Expand Up @@ -376,10 +377,7 @@ impl MultiState {
let member = self.members.get_mut(idx).unwrap();
// alignment is handled by the `MultiProgress`'s underlying draw target, so there is no
// point in propagating it here.
let state = member.draw_state.get_or_insert(DrawState {
move_cursor: self.move_cursor,
..Default::default()
});
let state = member.draw_state.get_or_insert(DrawState::default());

DrawStateWrapper::for_multi(state, &mut self.orphan_lines)
}
Expand Down
2 changes: 1 addition & 1 deletion src/progress_bar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl fmt::Debug for ProgressBar {
impl ProgressBar {
/// Creates a new progress bar with a given length
///
/// This progress bar by default draws directly to stderr, and refreshes a maximum of 15 times
/// This progress bar by default draws directly to stderr, and refreshes a maximum of 20 times
/// a second. To change the refresh rate, [set] the [draw target] to one with a different refresh
/// rate.
///
Expand Down
21 changes: 16 additions & 5 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ impl AtomicPosition {
}

let mut capacity = self.capacity.load(Ordering::Acquire);
// `prev` is the number of ms after `self.started` we last returned `true`, in ns
// `prev` is the number of ns after `self.started` we last returned `true`
let prev = self.prev.load(Ordering::Acquire);
// `elapsed` is the number of ns since `self.started`
let elapsed = (now - self.start).as_nanos() as u64;
Expand All @@ -551,10 +551,10 @@ impl AtomicPosition {
return false;
}

// We now calculate `new`, the number of ms, in ns, since we last returned `true`,
// and `remainder`, which represents a number of ns less than 1ms which we cannot
// We now calculate `new`, the number of INTERVALs since we last returned `true`,
// and `remainder`, which represents a number of ns less than INTERVAL which we cannot
// convert into capacity now, so we're saving it for later. We do this by
// substracting this from `elapsed` before storing it into `self.prev`.
// subtracting this from `elapsed` before storing it into `self.prev`.
let (new, remainder) = ((diff / INTERVAL), (diff % INTERVAL));
// We add `new` to `capacity`, subtract one for returning `true` from here,
// then make sure it does not exceed a maximum of `MAX_BURST`.
Expand All @@ -568,7 +568,7 @@ impl AtomicPosition {

fn reset(&self, now: Instant) {
self.set(0);
let elapsed = (now.saturating_duration_since(self.start)).as_millis() as u64;
let elapsed = (now.saturating_duration_since(self.start)).as_nanos() as u64;
self.prev.store(elapsed, Ordering::Release);
}

Expand Down Expand Up @@ -799,4 +799,15 @@ mod tests {
// Should not panic.
atomic_position.allow(later);
}

#[test]
fn test_atomic_position_reset() {
const ELAPSE_TIME: Duration = Duration::from_millis(20);
let mut pos = AtomicPosition::new();
pos.reset(pos.start + ELAPSE_TIME);

// prev should be exactly ELAPSE_TIME after reset
assert_eq!(*pos.pos.get_mut(), 0);
assert_eq!(*pos.prev.get_mut(), ELAPSE_TIME.as_nanos() as u64);
}
}
6 changes: 3 additions & 3 deletions src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -779,7 +779,8 @@ mod tests {

use super::*;
use crate::state::{AtomicPosition, ProgressState};
use console::colors_enabled;

use console::set_colors_enabled;
use std::sync::Mutex;

#[test]
Expand Down Expand Up @@ -865,7 +866,6 @@ mod tests {

#[test]
fn test_expand_template_flags() {
use console::set_colors_enabled;
set_colors_enabled(true);

const WIDTH: u16 = 80;
Expand Down Expand Up @@ -926,7 +926,7 @@ mod tests {

#[test]
fn wide_element_style() {
println!("colors_enabled: {}", colors_enabled());
set_colors_enabled(true);

const CHARS: &str = "=>-";
const WIDTH: u16 = 8;
Expand Down
48 changes: 48 additions & 0 deletions tests/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ fn multi_progress_single_bar_and_clear() {
drop(pb1);
assert_eq!(in_mem.contents(), "");
}

#[test]
fn multi_progress_two_bars() {
let in_mem = InMemoryTerm::new(10, 80);
Expand Down Expand Up @@ -417,6 +418,53 @@ Another line printed"#
);
}

#[test]
fn multi_progress_move_cursor() {
let in_mem = InMemoryTerm::new(10, 80);
let mp =
MultiProgress::with_draw_target(ProgressDrawTarget::term_like(Box::new(in_mem.clone())));
mp.set_move_cursor(true);

let pb1 = mp.add(ProgressBar::new(10));
pb1.tick();
assert_eq!(
in_mem.moves_since_last_check(),
r#"Str("\r")
Str("░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10")
Str("")
Flush
"#
);

let pb2 = mp.add(ProgressBar::new(10));
pb2.tick();
assert_eq!(
in_mem.moves_since_last_check(),
r#"Str("\r")
Str("░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10")
Str("")
NewLine
Str("░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10")
Str("")
Flush
"#
);

pb1.inc(1);
assert_eq!(
in_mem.moves_since_last_check(),
r#"Up(1)
Str("\r")
Str("███████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 1/10")
Str("")
NewLine
Str("░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0/10")
Str("")
Flush
"#
);
}

#[test]
fn ticker_drop() {
let in_mem = InMemoryTerm::new(10, 80);
Expand Down

0 comments on commit b27346e

Please sign in to comment.