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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
//! cli stuff
use {
crate::{
config::options::E62Rs,
error::{Report, Result},
},
clap::Parser,
schemars::generate::SchemaSettings,
std::{
fs::OpenOptions,
io::{BufWriter, Write},
path::Path,
},
};
/// the CLI
#[derive(Parser)]
pub struct Cli {
/// Save instead of printing
#[arg(long)]
pub save: bool,
/// Generate a JSON schemafile based on the defaults
#[arg(short = 's', long)]
pub gen_schema: bool,
/// Generate the default config file
#[arg(short = 'd', long)]
pub gen_default: bool,
/// Generate both the schema and the default config file
#[arg(short = 'a', long)]
pub gen_all: bool,
/// Display localization progress
#[arg(short, long = "localization")]
pub loc_prog: bool,
}
impl Cli {
/// run the CLI
///
/// # Errors
///
/// returns an error if it fails to generate and/or save the json schema
/// returns an error if it fails to generate and/or save the default config
pub async fn run() -> Result<()> {
let argv = Self::parse();
if argv.gen_schema || argv.gen_all {
Self::gen_schema(argv.save)?;
}
if argv.gen_default || argv.gen_all {
Self::gen_defaults(argv.save)?;
}
if argv.loc_prog {
crate::ui::menus::calculate_localization_progress();
}
if argv.gen_default || argv.gen_all || argv.gen_schema || argv.save || argv.loc_prog {
std::process::exit(0);
}
Ok(())
}
/// save a string to a file
///
/// # Arguments
///
/// * `path` - the path to the file being written
/// * `contents` - the data to write to the file
///
/// # Errors
///
/// returns an error if it fails to open `path`
pub fn write_to_file<T>(path: T, contents: &str) -> Result<()>
where
T: AsRef<Path>,
{
let file = OpenOptions::new()
.write(true)
.truncate(true)
.create(true)
.open(path)?;
let mut w = BufWriter::new(file);
w.write_all(contents.as_bytes()).map_err(Report::new)
}
/// generate/save the config schema
///
/// # Arguments
///
/// * `save` - save instead of printing
///
/// # Errors
///
/// returns an error if it fails to convert the schema to a JSON string
/// returns an error if it fails to save the schema to `resources/e62rs.schema.json`
pub fn gen_schema(save: bool) -> Result<()> {
let settings = SchemaSettings::draft2020_12().for_serialize();
let generator = settings.into_generator();
let schema = generator.into_root_schema_for::<E62Rs>();
let schema_str = serde_json::to_string_pretty(&schema)?;
if save {
Self::write_to_file("resources/e62rs.schema.json", &schema_str)?;
} else {
println!("{}", schema_str);
}
Ok(())
}
/// generate/save the default config file
///
/// # Arguments
///
/// * `save` - save instead of printing
///
/// # Errors
///
/// returns an error if it fails to convert the default config to TOML
/// returns an error if it fails to save the default config to `resources/e62rs.default.toml
pub fn gen_defaults(save: bool) -> Result<()> {
let defaults = toml::to_string_pretty(&E62Rs::default())?;
if save {
Self::write_to_file("resources/e62rs.default.toml", &defaults)?;
} else {
println!("{}", defaults);
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use {super::*, tempfile::NamedTempFile};
#[test]
fn test_write_to_file() -> crate::error::Result<()> {
let exfile = NamedTempFile::new()?;
let res = Cli::write_to_file(exfile.path(), "woah");
let contents = std::fs::read_to_string(exfile.path())?;
assert!(res.is_ok(), "failed to write 'woah' to temp file");
assert_eq!(
contents,
"woah".to_string(),
"contents of temp file not correct"
);
Ok(())
}
}