1use std::path::PathBuf;
4
5use clap::{Parser, ValueEnum};
6use log::LevelFilter;
7
8use crate::clap::parsers::path_parser;
9
10#[derive(Debug, Default, Parser)]
12pub struct AccountFlag {
13 #[arg(long = "account", short = 'a', global = true)]
18 #[arg(name = "account_name", value_name = "NAME")]
19 pub name: Option<String>,
20}
21
22#[derive(Debug, Default, Parser)]
24pub struct ConfigFlags {
25 #[arg(long = "config", short = 'c', global = true)]
32 #[arg(name = "config_paths", value_name = "PATH", value_parser = path_parser)]
33 pub paths: Vec<PathBuf>,
34}
35
36#[derive(Debug, Default, Parser)]
38pub struct AccountArg {
39 #[arg(name = "account_name", value_name = "NAME")]
44 pub name: String,
45}
46
47#[derive(Debug, Default, Parser)]
49pub struct JsonFlag {
50 #[arg(long = "json", name = "json", global = true)]
55 pub enabled: bool,
56}
57
58#[derive(Debug, Default, Parser)]
60pub struct PageTokenArg {
61 #[arg(long = "page-token", name = "page_token", value_name = "TOKEN")]
66 pub token: Option<String>,
67}
68
69#[derive(Debug, Default, Parser)]
71pub struct LogFlags {
72 #[arg(name = "log-level", long = "log-level", visible_alias = "log")]
79 #[arg(value_enum, value_name = "LEVEL", global = true)]
80 pub level: Option<LogLevel>,
81
82 #[arg(long = "log-file", global = true, name = "log-file")]
88 #[arg(value_name = "PATH", value_parser = path_parser)]
89 pub file: Option<PathBuf>,
90}
91
92#[derive(Debug, Default, Clone, Copy, ValueEnum)]
94pub enum LogLevel {
95 #[default]
97 Off,
98 Error,
100 Warn,
102 Info,
104 Debug,
106 Trace,
108}
109
110impl From<LogLevel> for LevelFilter {
111 fn from(level: LogLevel) -> Self {
112 match level {
113 LogLevel::Off => Self::Off,
114 LogLevel::Error => Self::Error,
115 LogLevel::Warn => Self::Warn,
116 LogLevel::Info => Self::Info,
117 LogLevel::Debug => Self::Debug,
118 LogLevel::Trace => Self::Trace,
119 }
120 }
121}
122
123#[macro_export]
126macro_rules! long_version {
127 () => {
128 concat!(
129 "v",
130 env!("CARGO_PKG_VERSION"),
131 " ",
132 env!("CARGO_FEATURES"),
133 "\nbuild: ",
134 env!("CARGO_CFG_TARGET_OS"),
135 " ",
136 env!("CARGO_CFG_TARGET_ENV"),
137 " ",
138 env!("CARGO_CFG_TARGET_ARCH"),
139 "\ngit: ",
140 env!("GIT_DESCRIBE"),
141 ", rev ",
142 env!("GIT_REV"),
143 )
144 };
145}
146
147#[macro_export]
149macro_rules! footer {
150 () => {
151 concat!(
152 "Report bugs to:\n",
153 " ", env!("CARGO_PKG_REPOSITORY"), "/issues/\n",
154 "\n",
155 "Sponsoring:\n",
156 " https://pimalaya.org/sponsor/\n",
157 "\n",
158 "This program is part of Pimalaya, free software funded entirely by grants and donations.\n",
159 "If you find it useful, consider supporting its development.\n",
160 )
161 };
162}
163
164#[cfg(test)]
165mod tests {
166 use std::path::PathBuf;
167
168 use clap::Parser;
169
170 use crate::clap::args::ConfigFlags;
171
172 #[test]
173 fn a_config_path_is_never_split() {
174 let args = ["app", "-c", r"C:\a.toml", "-c", "b:c;d.toml"];
175 let flags = ConfigFlags::try_parse_from(args).unwrap();
176 let paths = [PathBuf::from(r"C:\a.toml"), PathBuf::from("b:c;d.toml")];
177 assert_eq!(flags.paths, paths);
178 }
179}