Start using a common helper module for all binaries
This also introduces a tiny abstraction over the common "stdin or
file" pattern that shows up regularly in these tools
Getty Ritter
6 years ago
1 | use std::{fs,io}; | |
2 | ||
3 | pub const VERSION: &'static str = "0.0"; | |
4 | pub const AUTHOR: &'static str = | |
5 | "Getty Ritter <rrecutils@infinitenegativeutility.com>"; | |
6 | ||
7 | pub enum Input { | |
8 | Stdin(io::BufReader<io::Stdin>), | |
9 | File(io::BufReader<fs::File>), | |
10 | } | |
11 | ||
12 | impl io::Read for Input { | |
13 | fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | |
14 | match self { | |
15 | &mut Input::Stdin(ref mut stdin) => | |
16 | stdin.read(buf), | |
17 | &mut Input::File(ref mut file) => | |
18 | file.read(buf), | |
19 | } | |
20 | } | |
21 | } | |
22 | ||
23 | impl io::BufRead for Input { | |
24 | fn fill_buf(&mut self) -> io::Result<&[u8]> { | |
25 | match self { | |
26 | &mut Input::Stdin(ref mut stdin) => | |
27 | stdin.fill_buf(), | |
28 | &mut Input::File(ref mut file) => | |
29 | file.fill_buf(), | |
30 | } | |
31 | } | |
32 | ||
33 | fn consume(&mut self, amt: usize) { | |
34 | match self { | |
35 | &mut Input::Stdin(ref mut stdin) => | |
36 | stdin.consume(amt), | |
37 | &mut Input::File(ref mut file) => | |
38 | file.consume(amt), | |
39 | } | |
40 | } | |
41 | } | |
42 | ||
43 | pub fn input_from_spec<'a>( | |
44 | spec: Option<&'a str> | |
45 | ) -> io::Result<Input> { | |
46 | match spec.unwrap_or("-") { | |
47 | "-" => Ok(Input::Stdin(io::BufReader::new(io::stdin()))), | |
48 | path => { | |
49 | let f = fs::File::open(path)?; | |
50 | Ok(Input::File(io::BufReader::new(f))) | |
51 | } | |
52 | } | |
53 | } | |
54 | ||
55 | pub fn output_from_spec<'a>( | |
56 | spec: Option<&'a str> | |
57 | ) -> io::Result<Box<io::Write>> | |
58 | { | |
59 | match spec.unwrap_or("-") { | |
60 | "-" => Ok(Box::new(io::stdout())), | |
61 | path => Ok(Box::new(fs::File::open(path)?)), | |
62 | } | |
63 | } |
5 | 5 | use std::{fs,io}; |
6 | 6 | use std::convert::From; |
7 | 7 | use std::string::FromUtf8Error; |
8 | ||
9 | mod common; | |
8 | 10 | |
9 | 11 | use rustache::Render; |
10 | 12 | |
63 | 65 | } |
64 | 66 | |
65 | 67 | |
66 | fn run() -> Result<(), FormatErr> { | |
67 | let matches = clap::App::new("rr-format") | |
68 | .version("0.0") | |
69 | .author("Getty Ritter <rrecutils@infinitenegativeutility.com>") | |
68 | fn rr_format_args() -> clap::ArgMatches<'static> { | |
69 | clap::App::new("rr-format") | |
70 | .version(common::VERSION) | |
71 | .author(common::AUTHOR) | |
70 | 72 | .about("Display the Rust AST for a Recutils file") |
71 | 73 | |
72 | 74 | .arg(clap::Arg::with_name("input") |
100 | 102 | .value_name("STRING") |
101 | 103 | .help("The string used to separate each fragment")) |
102 | 104 | |
103 |
.get_matches() |
|
105 | .get_matches() | |
106 | } | |
104 | 107 | |
105 | let stdin = io::stdin(); | |
108 | fn run() -> Result<(), FormatErr> { | |
109 | let matches = rr_format_args(); | |
106 | 110 | |
107 | let input: Box<io::BufRead> = | |
108 | match matches.value_of("input").unwrap_or("-") { | |
109 | "-" => Box::new(stdin.lock()), | |
110 | path => | |
111 | Box::new(io::BufReader::new(fs::File::open(path)?)), | |
112 | }; | |
111 | let input = common::input_from_spec( | |
112 | matches.value_of("input"))?; | |
113 | let mut output = common::output_from_spec( | |
114 | matches.value_of("output"))?; | |
113 | 115 | |
114 | 116 | let template: String = match matches.value_of("mustache") { |
115 | 117 | Some(path) => { |
127 | 129 | recfile.filter_by_type(typ); |
128 | 130 | } |
129 | 131 | |
130 | let mut output: Box<io::Write> = | |
131 | match matches.value_of("output").unwrap_or("-") { | |
132 | "-" => Box::new(io::stdout()), | |
133 | path => Box::new(fs::File::open(path)?), | |
134 | }; | |
135 | 132 | |
136 | 133 | let joiner = matches.value_of("joiner"); |
137 | 134 |
1 | 1 | extern crate clap; |
2 | 2 | extern crate rrecutils; |
3 | 3 | |
4 | mod common; | |
5 | ||
4 | 6 | fn main() { |
5 | 7 | let matches = clap::App::new("rr-sel") |
6 | .version("0.0") | |
7 | .author("Getty Ritter <rrecutils@infinitenegativeutility.com>") | |
8 | .version(common::VERSION) | |
9 | .author(common::AUTHOR) | |
8 | 10 | .about("Print records from a recfile") |
9 | 11 | |
10 | 12 | .arg(clap::Arg::with_name("type") |
2 | 2 | extern crate rrecutils; |
3 | 3 | extern crate serde_json; |
4 | 4 | |
5 |
|
|
5 | mod common; | |
6 | ||
7 | use std::fmt; | |
6 | 8 | |
7 | 9 | use serde_json::Value; |
8 | 10 | use serde_json::map::Map; |
29 | 31 | |
30 | 32 | fn main() { |
31 | 33 | let matches = clap::App::new("rr-to-json") |
32 | .version("0.0") | |
33 | .author("Getty Ritter <rrecutils@infinitenegativeutility.com>") | |
34 | .version(common::VERSION) | |
35 | .author(common::AUTHOR) | |
34 | 36 | .about("Display the Rust AST for a Recutils file") |
35 | 37 | .arg(clap::Arg::with_name("pretty") |
36 | 38 | .short("p") |
48 | 50 | .help("The desired output location (or - for stdout)")) |
49 | 51 | .get_matches(); |
50 | 52 | |
51 |
let |
|
53 | let input = unwrap_err(common::input_from_spec( | |
54 | matches.value_of("input"))); | |
55 | let mut output = unwrap_err(common::output_from_spec( | |
56 | matches.value_of("output"))); | |
52 | 57 | |
53 | let input: Box<io::BufRead> = | |
54 | match matches.value_of("input").unwrap_or("-") { | |
55 | "-" => Box::new(stdin.lock()), | |
56 | path => | |
57 | Box::new(io::BufReader::new(unwrap_err(fs::File::open(path)))), | |
58 | }; | |
59 | ||
60 | let json = Value::Array(unwrap_err(rrecutils::Recfile::parse(input)) | |
61 | .records | |
62 | .iter() | |
63 | .map(|x| record_to_json(x)) | |
64 | .collect()); | |
65 | ||
66 | let mut output: Box<io::Write> = | |
67 | match matches.value_of("output").unwrap_or("-") { | |
68 | "-" => Box::new(io::stdout()), | |
69 | path => Box::new(unwrap_err(fs::File::open(path))), | |
70 | }; | |
58 | let json = Value::Array( | |
59 | unwrap_err(rrecutils::Recfile::parse(input)) | |
60 | .records | |
61 | .iter() | |
62 | .map(|x| record_to_json(x)) | |
63 | .collect()); | |
71 | 64 | |
72 | 65 | let serialized = if matches.is_present("pretty") { |
73 | 66 | unwrap_err(serde_json::to_string_pretty(&json)) |