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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
extern crate argonaut;
use std::env;
use argonaut::{ArgDef, parse, ParseError};
use std::process;
fn main() {
if let Some(exit_code) = epub_main() {
process::exit(exit_code);
}
}
fn create_epub(spec_file: &str, target_path: Option<String>, is_raw_spec: bool) {
println!("Creating epub from spec: '{}' (target_path: {:?}, is raw spec?: {})",
spec_file, target_path, is_raw_spec);
}
fn print_spec_template() {
println!("<Template goes here>");
}
fn create_epub_from_folder(folder: &str) {
println!("Creating epub from image folder '{}'...", folder);
}
fn epub_main() -> Option<i32> {
let args = env::args().skip(1).collect::<Vec<_>>();
let description = "
Program to create ePub e-book files.
";
match parse("epub", &args, vec![
// Defines a subcommand named 'create' that will run the given closure
// or function when it is encountered during a parse.
// The 'program' argument is a String with the name of the command that
// is currently running, in this case "epub create".
ArgDef::subcommand("create", |program, args| {
let mut spec_file = String::new();
let mut target_path: Option<String> = None;
let mut is_raw_spec = false;
parse(program, args, vec![
ArgDef::positional("spec_file", &mut spec_file)
.help("The TOML specification of the book"),
ArgDef::setting("target_path", &mut target_path).short("t")
.help("
A specific path to compile the ePub to. Defaults to a
name/author coupling in the current working directory
"),
ArgDef::flag("is_raw_spec", &mut is_raw_spec).short("r")
.help("
Interpret the spec-file argument as the contents of the
specification file, instead of a path to it.
"),
// This creates a simple 'interrupt' flag for '--help' that
// shows help for this subcommand with the given description.
ArgDef::default_help("
Compiles an ePub from a markdown source and a TOML specification. The files in
the specification are sought relatively to the location of the specification
file, so use absolute paths when needed. If no arguments are given, the
created file will be found in the active working directory.
")
// The common short form '-h' is not bound by default.
.short("h"),
])?;
// The subcommand closure returns the same type as 'parse', so this
// is the expected way to handle subparsing.
// The parse has succeeded and all required values assigned.
create_epub(&spec_file, target_path, is_raw_spec);
// In this simple example, no error code is returned.
// But if create_epub for instance checked whether the folder existed
// an error code for that might be passed here, so that 'main' could
// call process::exit with it later.
Ok(None)
})
.help("Creates a new ePub from a given specification."),
ArgDef::subcommand("example", |program, args| {
parse(program, args, vec![])?;
print_spec_template();
Ok(None)
})
.help("Prints a template for an ePub specification file."),
ArgDef::subcommand("from_folder", |program, args| {
let mut folder = String::new();
parse(program, args, vec![
ArgDef::positional("folder", &mut folder)
.help("The folder to load images from."),
ArgDef::default_help(
"
Creates a simple epub from the images in the given folder.
This is useful for quickly creating rather bad comic epubs.
"),
])?;
create_epub_from_folder(&folder);
Ok(None)
})
.help("Creates a simple ePub from the images in the given folder."),
ArgDef::default_help(description).short("h"),
ArgDef::default_version(),
])
// This is probably how any subcommand-parsing function should look
// Ok and Interrupt means that it terminated as expected.
// Otherwise return an error code to be set with process::exit.
{
Ok(_) => None,
Err(ParseError::Interrupted(_)) => None,
Err(_) => Some(1),
}
}