Skip to content

Commit b585e97

Browse files
committed
clap3 & irx-config
1 parent 6b7f13b commit b585e97

File tree

4 files changed

+114
-103
lines changed

4 files changed

+114
-103
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
- Update `clap` to 3.2, use `irx-config` instead of `clap_conf`
1011
- Add #[must_use] to prevent hanging field writers
1112

1213
## [v0.26.0] - 2022-10-07

Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,21 @@ required-features = ["bin"]
3838

3939
[features]
4040
default = ["bin", "json", "yaml"]
41-
bin = ["dep:clap", "dep:clap_conf", "dep:env_logger"]
41+
bin = ["dep:clap", "dep:env_logger", "serde", "dep:irx-config"]
4242
json = ["dep:serde_json"]
4343
yaml = ["dep:serde_yaml"]
4444

4545
[dependencies]
46-
clap = { version = "2.34", optional = true }
47-
clap_conf = { version = "0.1.5", optional = true }
46+
clap = { version = "3.2", optional = true }
47+
irx-config = { version = "2.3.1", features = ["cmd", "toml-parser"], optional = true }
4848
env_logger = { version = "0.9", optional = true }
4949
inflections = "1.1"
5050
log = { version = "~0.4", features = ["std"] }
5151
quote = "1.0"
5252
proc-macro2 = "1.0"
5353
anyhow = "1.0"
5454
thiserror = "1.0"
55+
serde = { version = "1.0", optional = true }
5556
serde_json = { version = "1.0.85", optional = true }
5657
serde_yaml = { version = "0.9.11", optional = true }
5758

src/main.rs

Lines changed: 70 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,70 @@
11
#![recursion_limit = "128"]
22

3-
use log::{error, info};
4-
use std::path::{Path, PathBuf};
3+
use log::{debug, error, info};
54

65
use std::fs::File;
76
use std::io::Write;
87
use std::process;
98

109
use anyhow::{Context, Result};
11-
use clap::{App, Arg};
10+
use clap::{Arg, Command};
1211

1312
use svd2rust::{
1413
generate, load_from,
1514
util::{self, build_rs, Config, SourceType, Target},
1615
};
1716

