[英]Dynamically generate subcommands with formatted description in clap
I want to generate subcommands for clap
based on a HashMap
content.我想根据HashMap
内容为clap
生成子命令。 To do that, I'm iterating over the items to create new App
instances.为此,我正在迭代这些项目以创建新的App
实例。 The problem is that App.about()
requires &str
as an input, and I can't make one that lives long enough from the format!()
macro.问题是App.about()
需要&str
作为输入,而我无法从format!()
宏中创建一个寿命足够长的输入。
Here's an example ( playground ):这是一个示例( 操场):
use clap::App;
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert("key", "value");
map.insert("key2", "value2");
map.insert("key3", "value3");
let mut app = App::new("Test").version("1.0");
for (key, value) in map.iter() {
let about = format!("Value: {}", value);
app = app.subcommand(App::new(*key)).about(about.as_str());
}
app.get_matches();
}
Error message:错误信息:
error[E0597]: `about` does not live long enough
--> src/main.rs:14:52
|
14 | app = app.subcommand(App::new(*key)).about(about.as_str());
| ^^^^^ borrowed value does not live long enough
15 | }
| - `about` dropped here while still borrowed
16 |
17 | app.get_matches();
| --- borrow later used here
How can I pass the formatted string to the about()
method?如何将格式化的字符串传递给about()
方法?
First of all, it looks like you have an unrelated mistake, which I'll mention just to reduce confusion about code sample correctness.首先,看起来您有一个不相关的错误,我会提到它只是为了减少对代码示例正确性的混淆。 I haven't used clap
myself, but it looks like this is overwriting the app's about
repeatedly我没有用clap
自己,但它看起来像这样被改写应用程序的about
反复
app = app.subcommand(App::new(*key)).about(about.as_str());
and you probably meant你可能是说
app = app.subcommand(App::new(*key).about(about.as_str()));
to apply it to the subcommand instead.将其应用于子命令。
The problem here is that App
doesn't want to own the strings, so there needs to be another object that does.这里的问题是App
不想拥有这些字符串,所以需要有另一个对象来拥有。 One approach would be to construct a map that contains the format!
一种方法是构建一个包含format!
的地图format!
ted strings (and thus owns them): ted 字符串(因此拥有它们):
let abouts: HashMap<String, String> = map.iter()
.map(|(key, value)| (key.to_string(), format!("Value: {}", value)))
.collect();
for (key, about) in abouts.iter() {
app = app.subcommand(App::new(key.as_str()).about(about.as_str()));
}
The map abouts
must live as long as app
.地图abouts
必须与app
一样长。
If you're only going to do this once in your program, then you can just leak the memory format!
如果你只打算在你的程序中这样做一次,那么你可能会泄漏内存format!
allocated:分配:
for (key, value) in map.iter() {
let about = &*Box::leak(format!("Value: {}", value).into_boxed_str());
app = app.subcommand(App::new(*key).about(about));
}
If you want to be able to reclaim the memory but don't want to have to deal with constructing a structure like abouts
above, because your actual problem is more complex, you can use the typed_arena
crate to provide a place to allocate any number of strings and keep them all alive:如果你希望能够回收内存,但不希望有处理类似构造的结构abouts
之上,因为你实际的问题是比较复杂的,你可以使用typed_arena
箱子提供一个地方分配任何数量的字符串并使它们保持活力:
use typed_arena::Arena;
...
let arena = Arena::new();
for (key, value) in map.iter() {
let about = arena.alloc(format!("Value: {}", value)).as_str();
app = app.subcommand(App::new(*key).about(about));
}
Like in the abouts
solution, you need to keep arena
around as long as you keep app
around.就像在abouts
解决方案中一样,只要您保留app
,您就需要保留arena
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.