diff options
-rw-r--r-- | src/actions/agenda.rs | 3 | ||||
-rw-r--r-- | src/actions/cursor.rs | 8 | ||||
-rw-r--r-- | src/actions/edit.rs | 4 | ||||
-rw-r--r-- | src/actions/get.rs | 3 | ||||
-rw-r--r-- | src/actions/seq.rs | 59 | ||||
-rw-r--r-- | src/actions/show.rs | 1 | ||||
-rw-r--r-- | src/cursorfile.rs | 2 | ||||
-rw-r--r-- | src/input.rs | 11 | ||||
-rw-r--r-- | src/macros.rs | 12 | ||||
-rw-r--r-- | src/seqfile.rs | 18 | ||||
-rw-r--r-- | src/testutils.rs | 32 | ||||
-rw-r--r-- | src/utils/fileutil.rs | 34 | ||||
-rw-r--r-- | src/utils/mod.rs | 2 | ||||
-rw-r--r-- | src/utils/stdioutils.rs | 124 |
14 files changed, 198 insertions, 115 deletions
diff --git a/src/actions/agenda.rs b/src/actions/agenda.rs index 41c0d9d..8750b1f 100644 --- a/src/actions/agenda.rs +++ b/src/actions/agenda.rs @@ -177,6 +177,7 @@ mod tests { use super::*; use testdata; use testutils::*; + use utils::stdioutils; use config::Config; use chrono::{Local, TimeZone}; @@ -272,7 +273,7 @@ mod tests { show_events(&Config::read_config(), &[]).unwrap(); - let stdout = test_stdout_clear(); + let stdout = stdioutils::test_stdout_clear(); let expected = indoc!(" 2018-12-13, Thursday 0 22:30- shows up on two days diff --git a/src/actions/cursor.rs b/src/actions/cursor.rs index 8b052a2..864fc52 100644 --- a/src/actions/cursor.rs +++ b/src/actions/cursor.rs @@ -1,17 +1,17 @@ extern crate atty; use cursorfile; -use utils::fileutil; +use utils::stdioutils; use KhResult; pub fn do_cursor(_args: &[&str]) -> KhResult<()> { - if atty::isnt(atty::Stream::Stdin) { + if !stdioutils::is_stdin_tty() { write_stdin_to_cursorfile(); } else { //println!("stdin is tty") } - if atty::isnt(atty::Stream::Stdout) || atty::is(atty::Stream::Stdin) { + if !stdioutils::is_stdout_tty() || stdioutils::is_stdin_tty() { write_cursorfile_to_stdout(); } @@ -19,7 +19,7 @@ pub fn do_cursor(_args: &[&str]) -> KhResult<()> { } fn write_stdin_to_cursorfile() { - let lines = match fileutil::read_lines_from_stdin() { + let lines = match stdioutils::read_lines_from_stdin() { Ok(input) => input, Err(error) => { error!("Error reading from stdin: {}", error); diff --git a/src/actions/edit.rs b/src/actions/edit.rs index d0b1251..1a9843c 100644 --- a/src/actions/edit.rs +++ b/src/actions/edit.rs @@ -7,7 +7,7 @@ use tempfile::NamedTempFile; use backup::backup; use input; use khline::KhLine; -use utils::fileutil; +use utils::{fileutil,stdioutils}; use KhResult; pub fn do_edit(_args: &[&str]) -> KhResult<()> { @@ -54,7 +54,7 @@ fn ask_continue_editing(error: &[String]) -> bool { println!("Calendar contains errors:\n{}", error.join("\n")); println!("Continue editing? y/n:"); - match fileutil::read_single_char_from_stdin().unwrap() { + match stdioutils::read_single_char_from_stdin().unwrap() { 'y' => true, _ => false } diff --git a/src/actions/get.rs b/src/actions/get.rs index 7c09470..f059ea0 100644 --- a/src/actions/get.rs +++ b/src/actions/get.rs @@ -24,6 +24,7 @@ mod tests { use super::*; use testutils; + use utils::stdioutils; #[test] fn test_get_calendars() { @@ -31,6 +32,6 @@ mod tests { action_get(&["calendars"]).unwrap(); - assert_eq!("first\nsecond\nsecond/second_sub\n", testutils::test_stdout_clear()); + assert_eq!("first\nsecond\nsecond/second_sub\n", stdioutils::test_stdout_clear()); } } diff --git a/src/actions/seq.rs b/src/actions/seq.rs index 8426bfd..bd71e34 100644 --- a/src/actions/seq.rs +++ b/src/actions/seq.rs @@ -1,41 +1,66 @@ -extern crate atty; - use seqfile; -use utils::fileutil; +use utils::stdioutils; use KhResult; pub fn do_seq(_args: &[&str]) -> KhResult<()> { - if atty::isnt(atty::Stream::Stdin) { - write_stdin_to_seqfile(); + if !stdioutils::is_stdin_tty() { + write_stdin_to_seqfile()?; } else { //println!("stdin is tty") } - if atty::isnt(atty::Stream::Stdout) || atty::is(atty::Stream::Stdin) { + if !stdioutils::is_stdout_tty() || stdioutils::is_stdin_tty() { write_seqfile_to_stdout(); } Ok(()) } -fn write_stdin_to_seqfile() { - let mut lines; - match fileutil::read_lines_from_stdin() { - Ok(input) => lines = input.join("\n"), - Err(error) => { - error!("Error reading from stdin: {}", error); - return - } - } +fn write_stdin_to_seqfile() -> KhResult<()> { + let mut lines = stdioutils::read_lines_from_stdin()?.join("\n"); lines.push_str("\n"); - seqfile::write_to_seqfile(&lines); + seqfile::write_to_seqfile(&lines)?; + + Ok(()) } fn write_seqfile_to_stdout() { if let Ok(sequence) = seqfile::read_seqfile() { for line in sequence { - println!("{}", line); + khprintln!("{}", line); } } } + +#[cfg(test)] +mod tests { + use super::*; + + use assert_fs::prelude::*; + use predicates::prelude::*; + use testutils; + use utils::stdioutils; + + #[test] + fn test_write_stdin_to_seqfile() { + let testdir = testutils::prepare_testdir_empty(); + stdioutils::test_stdin_write("hi\nthere"); + + write_stdin_to_seqfile().unwrap(); + + testdir.child(".khaleesi/seq").assert("hi\nthere\n"); + } + + #[test] + fn test_read_seqfile_to_stdout() { + let testdir = testutils::prepare_testdir("testdir_with_seq"); + + write_seqfile_to_stdout(); + let out = stdioutils::test_stdout_clear(); + + let predicate = predicate::str::similar(out); + testdir.child(".khaleesi/seq").assert(predicate); + } +} + diff --git a/src/actions/show.rs b/src/actions/show.rs index f5ead26..00f4626 100644 --- a/src/actions/show.rs +++ b/src/actions/show.rs @@ -19,6 +19,7 @@ mod tests { use super::*; use testutils::*; + use utils::stdioutils::*; #[test] fn test_() { diff --git a/src/cursorfile.rs b/src/cursorfile.rs index a06b80e..cd95286 100644 --- a/src/cursorfile.rs +++ b/src/cursorfile.rs @@ -1,5 +1,3 @@ -extern crate atty; - use std::fs::rename; use std::io; diff --git a/src/input.rs b/src/input.rs index 7dace16..860db05 100644 --- a/src/input.rs +++ b/src/input.rs @@ -1,15 +1,14 @@ -use atty; use std::io; use seqfile; use cursorfile; use khline::KhLine; -use utils::fileutil; +use utils::stdioutils; pub fn default_input_khlines() -> Result<Box<dyn Iterator<Item = KhLine>>, String> { - if atty::isnt(atty::Stream::Stdin) { + if !stdioutils::is_stdin_tty() { debug!("Taking input from Stdin"); - let lines = fileutil::read_lines_from_stdin().unwrap().into_iter(); + let lines = stdioutils::read_lines_from_stdin().unwrap().into_iter(); let khlines = lines.map(|line| line.parse::<KhLine>()).flatten(); Ok(Box::new(khlines)) } else { @@ -20,10 +19,10 @@ pub fn default_input_khlines() -> Result<Box<dyn Iterator<Item = KhLine>>, Strin } pub fn default_input_khline() -> io::Result<KhLine> { - if atty::isnt(atty::Stream::Stdin) { + if !stdioutils::is_stdin_tty() { debug!("Taking input from Stdin"); - let lines = fileutil::read_lines_from_stdin()?; + let lines = stdioutils::read_lines_from_stdin()?; if lines.len() > 1 { Err(io::Error::new(io::ErrorKind::Other, "too many lines in cursorfile")) } else { diff --git a/src/macros.rs b/src/macros.rs index a393399..2dc64da 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -4,7 +4,7 @@ macro_rules! khprint { ($($arg:tt)*) => ({ let line = format!($($arg)*); #[cfg(test)] { - use testutils; + use utils::stdioutils; testutils::test_stdout_write(&line); } print!("{}", line); @@ -15,17 +15,17 @@ macro_rules! khprint { macro_rules! khprintln { () => ({ #[cfg(test)] { - use testutils; - testutils::test_stdout_write("\n"); + use utils::stdioutils; + stdioutils::test_stdout_write("\n"); } println!(); }); ($($arg:tt)*) => ({ let line = format!($($arg)*); #[cfg(test)] { - use testutils; - testutils::test_stdout_write(&line); - testutils::test_stdout_write("\n"); + use utils::stdioutils; + stdioutils::test_stdout_write(&line); + stdioutils::test_stdout_write("\n"); } println!("{}", line); }) diff --git a/src/seqfile.rs b/src/seqfile.rs index adb1c93..66caed3 100644 --- a/src/seqfile.rs +++ b/src/seqfile.rs @@ -1,23 +1,18 @@ -extern crate atty; - use std::fs::rename; use std::io; use defaults::*; use utils::fileutil; -pub fn write_to_seqfile(lines: &str) { +pub fn write_to_seqfile(lines: &str) -> io::Result<()> { let tmpfilename = get_datafile("tmpseq"); - if let Err(error) = fileutil::write_file(&tmpfilename, lines) { - error!("Could not write seqfile: {}", error); - return - } + fileutil::write_file(&tmpfilename, lines)?; let seqfile = get_seqfile(); - if let Err(error) = rename(tmpfilename, seqfile) { - error!("{}", error) - } + rename(tmpfilename, seqfile)?; + + Ok(()) } pub fn read_seqfile() -> io::Result<impl Iterator<Item = String>> { @@ -50,7 +45,8 @@ mod tests { let testdir = prepare_testdir("testdir"); let teststr = "Teststr äöüß\n"; - write_to_seqfile(teststr); + write_to_seqfile(teststr).unwrap(); + testdir.child(".khaleesi/seq").assert(teststr); } } diff --git a/src/testutils.rs b/src/testutils.rs index 7593f98..42fa765 100644 --- a/src/testutils.rs +++ b/src/testutils.rs @@ -1,12 +1,7 @@ use assert_fs::prelude::*; use assert_fs::TempDir; use std::path::PathBuf; - -use std::cell::RefCell; -thread_local! { - pub static STDOUT_BUF: RefCell<String> = RefCell::new(String::new()); - pub static STDIN_BUF: RefCell<String> = RefCell::new(String::new()); -} +use std::fs; use defaults; @@ -16,6 +11,7 @@ pub fn path_to(artifact: &str) -> PathBuf { pub fn prepare_testdir_empty() -> TempDir { let testdir = TempDir::new().unwrap(); + fs::create_dir(testdir.child(".khaleesi").path()).unwrap(); defaults::set_khaleesi_dir(testdir.path()); testdir } @@ -25,27 +21,3 @@ pub fn prepare_testdir(template: &str) -> TempDir { testdir.child(".khaleesi/").copy_from(path_to(template), &["*"]).unwrap(); testdir } - -pub fn test_stdout_write(line: &str) { - STDOUT_BUF.with(|cell| cell.borrow_mut().push_str(&line)); -} - -pub fn test_stdout_clear() -> String { - STDOUT_BUF.with(|cell| { - let result = cell.borrow().clone(); - *cell.borrow_mut() = String::new(); - result - }) -} - -pub fn test_stdin_write(text: &str) { - STDIN_BUF.with(|cell| cell.borrow_mut().push_str(&text)); -} - -pub fn test_stdin_clear() -> Vec<String> { - STDIN_BUF.with(|cell| { - let result = cell.borrow().lines().map(|line| line.to_owned()).collect(); - *cell.borrow_mut() = String::new(); - result - }) -} diff --git a/src/utils/fileutil.rs b/src/utils/fileutil.rs index fca810e..ab90a55 100644 --- a/src/utils/fileutil.rs +++ b/src/utils/fileutil.rs @@ -53,33 +53,6 @@ pub fn read_lines_from_file(filepath: &Path) -> io::Result<impl Iterator<Item = lines.map(|result| result.into_iter()) } -pub fn read_single_char(mut source: impl BufRead) -> io::Result<char> { - let mut buf = String::new(); - source.read_line(&mut buf)?; - - buf.chars().next().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "calendar has no path")) -} - -pub fn read_single_char_from_stdin() -> io::Result<char> { - let stdin = std::io::stdin(); - let stdinlock = stdin.lock(); - read_single_char(stdinlock) -} - -#[cfg(not(test))] -pub fn read_lines_from_stdin() -> io::Result<Vec<String>> { - let stdin = io::stdin(); - let lines = stdin.lock().lines(); - lines.collect() -} - -#[cfg(test)] -pub fn read_lines_from_stdin() -> io::Result<Vec<String>> { - use testutils; - let lines = testutils::test_stdin_clear(); - Ok(lines) -} - pub fn read_file_to_string(path: &Path) -> io::Result<String> { let mut file = fs::File::open(&path)?; let mut contents = String::new(); @@ -117,11 +90,4 @@ mod tests { write_file(file.path(), "z\n").unwrap(); file.assert("z\n"); } - - #[test] - fn read_single_char_test() { - let source = "ab".as_bytes(); - let read_char = read_single_char(source).unwrap(); - assert_eq!('a', read_char); - } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 8244c95..b4b17e2 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -2,4 +2,4 @@ pub mod dateutil; pub mod lock; pub mod fileutil; pub mod misc; - +pub mod stdioutils; diff --git a/src/utils/stdioutils.rs b/src/utils/stdioutils.rs new file mode 100644 index 0000000..963cdc0 --- /dev/null +++ b/src/utils/stdioutils.rs @@ -0,0 +1,124 @@ +use std::io; +use std::io::BufRead; + +pub fn read_single_char_from_stdin() -> io::Result<char> { + let stdin = io::stdin(); + let stdinlock = stdin.lock(); + read_single_char(stdinlock) +} + +pub fn read_single_char(mut source: impl BufRead) -> io::Result<char> { + let mut buf = String::new(); + source.read_line(&mut buf)?; + + buf.chars().next().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "calendar has no path")) +} + +#[cfg(not(test))] +pub use self::production::*; +#[cfg(test)] +pub use self::test::*; +#[cfg(test)] +pub use self::fixtures::*; + +#[cfg(not(test))] +mod production { + use super::*; + + pub fn read_lines_from_stdin() -> io::Result<Vec<String>> { + let stdin = io::stdin(); + let lines = stdin.lock().lines(); + lines.collect() + } + + pub fn is_stdin_tty() -> bool { + atty::is(atty::Stream::Stdin) + } + + pub fn is_stdout_tty() -> bool { + atty::is(atty::Stream::Stdout) + } +} + +#[cfg(test)] +mod test { + use super::*; + + pub fn read_lines_from_stdin() -> io::Result<Vec<String>> { + let lines = fixtures::test_stdin_clear(); + Ok(lines) + } + + pub fn is_stdin_tty() -> bool { + fixtures::test_stdin_is_tty() + } + + pub fn is_stdout_tty() -> bool { + fixtures::test_stdout_is_tty() + } + +} + +#[cfg(test)] +pub mod fixtures { + use std::cell::RefCell; + thread_local! { + pub static STDOUT_BUF: RefCell<String> = RefCell::new(String::new()); + pub static STDIN_BUF: RefCell<String> = RefCell::new(String::new()); + pub static STDIN_TTY: RefCell<bool> = RefCell::new(true); + pub static STDOUT_TTY: RefCell<bool> = RefCell::new(true); + } + + pub fn test_stdout_write(line: &str) { + STDOUT_BUF.with(|cell| cell.borrow_mut().push_str(&line)); + } + + pub fn test_stdout_clear() -> String { + STDOUT_BUF.with(|cell| { + let result = cell.borrow().clone(); + *cell.borrow_mut() = String::new(); + result + }) + } + + pub fn test_stdout_set_tty(istty: bool) { + STDOUT_TTY.with(|cell| { *cell.borrow_mut() = istty } ); + } + + pub fn test_stdout_is_tty() -> bool { + STDOUT_TTY.with(|cell| { *cell.borrow() } ) + } + + pub fn test_stdin_write(text: &str) { + test_stdin_set_tty(false); + STDIN_BUF.with(|cell| cell.borrow_mut().push_str(&text)); + } + + pub fn test_stdin_clear() -> Vec<String> { + STDIN_BUF.with(|cell| { + let result = cell.borrow().lines().map(|line| line.to_owned()).collect(); + *cell.borrow_mut() = String::new(); + result + }) + } + + pub fn test_stdin_set_tty(istty: bool) { + STDIN_TTY.with(|cell| { *cell.borrow_mut() = istty } ); + } + + pub fn test_stdin_is_tty() -> bool { + STDIN_TTY.with(|cell| { *cell.borrow() } ) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn read_single_char_test() { + let source = "ab".as_bytes(); + let read_char = read_single_char(source).unwrap(); + assert_eq!('a', read_char); + } +} |