簡體   English   中英

在 clap 中動態生成帶有格式化描述的子命令

[英]Dynamically generate subcommands with formatted description in clap

我想根據HashMap內容為clap生成子命令。 為此,我正在迭代這些項目以創建新的App實例。 問題是App.about()需要&str作為輸入,而我無法從format!()宏中創建一個壽命足夠長的輸入。

這是一個示例( 操場):

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[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

如何將格式化的字符串傳遞給about()方法?

首先,看起來您有一個不相關的錯誤,我會提到它只是為了減少對代碼示例正確性的混淆。 我沒有用clap自己,但它看起來像這樣被改寫應用程序的about反復

app = app.subcommand(App::new(*key)).about(about.as_str());

你可能是說

app = app.subcommand(App::new(*key).about(about.as_str()));

將其應用於子命令。


這里的問題是App不想擁有這些字符串,所以需要有另一個對象來擁有。 一種方法是構建一個包含format!的地圖format! 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()));
    }

地圖abouts必須與app一樣長。

如果你只打算在你的程序中這樣做一次,那么你可能會泄漏內存format! 分配:

    for (key, value) in map.iter() {
        let about = &*Box::leak(format!("Value: {}", value).into_boxed_str());
        app = app.subcommand(App::new(*key).about(about));
    }

如果你希望能夠回收內存,但不希望有處理類似構造的結構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));
    }

就像在abouts解決方案中一樣,只要您保留app ,您就需要保留arena

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM