我在这个问题上兜圈子已经有一段时间了,还没有找到一个好的解决办法:
我在同一个代码库中有一堆模拟。我试着像个成年人一样,使用命令行参数来选择运行哪些模拟以及使用哪些参数。问题是,许多参数在不同的模拟之间共享,有些参数集传递给共享组件。
例如,下面我有三个模拟,其中两个共享"Threaded"参数子集,另外两个共享MazeCli
参数子集,这是Maze
trait所需要的(在完整的模拟中,有更多的参数和组合)。
use clap::*;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[command(subcommand)]
sim: Simulation,
}
#[derive(Subcommand, Debug)]
enum Simulation {
Maze {
maze_args: MazeCli,
thread_args: ThreadCli,
},
ThreadedMaze {
maze_args: MazeCli,
},
Threaded {
thread_args: ThreadCli,
},
}
trait Maze {
fn new(args: MazeCli) -> Self;
}
#[derive(Args, Debug, Clone)]
struct MazeCli {
squares: usize,
openness: f64,
}
#[derive(Args, Debug, Clone)]
struct ThreadCli {
threads: usize,
}
fn main() {
let config = Cli::parse();
println!("{:?}", config);
}
这个版本失败了,因为它想让MazeCli
和ThreadCli
实现ValueEnum
(据我所知-实际的错误很长,没有帮助)。ValueEnum不能为结构体派生。我尝试了一些其他的方法,但没有得到任何编译。
我可以用一个简单的arg列表来完成所有的事情,但是错误消息不会告诉您运行的特定子命令需要什么。
我可以手动指定每个列表,但这是一堆样板文件,特别是在考虑默认值的情况下。
正确的方法是什么?它是拍手支持的东西吗?
附加问题:
- 如果这是可能的,那么特定的子命令是否有办法覆盖其特定情况下的通用默认值(例如,如果一个模拟在默认情况下需要两倍于标准的线程)。
- 我可以让
default
值以某种方式回退到该结构体的Default
trait实现吗?
1条答案
按热度按时间9gm1akwq1#
使用
#[command(flatten)]
:我可以让默认值以某种方式回退到该结构体的Default trait实现吗?
使用
default_value_t
,不带参数,默认为Default::default()
:如果这是可能的,那么特定的子命令是否有办法覆盖其特定情况下的通用默认值(例如,如果一个模拟在默认情况下需要两倍于标准的线程)。
我认为不使用单独的结构体是不可能的。