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

Write output to stderr instead of stdout #1

Merged
merged 2 commits into from
Dec 20, 2020
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Unreleased

#### Changed

- Progress bars are now written to standard error instead of standard output.
See https://github.com/fosskers/linya/pull/1.

#### Fixed

- Some documentation inaccuracies.
Expand Down
4 changes: 2 additions & 2 deletions examples/cancel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::sync::{Arc, Mutex};
use std::time::Duration;

fn main() {
println!("Starting bars...");
eprintln!("Starting bars...");
Copy link
Owner

Choose a reason for hiding this comment

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

These can stay as println!, they're just demos after all.

Copy link
Author

Choose a reason for hiding this comment

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

Is there any reason to keep them that way? eprintln seems more consistent to me, but I'll defer to your judgement.


let progress = Arc::new(Mutex::new(Progress::new()));

Expand All @@ -32,5 +32,5 @@ fn main() {
}
});

println!("Complete!");
eprintln!("Complete!");
}
4 changes: 2 additions & 2 deletions examples/curl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use curl::easy::Easy;
use linya::{Bar, Progress};

fn main() -> Result<(), curl::Error> {
println!("Starting tarball download...");
eprintln!("Starting tarball download...");

let url = "";
let mut progress = Progress::new();
Expand All @@ -28,6 +28,6 @@ fn main() -> Result<(), curl::Error> {
// `write_function`.
handle.perform()?;

println!("Complete!");
eprintln!("Complete!");
Ok(())
}
4 changes: 2 additions & 2 deletions examples/multi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::time::Duration;
const BAR_MAX: usize = 1234;

fn main() {
println!("Starting bars...");
eprintln!("Starting bars...");

// `Progress` on its own can't be passed between threads, so we wrap it in
// the usual sharing types.
Expand Down Expand Up @@ -37,5 +37,5 @@ fn main() {
}
});

println!("Complete!");
eprintln!("Complete!");
}
4 changes: 2 additions & 2 deletions examples/single.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use linya::{Bar, Progress};
use std::time::Duration;

fn main() {
println!("Starting bar...");
eprintln!("Starting bar...");

// `Progress` is not a bar, but a "bar coordinator".
let mut progress = Progress::new();
Expand All @@ -18,5 +18,5 @@ fn main() {
std::thread::sleep(Duration::from_millis(60));
}

println!("Complete!");
eprintln!("Complete!");
}
37 changes: 23 additions & 14 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,32 +95,34 @@
#![warn(missing_docs)]
#![doc(html_root_url = "https://docs.rs/linya/0.1.0")]

use std::io::{Stdout, Write};
use std::io::{LineWriter, Stderr, Write};
use terminal_size::{terminal_size, Height, Width};

/// A progress bar "coordinator" to share between threads.
#[derive(Debug)]
pub struct Progress {
/// The drawable bars themselves.
bars: Vec<SubBar>,
/// A shared handle to `Stdout`, for buffer flushing.
out: Stdout,
/// A shared handle to `Stderr`.
///
/// Line-buffered so that the cursor doesn't jump around unpleasantly.
out: LineWriter<Stderr>,
/// Terminal width and height.
size: Option<(usize, usize)>,
}

impl Progress {
/// Initialize a new progress bar coordinator.
pub fn new() -> Progress {
let out = std::io::stdout();
let out = LineWriter::new(std::io::stderr());
let bars = vec![];
let size = terminal_size().map(|(Width(w), Height(h))| (w as usize, h as usize));
Progress { bars, out, size }
}

/// Like [`Progress::new`] but accepts a size hint to avoid reallocation as bar count grows.
pub fn with_capacity(capacity: usize) -> Progress {
let out = std::io::stdout();
let out = LineWriter::new(std::io::stderr());
let bars = Vec::with_capacity(capacity);
let size = terminal_size().map(|(Width(w), Height(h))| (w as usize, h as usize));
Progress { bars, out, size }
Expand All @@ -139,14 +141,15 @@ impl Progress {
let label: String = label.into();

// An initial "empty" rendering of the new bar.
println!(
writeln!(
&mut self.out,
"{:<l$} [{:->f$}] 0%",
label,
"",
l = twidth - w - 8 - 5,
f = w
);
self.out.flush().unwrap();
Copy link
Owner

Choose a reason for hiding this comment

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

The flush was removed here, but kept elsewhere. What was the intent?

Copy link
Author

Choose a reason for hiding this comment

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

Since we call writeln! and self.out is line-buffered it'll flush anyway. The other cases don't write a newline so an explicit flush is needed.

)
.unwrap();

let bar = SubBar {
curr: 0,
Expand Down Expand Up @@ -187,7 +190,8 @@ impl Progress {
let diff = 100 * (b.curr - b.prev) / b.total;

if b.cancelled {
print!(
write!(
&mut self.out,
"\x1B[s\x1B[{}A\r{:<l$} {:3}{} [{:_>f$}] ???%\x1B[u\r",
pos,
b.label,
Expand All @@ -196,12 +200,14 @@ impl Progress {
"",
l = term_width - w - 8 - 5,
f = w,
);
)
.unwrap();

// Very important, or the output won't appear fluid.
self.out.flush().unwrap();
} else if b.curr >= b.total {
print!(
write!(
&mut self.out,
"\x1B[s\x1B[{}A\r{:<l$} {:3}{} [{:#>f$}] 100%\x1B[u\r",
pos,
b.label,
Expand All @@ -210,14 +216,16 @@ impl Progress {
"",
l = term_width - w - 8 - 5,
f = w,
);
)
.unwrap();
self.out.flush().unwrap();
} else if diff >= 1 {
b.prev = b.curr;
let f = (w * b.curr / b.total).min(w - 1);
let e = (w - 1) - f;

print!(
write!(
&mut self.out,
"\x1B[s\x1B[{}A\r{:<l$} {:3}{} [{:#>f$}{}{:->e$}] {:3}%\x1B[u\r",
pos,
b.label,
Expand All @@ -230,7 +238,8 @@ impl Progress {
l = term_width - w - 8 - 5,
f = f,
e = e
);
)
.unwrap();
self.out.flush().unwrap();
}
}
Expand Down