Skip to content

Commit

Permalink
Allow - to read/write from/to stdin/stdout
Browse files Browse the repository at this point in the history
Needs to write to a buffer due to zip-rs/zip-old#16
  • Loading branch information
nabijaczleweli committed Feb 14, 2017
1 parent e2fa364 commit 7beb3f4
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 37 deletions.
4 changes: 4 additions & 0 deletions gen-epub-book.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,14 @@ Exit values and possible errors:

File to parse, must exist, must comply with the DESCRIPTOR FORMAT.

Special case: '-' to read from stdin.

OUT_FILE

File to write the book to, parent directory needn't exist.

Special case: '-' to write to stdout.

## DESCRIPTOR FORMAT

The descriptor consists of multiple lines in the format *"Key: Value"*, unknown
Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,16 @@
//!
//! ```text
//! File to parse, must exist, must comply with the DESCRIPTOR FORMAT.
//!
//! Special case: '-' to read from stdin.
//! ```
//!
//! OUT_FILE
//!
//! ```text
//! File to write the book to, parent directory needn't exist.
//!
//! Special case: '-' to write to stdout.
//! ```
//!
//! ## DESCRIPTOR FORMAT
Expand Down
77 changes: 54 additions & 23 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ extern crate gen_epub_book;

use std::process::exit;
use std::fs::{self, File};
use std::io::{Write, stderr};
use std::io::{Write, Cursor, stdin, stderr, stdout};
use self::gen_epub_book::{ops, Options, Error};


Expand All @@ -23,37 +23,68 @@ fn actual_main() -> i32 {
fn result_main() -> Result<(), Error> {
let opts = Options::parse();

let descriptors = try!(ops::parse_descriptor("input file",
&mut try!(File::open(&opts.source_file.1).map_err(|_| {
Error::Io {
desc: "input file",
op: "open",
more: None,
}
}))));
let descriptors = try!(if let Some(ref infile) = opts.source_file.as_ref() {
ops::parse_descriptor("input file",
&mut try!(File::open(&infile.1).map_err(|_| {
Error::Io {
desc: "input file",
op: "open",
more: None,
}
})))
} else {
ops::parse_descriptor("stdin", &mut stdin())
});

if opts.verbose {
let _ = writeln!(stderr(), "Loaded descriptor file {} with {} entries.", opts.source_file.0, descriptors.len());
let _ = writeln!(stderr(),
"Loaded descriptor {}{} with {} entries.",
if opts.source_file.is_some() {
"file "
} else {
""
},
if let Some(ref infile) = opts.source_file.as_ref() {
&infile.0
} else {
""
},
descriptors.len());
}

let mut book = try!(ops::EPubBook::from_elements(descriptors));
try!(book.normalise_paths(&opts.relative_root, opts.verbose, &mut stderr()));

if let Some(p) = opts.output_file.1.parent() {
if !p.exists() && fs::create_dir_all(p).is_ok() && opts.verbose {
let _ = writeln!(stderr(),
"Created directory {}.",
opts.output_file.0[..opts.output_file.0.rfind('/').or_else(|| opts.output_file.0.rfind('\\')).unwrap() + 1].to_string());
if let Some(ref outfile) = opts.output_file.as_ref() {
if let Some(p) = outfile.1.parent() {
if !p.exists() && fs::create_dir_all(p).is_ok() && opts.verbose {
let _ = writeln!(stderr(),
"Created directory {}.",
outfile.0[..outfile.0.rfind('/').or_else(|| outfile.0.rfind('\\')).unwrap() + 1].to_string());
}
}
}
let mut outf = try!(File::create(&opts.output_file.1).map_err(|_| {
Error::Io {
desc: "output file",
op: "create",
more: None,
}
}));
try!(book.write_zip(&mut outf, opts.verbose, &mut stderr()));

if let Some(ref outfile) = opts.output_file.as_ref() {
let mut outf = try!(File::create(&outfile.1).map_err(|_| {
Error::Io {
desc: "output file",
op: "create",
more: None,
}
}));
try!(book.write_zip(&mut outf, opts.verbose, &mut stderr()));
} else {
let mut buf = Cursor::new(vec![]);
try!(book.write_zip(&mut buf, opts.verbose, &mut stderr()));
try!(stdout().write_all(buf.get_ref()).map_err(|_| {
Error::Io {
desc: "stdout",
op: "write",
more: Some("final ePub"),
}
}));
}

Ok(())
}
36 changes: 22 additions & 14 deletions src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! ```no_run
//! # use gen_epub_book::Options;
//! let options = Options::parse();
//! println!("Assembling {} to {}", options.source_file.0, options.output_file.0);
//! println!("{}sing verbose output", if options.verbose {"U"} else {"Not u"});
//! ```

Expand All @@ -19,12 +19,12 @@ use std::fs;
/// Representation of the application's all configurable values.
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Options {
/// The descriptor file.
pub source_file: (String, PathBuf),
/// The descriptor file, or `None` for stdin.
pub source_file: Option<(String, PathBuf)>,
/// The root for relative source paths.
pub relative_root: (String, PathBuf),
/// The file to insert the assembled ePub to.
pub output_file: (String, PathBuf),
/// The file to insert the assembled ePub to, or `None` for stdout.
pub output_file: Option<(String, PathBuf)>,
/// Whether to print more information. Default: false
pub verbose: bool,
}
Expand All @@ -39,24 +39,32 @@ impl Options {
.arg(Arg::from_usage("-v --verbose 'Print more information'"))
.get_matches();

let source = matches.value_of("SOURCE").unwrap();
let target = matches.value_of("TARGET").unwrap();
let source = Options::optional_fname_arg(matches.value_of("SOURCE").unwrap());
let target = Options::optional_fname_arg(matches.value_of("TARGET").unwrap());
Options {
source_file: (source.to_string(), PathBuf::from(source)),
relative_root: match source.rfind('/').or_else(|| source.rfind('\\')) {
Some(s) => (source[..s + 1].to_string(), PathBuf::from(&source[..s])),
source_file: source.map(|s| (s.to_string(), PathBuf::from(s))),
relative_root: match source.and_then(|src| src.rfind('/').or_else(|| src.rfind('\\'))) {
Some(s) => (source.unwrap()[..s + 1].to_string(), PathBuf::from(&source.unwrap()[..s])),
None => ("".to_string(), PathBuf::from(".")),
},
output_file: (target.to_string(), PathBuf::from(target)),
output_file: target.map(|tgt| (tgt.to_string(), PathBuf::from(tgt))),
verbose: matches.is_present("verbose"),
}
}

fn source_file_validator(s: String) -> Result<(), String> {
fs::canonicalize(&s).map_err(|_| format!("Source file \"{}\" not found", s)).and_then(|f| if f.is_file() {
if s == "-" {
Ok(())
} else {
Err(format!("Source file \"{}\" not actualy a file", s))
})
fs::canonicalize(&s).map_err(|_| format!("Source file \"{}\" not found", s)).and_then(|f| if f.is_file() {
Ok(())
} else {
Err(format!("Source file \"{}\" not actualy a file", s))
})
}
}

fn optional_fname_arg(s: &str) -> Option<&str> {
if s == "-" { None } else { Some(s) }
}
}

0 comments on commit 7beb3f4

Please sign in to comment.