17+
fn parse_configs(app: Command) -> Result<Config> {
18+
use irx_config::parsers::{cmd, toml};
19+
use irx_config::ConfigBuilder;
20+
let irxconfig = ConfigBuilder::default()
21+
.append_parser(
22+
cmd::ParserBuilder::new(app)
23+
.single_flags_as_bool(true)
24+
.build()?,
25+
)
26+
.append_parser(
27+
toml::ParserBuilder::default()
28+
.default_path("svd2rust.toml")
29+
.path_option("config")
30+
.ignore_missing_file(true)
31+
.build()?,
32+
)
33+
.load()?;
34+
35+
irxconfig.get().map_err(Into::into)
36+
}
37+
1838
fn run() -> Result<()> {
19-
use clap_conf::prelude::*;
2039
use std::io::Read;
2140

22-
let matches = App::new("svd2rust")
41+
let log_help = format!(
42+
"Choose which messages to log (overrides {})",
43+
env_logger::DEFAULT_FILTER_ENV
44+
);
45+
46+
let app = Command::new("svd2rust")
2347
.about("Generate a Rust API from SVD files")
2448
.arg(
2549
Arg::with_name("input")
2650
.help("Input SVD file")
27-
.short("i")
51+
.short('i')
2852
.takes_value(true)
2953
.value_name("FILE"),
3054
)
3155
.arg(
32-
Arg::with_name("output")
56+
Arg::with_name("output_dir")
3357
.long("output-dir")
3458
.help("Directory to place generated files")
35-
.short("o")
59+
.short('o')
3660
.takes_value(true)
3761
.value_name("PATH"),
3862
)
3963
.arg(
4064
Arg::with_name("config")
4165
.long("config")
4266
.help("Config TOML file")
43-
.short("c")
67+
.short('c')
4468
.takes_value(true)
4569
.value_name("TOML_FILE"),
4670
)
@@ -52,7 +76,7 @@ fn run() -> Result<()> {
5276
.value_name("ARCH"),
5377
)
5478
.arg(
55-
Arg::with_name("nightly_features")
79+
Arg::with_name("nightly")
5680
.long("nightly")
5781
.help("Enable features only available to nightly rustc"),
5882
)
@@ -72,7 +96,7 @@ fn run() -> Result<()> {
7296
.arg(
7397
Arg::with_name("generic_mod")
7498
.long("generic_mod")
75-
.short("g")
99+
.short('g')
76100
.help("Push generic mod in separate file"),
77101
)
78102
.arg(
@@ -93,13 +117,13 @@ fn run() -> Result<()> {
93117
.arg(
94118
Arg::with_name("make_mod")
95119
.long("make_mod")
96-
.short("m")
120+
.short('m')
97121
.help("Create mod.rs instead of lib.rs, without inner attributes"),
98122
)
99123
.arg(
100124
Arg::with_name("strict")
101125
.long("strict")
102-
.short("s")
126+
.short('s')
103127
.help("Make advanced checks due to parsing SVD"),
104128
)
105129
.arg(
@@ -120,22 +144,31 @@ fn run() -> Result<()> {
120144
.arg(
121145
Arg::with_name("log_level")
122146
.long("log")
123-
.short("l")
124-
.help(&format!(
125-
"Choose which messages to log (overrides {})",
126-
env_logger::DEFAULT_FILTER_ENV
127-
))
147+
.short('l')
148+
.help(log_help.as_ref())
128149
.takes_value(true)
129150
.possible_values(&["off", "error", "warn", "info", "debug", "trace"]),
130151
)
131152
.version(concat!(
132153
env!("CARGO_PKG_VERSION"),
133154
include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))
134-
))
135-
.get_matches();
155+
));
156+
157+
let mut config = match parse_configs(app) {
158+
Ok(config) => {
159+
setup_logging(&config.log_level);
160+
config
161+
}
162+
Err(e) => {
163+
setup_logging(&None);
164+
return Err(e);
165+
}
166+
};
167+
168+
debug!("Current svd2rust config: {config:#?}");
136169

137170
let input = &mut String::new();
138-
match matches.value_of("input") {
171+
match config.input.as_ref() {
139172
Some(file) => {
140173
File::open(file)
141174
.context("Cannot open the SVD file")?
@@ -151,75 +184,10 @@ fn run() -> Result<()> {
151184
}
152185
}
153186

154-
let path = PathBuf::from(matches.value_of("output").unwrap_or("."));
155-
156-
let config_filename = matches.value_of("config").unwrap_or("");
157-
158-
let cfg = with_toml_env(&matches, &[config_filename, "svd2rust.toml"]);
159-
160-
setup_logging(&cfg);
161-
162-
let target = cfg
163-
.grab()
164-
.arg("target")
165-
.conf("target")
166-
.done()
167-
.map(|s| Target::parse(&s))
168-
.unwrap_or_else(|| Ok(Target::default()))?;
169-
170-
let nightly =
171-
cfg.bool_flag("nightly_features", Filter::Arg) || cfg.bool_flag("nightly", Filter::Conf);
172-
let generic_mod =
173-
cfg.bool_flag("generic_mod", Filter::Arg) || cfg.bool_flag("generic_mod", Filter::Conf);
174-
let make_mod =
175-
cfg.bool_flag("make_mod", Filter::Arg) || cfg.bool_flag("make_mod", Filter::Conf);
176-
let const_generic =
177-
cfg.bool_flag("const_generic", Filter::Arg) || cfg.bool_flag("const_generic", Filter::Conf);
178-
let ignore_groups =
179-
cfg.bool_flag("ignore_groups", Filter::Arg) || cfg.bool_flag("ignore_groups", Filter::Conf);
180-
let keep_list =
181-
cfg.bool_flag("keep_list", Filter::Arg) || cfg.bool_flag("keep_list", Filter::Conf);
182-
let strict = cfg.bool_flag("strict", Filter::Arg) || cfg.bool_flag("strict", Filter::Conf);
183-
let pascal_enum_values = cfg.bool_flag("pascal_enum_values", Filter::Arg)
184-
|| cfg.bool_flag("pascal_enum_values", Filter::Conf);
185-
let derive_more =
186-
cfg.bool_flag("derive_more", Filter::Arg) || cfg.bool_flag("derive_more", Filter::Conf);
187-
let feature_group =
188-
cfg.bool_flag("feature_group", Filter::Arg) || cfg.bool_flag("feature_group", Filter::Conf);
189-
let feature_peripheral = cfg.bool_flag("feature_peripheral", Filter::Arg)
190-
|| cfg.bool_flag("feature_peripheral", Filter::Conf);
191-
let max_cluster_size = cfg.bool_flag("max_cluster_size", Filter::Arg)
192-
|| cfg.bool_flag("max_cluster_size", Filter::Conf);
193-
194-
let mut source_type = cfg
195-
.grab()
196-
.arg("source_type")
197-
.conf("source_type")
198-
.done()
199-
.and_then(|s| SourceType::from_extension(&s))
200-
.unwrap_or_default();
201-
202-
if let Some(file) = matches.value_of("input") {
203-
source_type = SourceType::from_path(Path::new(file))
187+
if let Some(file) = config.input.as_ref() {
188+
config.source_type = SourceType::from_path(file)
204189
}
205-
206-
let config = Config {
207-
target,
208-
nightly,
209-
generic_mod,
210-
make_mod,
211-
const_generic,
212-
ignore_groups,
213-
keep_list,
214-
strict,
215-
pascal_enum_values,
216-
derive_more,
217-
feature_group,
218-
feature_peripheral,
219-
max_cluster_size,
220-
output_dir: path.clone(),
221-
source_type,
222-
};
190+
let path = &config.output_dir;
223191

224192
info!("Parsing device from SVD file");
225193
let device = load_from(input, &config)?;
@@ -229,25 +197,28 @@ fn run() -> Result<()> {
229197
let items = generate::device::render(&device, &config, &mut device_x)
230198
.with_context(|| "Error rendering device")?;
231199

232-
let filename = if make_mod { "mod.rs" } else { "lib.rs" };
200+
let filename = if config.make_mod { "mod.rs" } else { "lib.rs" };
233201
let mut file = File::create(path.join(filename)).expect("Couldn't create output file");
234202

235203
let data = items.to_string().replace("] ", "]\n");
236204
file.write_all(data.as_ref())
237205
.expect("Could not write code to lib.rs");
238206

239-
if target == Target::CortexM
240-
|| target == Target::Msp430
241-
|| target == Target::XtensaLX
242-
|| target == Target::RISCV
207+
if [
208+
Target::CortexM,
209+
Target::Msp430,
210+
Target::XtensaLX,
211+
Target::RISCV,
212+
]
213+
.contains(&config.target)
243214
{
244215
writeln!(File::create(path.join("device.x"))?, "{}", device_x)?;
245216
writeln!(File::create(path.join("build.rs"))?, "{}", build_rs())?;
246217
}
247218

248-
if feature_group || feature_peripheral {
219+
if config.feature_group || config.feature_peripheral {
249220
let mut features = Vec::new();
250-
if feature_group {
221+
if config.feature_group {
251222
features.extend(
252223
util::group_names(&device)
253224
.iter()
@@ -259,7 +230,7 @@ fn run() -> Result<()> {
259230
.collect();
260231
features.push(format!("all-groups = [{}]\n", add_groups.join(",")))
261232
}
262-
if feature_peripheral {
233+
if config.feature_peripheral {
263234
features.extend(
264235
util::peripheral_names(&device)
265236
.iter()
@@ -287,7 +258,7 @@ fn run() -> Result<()> {
287258
Ok(())
288259
}
289260

290-
fn setup_logging<'a>(getter: &'a impl clap_conf::Getter<'a, String>) {
261+
fn setup_logging(log_level: &Option<String>) {
291262
// * Log at info by default.
292263
// * Allow users the option of setting complex logging filters using
293264
// env_logger's `RUST_LOG` environment variable.
@@ -302,7 +273,7 @@ fn setup_logging<'a>(getter: &'a impl clap_conf::Getter<'a, String>) {
302273
if log_lvl_from_env {
303274
log::set_max_level(log::LevelFilter::Trace);
304275
} else {
305-
let level = match getter.grab().arg("log_level").conf("log_level").done() {
276+
let level = match log_level {
306277
Some(lvl) => lvl.parse().unwrap(),
307278
None => log::LevelFilter::Info,
308279
};

0 commit comments

Comments
 (0)