openrr_apps_config/
config.rs

1use std::{fs, path::PathBuf};
2
3use anyhow::Result;
4use clap::{Parser, ValueEnum};
5use openrr_apps::utils::init_tracing;
6use schemars::schema_for;
7use serde::Deserialize;
8use tracing::debug;
9
10#[derive(Debug, Parser)]
11#[clap(name = env!("CARGO_BIN_NAME"))]
12struct Args {
13    #[clap(subcommand)]
14    subcommand: Subcommand,
15}
16
17#[derive(Debug, Parser)]
18enum Subcommand {
19    /// Generate JSON schema for the specified config file.
20    Schema {
21        /// Kind of config file.
22        #[clap(value_enum, ignore_case = true)]
23        kind: ConfigKind,
24    },
25    Merge {
26        /// Path to the setting file.
27        #[clap(long, value_parser)]
28        config_path: PathBuf,
29        /// Config to overwrite
30        #[clap(long)]
31        config: String,
32    },
33}
34
35#[derive(Debug, Clone, Copy, ValueEnum)]
36enum ConfigKind {
37    RobotConfig,
38    RobotTeleopConfig,
39}
40
41#[derive(Debug, Deserialize)]
42#[serde(untagged)]
43enum Config {
44    RobotConfig(#[allow(dead_code)] Box<openrr_apps::RobotConfig>),
45    RobotTeleopConfig(#[allow(dead_code)] Box<openrr_apps::RobotTeleopConfig>),
46}
47
48fn main() -> Result<()> {
49    init_tracing();
50    let args = Args::parse();
51    debug!(?args);
52
53    match args.subcommand {
54        Subcommand::Schema { kind } => {
55            let schema = match kind {
56                ConfigKind::RobotConfig => schema_for!(openrr_apps::RobotConfig),
57                ConfigKind::RobotTeleopConfig => schema_for!(openrr_apps::RobotTeleopConfig),
58            };
59            println!("{}", serde_json::to_string_pretty(&schema).unwrap());
60        }
61        Subcommand::Merge {
62            config_path,
63            config: overwrite,
64        } => {
65            let s = &fs::read_to_string(config_path)?;
66            let s = &openrr_config::overwrite_str(s, &overwrite)?;
67            // check if the edited document is valid config.
68            let _base: Config = toml::from_str(s)?;
69            println!("{s}");
70        }
71    }
72
73    Ok(())
74}
75
76#[cfg(test)]
77mod tests {
78    use clap::CommandFactory;
79
80    use super::*;
81
82    #[test]
83    fn assert_app() {
84        Args::command().debug_assert();
85    }
86}