1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
//! Subplot top level binary
//!
use anyhow::Result;
use structopt::StructOpt;
use subplot::{resource, DataFile, Style};
use std::fs::write;
use std::path::PathBuf;
use std::process;
mod cli;
#[derive(Debug, StructOpt)]
struct Toplevel {
#[structopt(flatten)]
resources: resource::ResourceOpts,
#[structopt(flatten)]
command: Cmd,
}
impl Toplevel {
fn run(&self) -> Result<()> {
self.command.run()
}
}
#[derive(Debug, StructOpt)]
enum Cmd {
Extract(Extract),
}
impl Cmd {
fn run(&self) -> Result<()> {
match self {
Cmd::Extract(e) => e.run(),
}
}
}
#[derive(Debug, StructOpt)]
/// Extract embedded files from a subplot document
///
/// If no embedded filenames are provided, this will
/// extract all embedded files. if the output directory
/// is not specified then this will extract to the current directory.
struct Extract {
/// Directory to write extracted files to
#[structopt(
name = "DIR",
long = "directory",
short = "d",
parse(from_os_str),
default_value = "."
)]
directory: PathBuf,
/// Don't actually write the files out
#[structopt(long)]
dry_run: bool,
/// Input subplot document filename
#[structopt(parse(from_os_str))]
filename: PathBuf,
/// Names of embedded files to be extracted.
embedded: Vec<String>,
}
impl Extract {
fn run(&self) -> Result<()> {
let doc = cli::load_document(&self.filename, Style::default())?;
let files: Vec<&DataFile> = if self.embedded.is_empty() {
doc.files()
.iter()
.map(Result::Ok)
.collect::<Result<Vec<_>>>()
} else {
self.embedded
.iter()
.map(|filename| cli::extract_file(&doc, filename))
.collect::<Result<Vec<_>>>()
}?;
for f in files {
let outfile = self.directory.join(f.filename());
if self.dry_run {
println!("Would write out {}", outfile.display());
} else {
write(outfile, f.contents())?
}
}
Ok(())
}
}
fn main() {
let args = Toplevel::from_args();
args.resources.handle();
match args.run() {
Ok(_) => {}
Err(e) => {
eprintln!("Failure: {:?}", e);
process::exit(1);
}
}
}
|