plantuml_server_client_rs/config/
args.rs

1use plantuml_parser as parser;
2
3use crate::config::ConfigTrait;
4use crate::{Config, Format, Locate, MetadataVersion, Method, Mode};
5use crate::{PKG_NAME, PKG_VERSION};
6use clap::Parser;
7use const_format::concatcp;
8use std::path::PathBuf;
9use std::sync::Arc;
10use std::time::Duration;
11
12/// The vertion string for `--version` output
13const VERSION: &str = concatcp!(
14    "\n",
15    concatcp!("  ", PKG_NAME, "=", PKG_VERSION, "\n"),
16    concatcp!("  ", parser::PKG_NAME, "=", parser::PKG_VERSION,)
17);
18
19/// The string about `plantuml-server-client` for `--help`
20const ABOUT: &str = std::include_str!("../../docs/include/about.md");
21
22/// The definition of program arguments.
23/// [`Args`] has a higher priority than [`FileConfig`](crate::FileConfig).
24/// If no value is specified for a configuration item in either [`Args`] or [`FileConfig`](crate::FileConfig), the default value is used.
25#[derive(Clone, Debug, Parser)]
26#[command(author, version = VERSION, about = ABOUT)]
27pub struct Args {
28    /// (deprecated) input file path. if not specified, use stdin.
29    #[arg(short, long)]
30    pub input: Option<PathBuf>,
31
32    /// output file prefix. if both of `[INPUT_FILES]` and `--output` are not specified, use stdout.
33    #[arg(short, long)]
34    pub output: Option<PathBuf>,
35
36    /// config file path. if `--config` option is specified and the configuration file fails to load, this program will exit with an error for security reasons.
37    #[arg(short, long)]
38    pub config: Option<PathBuf>,
39
40    /// HTTP Method: `"get"` | `"post"`
41    #[arg(short, long)]
42    pub method: Option<Method>,
43
44    /// Server's URL Prefix. default: `"http://www.plantuml.com/plantuml/"`. example: `"http://localhost:8080/"`.
45    #[arg(short, long)]
46    pub url_prefix: Option<String>,
47
48    /// output format: `"svg"` | `"png"` | `"txt"`
49    #[arg(short, long)]
50    pub format: Option<Format>,
51
52    /// output pre-proccessed data has `.puml` extension
53    #[arg(short = 'C', long)]
54    pub combined: bool,
55
56    /// output path for metadata
57    #[arg(long)]
58    pub metadata: Option<PathBuf>,
59
60    /// watch over input files
61    #[arg(short = 'W', long)]
62    pub watch: bool,
63
64    /// watch throttle msec
65    #[arg(short = 'T', long, default_value_t = 50)]
66    pub watch_throttle: u64,
67
68    /// increase log level: `-v` -> info, `-vv` -> debug.
69    /// if the `PSCR_LOG` environment variable is specified, this `-v` option will ignore.
70    /// related: [`init_logger`][`crate::init_logger`]
71    #[arg(short, long, action = clap::ArgAction::Count)]
72    pub verbose: u8,
73
74    /// input file paths. if not specified, use stdin.
75    pub input_files: Vec<PathBuf>,
76
77    /// The version of metadata
78    #[arg(long, default_value = "v1")]
79    pub metadata_version: MetadataVersion,
80}
81
82impl Args {
83    /// Creates a [`Config`] from [`Args`].
84    pub async fn config(self) -> anyhow::Result<Config> {
85        let mut config = Config::load(&self).await?;
86        config.metadata = self.metadata;
87
88        Ok(config)
89    }
90
91    /// Returns the mode of execution.
92    pub fn mode(&self, current_dir: PathBuf) -> Mode {
93        let input_files = self.input_files();
94
95        if input_files.is_empty() {
96            return Mode::Stdin;
97        }
98
99        if self.watch {
100            let throttle = Duration::from_millis(self.watch_throttle);
101            Mode::new_watch(current_dir, input_files, throttle)
102        } else {
103            Mode::NoWatch(input_files)
104        }
105    }
106
107    /// Returns the locate of output.
108    pub fn output_arc(&self) -> Arc<Locate> {
109        Arc::new(self.output.clone().into())
110    }
111
112    fn input_files(&self) -> Vec<PathBuf> {
113        if self.input.is_some() {
114            tracing::warn!(
115                "The `--input [INPUT]` option is deprecated. Simply remove `--input` from `--input [INPUT]` and give it as an extra argument (`[INPUT_FILES]`)."
116            );
117        }
118
119        self.input_files
120            .clone()
121            .into_iter()
122            .chain(self.input.clone())
123            .collect()
124    }
125}
126
127impl ConfigTrait for Args {
128    /// Returns HTTP Request Method ([`Method::Get`] or [`Method::Post`])
129    fn method(&self) -> Option<Method> {
130        self.method.clone()
131    }
132
133    /// Returns URL prefix of the PlantUML Server (e.g. `http://localhost:8080/`)
134    fn url_prefix(&self) -> Option<String> {
135        self.url_prefix.clone()
136    }
137
138    /// Returns output format ([`Format::Svg`] or [`Format::Png`] or [`Format::Ascii`] (`txt`))
139    fn format(&self) -> Option<Format> {
140        self.format.clone()
141    }
142
143    /// Returns whether to output a `combined` diagram.
144    fn combined(&self) -> Option<bool> {
145        self.combined.then_some(true)
146    }
147
148    fn metadata_version(&self) -> Option<MetadataVersion> {
149        Some(self.metadata_version)
150    }
151}
152
153#[cfg(test)]
154mod tests {
155    use super::*;
156
157    use clap::CommandFactory;
158
159    #[test]
160    fn test_args_debug_assert() {
161        Args::command().debug_assert();
162    }
163}