Skip to content

Commit

Permalink
support logging [WIP, missing windows]
Browse files Browse the repository at this point in the history
  • Loading branch information
Stefan Bühler committed Jul 27, 2017
1 parent 8151995 commit aadb45f
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 10 deletions.
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ mod tty;
mod pb;
mod multi;
pub use pb::{ProgressBar, Units};
pub use multi::{MultiBar, Pipe};
pub use multi::{MultiBar, Pipe, LogTarget};
use std::io::{Write, Stdout, stdout};

pub struct PbIter<T, I>
Expand Down Expand Up @@ -189,14 +189,14 @@ pub trait ProgressReceiver: private::SealedProgressReceiver {

impl<T: Write> private::SealedProgressReceiver for T {
fn update_progress(&mut self, line: &str) {
self.write(tty::clear_current_line().as_bytes()).expect("write() fail");
self.write(b"\r").expect("write() fail");
self.write(line.as_bytes()).expect("write() fail");
self.flush().expect("flush() fail");
}

fn clear_progress(&mut self, line: &str) {
self.write(tty::clear_current_line().as_bytes()).expect("write() fail");
self.write(b"\r").expect("write() fail");
self.write(tty::clear_until_newline().as_bytes()).expect("write() fail");
self.write(line.as_bytes()).expect("write() fail");
self.write(b"\n").expect("write() fail");
self.flush().expect("flush() fail");
Expand Down
75 changes: 70 additions & 5 deletions src/multi.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use pb::ProgressBar;
use std::str::from_utf8;
use tty;
use std::io::{Stdout, Write};
use std::io::{self, Stdout, Write};
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver};

Expand Down Expand Up @@ -158,6 +159,12 @@ impl<T: Write> MultiBar<T> {
p
}

pub fn create_log_target(&mut self) -> LogTarget {
LogTarget{
buf: Vec::new(),
chan: self.chan.0.clone(),
}
}

/// listen start listen to all bars changes.
///
Expand Down Expand Up @@ -194,21 +201,30 @@ impl<T: Write> MultiBar<T> {
let mut first = true;
let mut nbars = self.nbars;
while nbars > 0 {
let mut log_line = None;

// receive message
let msg = self.chan.1.recv().unwrap();
match msg {
WriteMsg::ProgressUpdate{level,line} => {
self.lines[level] = line;
},
WriteMsg::ProgressClear{level,line} => {
self.lines[level] = tty::clear_current_line() + &line;
self.lines[level] = tty::clear_until_newline() + &line;
nbars -= 1;
},
WriteMsg::ProgressFinish{level,line} => {
// writing lines below progress not supported;
// replace progress instead
self.lines[level] = tty::clear_current_line() + &line;
// writing lines below progress not supported; treat
// as log message
let _ = level;
nbars -= 1;
if line.is_empty() { continue; }
log_line = Some(line);
},
WriteMsg::Log{level,line} => {
let _ = level;
if line.is_empty() { continue; }
log_line = Some(line);
},
}

Expand All @@ -219,6 +235,12 @@ impl<T: Write> MultiBar<T> {
} else {
first = false;
}
if let Some(line) = log_line {
out += "\r";
out += &tty::clear_after_cursor();
out += &line;
out += "\n";
}
for l in self.lines.iter() {
out += "\r";
out += &l;
Expand All @@ -234,6 +256,45 @@ pub struct Pipe {
chan: Sender<WriteMsg>,
}

pub struct LogTarget {
buf: Vec<u8>,
chan: Sender<WriteMsg>,
}

impl Write for LogTarget {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
use std::mem::replace;

self.buf.extend_from_slice(buf);
// find last newline and flush the part before it
for pos in (0..self.buf.len()).rev() {
if self.buf[pos] == b'\n' {
let rem = self.buf.split_off(pos+1);
let msg = replace(&mut self.buf, rem);
self.chan.send(WriteMsg::Log{
level: 0,
line: from_utf8(&msg[..pos]).unwrap().to_owned(),
})
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
break;
}
}
Ok(buf.len())
}

fn flush(&mut self) -> io::Result<()> {
use std::mem::replace;

let msg = replace(&mut self.buf, Vec::new());
self.chan.send(WriteMsg::Log{
level: 0,
line: from_utf8(&msg).unwrap().to_owned(),
})
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
Ok(())
}
}

impl ::private::SealedProgressReceiver for Pipe {
fn update_progress(&mut self, line: &str) {
self.chan.send(WriteMsg::ProgressUpdate{
Expand Down Expand Up @@ -278,4 +339,8 @@ enum WriteMsg {
level: usize,
line: String,
},
Log {
level: usize,
line: String,
},
}
8 changes: 6 additions & 2 deletions src/tty/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,12 @@ pub fn move_cursor_up(n: usize) -> String {
format!("{}", termion::cursor::Up(n as u16))
}

pub fn clear_current_line() -> String {
format!("{}", termion::clear::CurrentLine)
pub fn clear_until_newline() -> String {
format!("{}", termion::clear::UntilNewline)
}

pub fn clear_after_cursor() -> String {
format!("{}", termion::clear::AfterCursor)
}

#[cfg(not(target_os = "redox"))]
Expand Down

0 comments on commit aadb45f

Please sign in to comment.