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
use clap::{ErrorKind as ClapErrorKind, Error as ClapError, AppSettings, Arg};
use std::path::{PathBuf, Path};
use std::fs;
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Options {
pub source_dir: (String, PathBuf),
pub output_dir: (String, PathBuf),
}
impl Options {
pub fn parse() -> Options {
let matches = app_from_crate!("\n")
.setting(AppSettings::ColoredHelp)
.arg(Arg::from_usage("<IN_DIR> 'Directory to generate a blogue from'").validator(Options::source_directory_validator))
.arg(Arg::from_usage("<OUT_DIR> 'Directory to generate the blogue into'").validator(Options::output_directory_validator))
.arg(Arg::from_usage("-f --force 'Allow the output directory to exist, overriding it'"))
.get_matches();
Options {
source_dir: matches.value_of("IN_DIR")
.map(|s| {
({
let mut src = s.to_string();
if !['/', '\\'].contains(&src.chars().last().unwrap()) {
src.push('/');
}
src
},
PathBuf::from(s).canonicalize().unwrap())
})
.unwrap(),
output_dir: matches.value_of("OUT_DIR")
.map(|o| {
{
let mut p = PathBuf::from(&o);
if !p.is_absolute() {
p = PathBuf::from(format!("./{}", o));
}
if p.exists() {
if !matches.is_present("force") {
ClapError {
message: format!("Output directory \"{}\" already exists", p.display()),
kind: ClapErrorKind::InvalidValue,
info: None,
}
.exit();
} else {
fs::remove_dir_all(p).expect("failed to remove preexisting output directory");
}
}
}
({
let mut out = o.to_string();
if !['/', '\\'].contains(&out.chars().last().unwrap()) {
out.push('/');
}
out
},
{
let fname = Path::new(&o).file_name().unwrap();
let mut p = PathBuf::from(&o);
if !p.is_absolute() {
p = PathBuf::from(format!("./{}", o));
}
p.parent().unwrap().canonicalize().unwrap_or_else(|_| Path::new(".").canonicalize().unwrap()).join(fname)
})
})
.unwrap(),
}
}
fn source_directory_validator(s: String) -> Result<(), String> {
fs::canonicalize(&s).map_err(|_| format!("Input directory \"{}\" not found", s)).and_then(|f| if f.is_file() {
Err(format!("Input directory \"{}\" not actualy a directory", s))
} else {
Ok(())
})
}
fn output_directory_validator(s: String) -> Result<(), String> {
let mut p = PathBuf::from(&s);
if !p.is_absolute() {
p = PathBuf::from(format!("./{}", s));
}
if p.parent().is_some() {
p.pop();
fs::canonicalize(&p).map_err(|_| format!("Output directory's parent directory \"{}\" nonexistant", p.display())).and_then(|f| if !f.is_file() {
Ok(())
} else {
Err(format!("Output directory's parent directory \"{}\" actually a file", p.display()))
})
} else {
Ok(())
}
}
}