mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Add vpv example
This commit is contained in:
parent
063589b0cd
commit
b1e9afe0ff
@ -62,6 +62,7 @@ version = "1.5.0"
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rand = "0.4"
|
rand = "0.4"
|
||||||
|
pretty-bytes = "0.2.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
blt-backend = ["bear-lib-terminal"]
|
blt-backend = ["bear-lib-terminal"]
|
||||||
|
139
examples/vpv.rs
Normal file
139
examples/vpv.rs
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
extern crate cursive;
|
||||||
|
extern crate pretty_bytes;
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use cursive::Cursive;
|
||||||
|
use cursive::traits::{Boxable, With};
|
||||||
|
use cursive::utils;
|
||||||
|
use cursive::views::{Canvas, Dialog, LinearLayout, ProgressBar};
|
||||||
|
use pretty_bytes::converter::convert;
|
||||||
|
use std::thread;
|
||||||
|
use std::time;
|
||||||
|
|
||||||
|
// This example is a visual version of the `pv` tool.
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut siv = Cursive::default();
|
||||||
|
|
||||||
|
// We'll use this channel to signal the end of the transfer
|
||||||
|
let cb_sink = siv.cb_sink().clone();
|
||||||
|
|
||||||
|
// Use a counter to track progress
|
||||||
|
let counter = utils::Counter::new(0);
|
||||||
|
let counter_copy = counter.clone();
|
||||||
|
let start = time::Instant::now();
|
||||||
|
|
||||||
|
// If an argument is given, it is the file we'll read from.
|
||||||
|
// Else, read from stdin.
|
||||||
|
let (source, len) = match std::env::args().nth(1) {
|
||||||
|
Some(source) => {
|
||||||
|
let meta = std::fs::metadata(&source).unwrap();
|
||||||
|
// If possible, read the file size to have a progress bar.
|
||||||
|
let len = meta.len();
|
||||||
|
(
|
||||||
|
Some(source),
|
||||||
|
if len > 0 { Some(len) } else { None },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
None => (None, None),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Start the copy in a separate thread
|
||||||
|
thread::spawn(move || {
|
||||||
|
// Copy to stdout - lock it for better performance.
|
||||||
|
let stdout = io::stdout();
|
||||||
|
let mut stdout = stdout.lock();
|
||||||
|
|
||||||
|
match source {
|
||||||
|
None => {
|
||||||
|
// Copy from stdin - lock it for better performance.
|
||||||
|
let stdin = io::stdin();
|
||||||
|
let stdin = stdin.lock();
|
||||||
|
let mut reader =
|
||||||
|
utils::ProgressReader::new(counter_copy, stdin);
|
||||||
|
|
||||||
|
// And copy!
|
||||||
|
io::copy(&mut reader, &mut stdout).unwrap();
|
||||||
|
}
|
||||||
|
Some(source) => {
|
||||||
|
// Copy from stdin - lock it for better performance.
|
||||||
|
let input = std::fs::File::open(source).unwrap();
|
||||||
|
let mut reader =
|
||||||
|
utils::ProgressReader::new(counter_copy, input);
|
||||||
|
|
||||||
|
// And copy!
|
||||||
|
io::copy(&mut reader, &mut stdout).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// When we're done, shut down the application
|
||||||
|
cb_sink
|
||||||
|
.send(Box::new(|s: &mut Cursive| s.quit()))
|
||||||
|
.unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add a single view: progress status
|
||||||
|
siv.add_layer(
|
||||||
|
Dialog::new().title("Copying...").content(
|
||||||
|
LinearLayout::vertical()
|
||||||
|
.child(
|
||||||
|
Canvas::new(counter.clone())
|
||||||
|
.with_draw(move |c, printer| {
|
||||||
|
let ticks = c.get() as f64;
|
||||||
|
let now = time::Instant::now();
|
||||||
|
let duration = now - start;
|
||||||
|
|
||||||
|
let seconds = duration.as_secs() as f64
|
||||||
|
+ duration.subsec_nanos() as f64 * 1e-9;
|
||||||
|
|
||||||
|
let speed = ticks / seconds;
|
||||||
|
|
||||||
|
// Print ETA if we have a file size
|
||||||
|
// Otherwise prints elapsed time.
|
||||||
|
if let Some(len) = len {
|
||||||
|
let remaining = (len as f64 - ticks) / speed;
|
||||||
|
printer.print(
|
||||||
|
(0, 0),
|
||||||
|
&format!(
|
||||||
|
"ETA: {:.1} seconds",
|
||||||
|
remaining
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
printer.print(
|
||||||
|
(0, 0),
|
||||||
|
&format!(
|
||||||
|
"Elapsed: {:.1} seconds",
|
||||||
|
seconds
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
printer.print(
|
||||||
|
(0, 1),
|
||||||
|
&format!("Copied: {}", convert(ticks)),
|
||||||
|
);
|
||||||
|
printer.print(
|
||||||
|
(0, 2),
|
||||||
|
&format!("Speed: {}/s", convert(speed)),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.fixed_size((25, 3)),
|
||||||
|
)
|
||||||
|
.with(|l| {
|
||||||
|
// If we have a file length, add a progress bar
|
||||||
|
if let Some(len) = len {
|
||||||
|
l.add_child(
|
||||||
|
ProgressBar::new()
|
||||||
|
.max(len as usize)
|
||||||
|
.with_value(counter.clone()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
siv.set_fps(10);
|
||||||
|
|
||||||
|
siv.run();
|
||||||
|
}
|
@ -32,7 +32,7 @@ impl<R: Read> ProgressReader<R> {
|
|||||||
|
|
||||||
impl<R: Read> Read for ProgressReader<R> {
|
impl<R: Read> Read for ProgressReader<R> {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
let result = try!(self.reader.read(buf));
|
let result = self.reader.read(buf)?;
|
||||||
self.counter.tick(result);
|
self.counter.tick(result);
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
11
src/with.rs
11
src/with.rs
@ -14,6 +14,17 @@ pub trait With: Sized {
|
|||||||
f(&mut self)?;
|
f(&mut self)?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Calls the given closure if `condition == true`.
|
||||||
|
fn with_if<F>(mut self, condition: bool, f: F) -> Self
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut Self),
|
||||||
|
{
|
||||||
|
if condition {
|
||||||
|
f(&mut self);
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Sized> With for T {}
|
impl<T: Sized> With for T {}
|
||||||
|
Loading…
Reference in New Issue
Block a user