Skip to content

Commit 1c5515e

Browse files
committed
cli: add merge strategies
1 parent bc51841 commit 1c5515e

File tree

1 file changed

+57
-8
lines changed

1 file changed

+57
-8
lines changed

src/cli.rs

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use onefetch_image::ImageProtocol;
1111
use onefetch_manifest::ManifestType;
1212
use regex::Regex;
1313
use serde::Serialize;
14+
use merge::Merge;
1415
use std::env;
1516
use std::io;
1617
use std::path::PathBuf;
@@ -20,12 +21,18 @@ use strum::IntoEnumIterator;
2021
const COLOR_RESOLUTIONS: [&str; 5] = ["16", "32", "64", "128", "256"];
2122
pub const NO_BOTS_DEFAULT_REGEX_PATTERN: &str = r"(?:-|\s)[Bb]ot$|\[[Bb]ot\]";
2223

23-
#[derive(Clone, Debug, Parser, PartialEq, Eq)]
24+
#[derive(Clone, Debug, Parser, PartialEq, Eq, Merge)]
2425
#[command(version, about)]
2526
pub struct CliOptions {
2627
/// Run as if onefetch was started in <input> instead of the current working directory
2728
#[arg(default_value = ".", hide_default_value = true, value_hint = ValueHint::DirPath)]
29+
#[merge(skip)]
2830
pub input: PathBuf,
31+
/// Specify a custom path to a config file.
32+
/// Default config is located at ${HOME}/.config/onefetch/config.conf.
33+
#[arg(long, value_hint = ValueHint::AnyPath)]
34+
#[merge(skip)]
35+
pub config_path: Option<PathBuf>,
2936
#[command(flatten)]
3037
pub info: InfoCliOptions,
3138
#[command(flatten)]
@@ -42,7 +49,7 @@ pub struct CliOptions {
4249
pub other: OtherCliOptions,
4350
}
4451

45-
#[derive(Clone, Debug, Args, PartialEq, Eq)]
52+
#[derive(Clone, Debug, Args, PartialEq, Eq, Merge)]
4653
#[command(next_help_heading = "INFO")]
4754
pub struct InfoCliOptions {
4855
/// Allows you to disable FIELD(s) from appearing in the output
@@ -54,27 +61,34 @@ pub struct InfoCliOptions {
5461
value_enum,
5562
value_name = "FIELD"
5663
)]
64+
#[merge(strategy = overwrite_vec)]
5765
pub disabled_fields: Vec<InfoType>,
5866
/// Hides the title
5967
#[arg(long)]
68+
#[merge(strategy = merge::bool::overwrite_false)]
6069
pub no_title: bool,
6170
/// Maximum NUM of authors to be shown
6271
#[arg(long, default_value_t = 3usize, value_name = "NUM")]
72+
#[merge(strategy = overwrite)]
6373
pub number_of_authors: usize,
6474
/// Maximum NUM of languages to be shown
6575
#[arg(long, default_value_t = 6usize, value_name = "NUM")]
76+
#[merge(strategy = overwrite)]
6677
pub number_of_languages: usize,
6778
/// Maximum NUM of file churns to be shown
6879
#[arg(long, default_value_t = 3usize, value_name = "NUM")]
80+
#[merge(strategy = overwrite)]
6981
pub number_of_file_churns: usize,
7082
/// Minimum NUM of commits from HEAD used to compute the churn summary
7183
///
7284
/// By default, the actual value is non-deterministic due to time-based computation
7385
/// and will be displayed under the info title "Churn (NUM)"
7486
#[arg(long, value_name = "NUM")]
87+
#[merge(strategy = overwrite)]
7588
pub churn_pool_size: Option<usize>,
7689
/// Ignore all files & directories matching EXCLUDE
7790
#[arg(long, short, num_args = 1..)]
91+
#[merge(strategy = overwrite_vec)]
7892
pub exclude: Vec<String>,
7993
/// Exclude [bot] commits. Use <REGEX> to override the default pattern
8094
#[arg(
@@ -84,21 +98,27 @@ pub struct InfoCliOptions {
8498
default_missing_value = NO_BOTS_DEFAULT_REGEX_PATTERN,
8599
value_name = "REGEX"
86100
)]
101+
#[merge(strategy = overwrite)]
87102
pub no_bots: Option<MyRegex>,
88103
/// Ignores merge commits
89104
#[arg(long)]
105+
#[merge(strategy = merge::bool::overwrite_false)]
90106
pub no_merges: bool,
91107
/// Show the email address of each author
92108
#[arg(long, short = 'E')]
109+
#[merge(strategy = merge::bool::overwrite_false)]
93110
pub email: bool,
94111
/// Display repository URL as HTTP
95112
#[arg(long)]
113+
#[merge(strategy = merge::bool::overwrite_false)]
96114
pub http_url: bool,
97115
/// Hide token in repository URL
98116
#[arg(long)]
117+
#[merge(strategy = merge::bool::overwrite_false)]
99118
pub hide_token: bool,
100119
/// Count hidden files and directories
101120
#[arg(long)]
121+
#[merge(strategy = merge::bool::overwrite_false)]
102122
pub include_hidden: bool,
103123
/// Filters output by language type
104124
#[arg(
@@ -108,10 +128,11 @@ pub struct InfoCliOptions {
108128
short = 'T',
109129
value_enum,
110130
)]
131+
#[merge(strategy = overwrite_vec)]
111132
pub r#type: Vec<LanguageType>,
112133
}
113134

114-
#[derive(Clone, Debug, Args, PartialEq, Eq)]
135+
#[derive(Clone, Debug, Args, PartialEq, Eq, Merge)]
115136
#[command(next_help_heading = "ASCII")]
116137
pub struct AsciiCliOptions {
117138
/// Takes a non-empty STRING as input to replace the ASCII logo
@@ -122,6 +143,7 @@ pub struct AsciiCliOptions {
122143
///
123144
/// '--ascii-input "$(fortune | cowsay -W 25)"'
124145
#[arg(long, value_name = "STRING", value_hint = ValueHint::CommandString)]
146+
#[merge(strategy = overwrite)]
125147
pub ascii_input: Option<String>,
126148
/// Colors (X X X...) to print the ascii art
127149
#[arg(
@@ -131,6 +153,7 @@ pub struct AsciiCliOptions {
131153
short = 'c',
132154
value_parser = value_parser!(u8).range(..16),
133155
)]
156+
#[merge(strategy = overwrite_vec)]
134157
pub ascii_colors: Vec<u8>,
135158
/// Which LANGUAGE's ascii art to print
136159
#[arg(
@@ -140,22 +163,26 @@ pub struct AsciiCliOptions {
140163
value_enum,
141164
hide_possible_values = true
142165
)]
166+
#[merge(skip)]
143167
pub ascii_language: Option<Language>,
144168
/// Specify when to use true color
145169
///
146170
/// If set to auto: true color will be enabled if supported by the terminal
147171
#[arg(long, default_value = "auto", value_name = "WHEN", value_enum)]
172+
#[merge(strategy = overwrite)]
148173
pub true_color: When,
149174
}
150175

151-
#[derive(Clone, Debug, Args, PartialEq, Eq)]
176+
#[derive(Clone, Debug, Args, PartialEq, Eq, Merge)]
152177
#[command(next_help_heading = "IMAGE")]
153178
pub struct ImageCliOptions {
154179
/// Path to the IMAGE file
155180
#[arg(long, short, value_hint = ValueHint::FilePath)]
181+
#[merge(strategy = overwrite)]
156182
pub image: Option<PathBuf>,
157183
/// Which image PROTOCOL to use
158184
#[arg(long, value_enum, requires = "image", value_name = "PROTOCOL")]
185+
#[merge(skip)]
159186
pub image_protocol: Option<ImageProtocol>,
160187
/// VALUE of color resolution to use with SIXEL backend
161188
#[arg(
@@ -166,10 +193,11 @@ pub struct ImageCliOptions {
166193
value_parser = PossibleValuesParser::new(COLOR_RESOLUTIONS)
167194
.map(|s| s.parse::<usize>().unwrap())
168195
)]
196+
#[merge(strategy = overwrite)]
169197
pub color_resolution: usize,
170198
}
171199

172-
#[derive(Clone, Debug, Args, PartialEq, Eq)]
200+
#[derive(Clone, Debug, Args, PartialEq, Eq, Merge)]
173201
#[command(next_help_heading = "TEXT FORMATTING")]
174202
pub struct TextForamttingCliOptions {
175203
/// Changes the text colors (X X X...)
@@ -186,59 +214,71 @@ pub struct TextForamttingCliOptions {
186214
value_parser = value_parser!(u8).range(..16),
187215
num_args = 1..=6
188216
)]
217+
#[merge(strategy = overwrite_vec)]
189218
pub text_colors: Vec<u8>,
190219
/// Use ISO 8601 formatted timestamps
191220
#[arg(long, short = 'z')]
221+
#[merge(strategy = merge::bool::overwrite_false)]
192222
pub iso_time: bool,
193223
/// Which thousands SEPARATOR to use
194224
#[arg(long, value_name = "SEPARATOR", default_value = "plain", value_enum)]
225+
#[merge(strategy = overwrite)]
195226
pub number_separator: NumberSeparator,
196227
/// Turns off bold formatting
197228
#[arg(long)]
229+
#[merge(strategy = merge::bool::overwrite_false)]
198230
pub no_bold: bool,
199231
}
200-
#[derive(Clone, Debug, Args, PartialEq, Eq, Default)]
232+
#[derive(Clone, Debug, Args, PartialEq, Eq, Default, Merge)]
201233
#[command(next_help_heading = "VISUALS")]
202234
pub struct VisualsCliOptions {
203235
/// Hides the color palette
204236
#[arg(long)]
237+
#[merge(strategy = merge::bool::overwrite_false)]
205238
pub no_color_palette: bool,
206239
/// Hides the ascii art or image if provided
207240
#[arg(long)]
241+
#[merge(strategy = merge::bool::overwrite_false)]
208242
pub no_art: bool,
209243
/// Use Nerd Font icons
210244
///
211245
/// Replaces language chips with Nerd Font icons
212246
#[arg(long)]
247+
#[merge(strategy = merge::bool::overwrite_false)]
213248
pub nerd_fonts: bool,
214249
}
215250

216-
#[derive(Clone, Debug, Args, PartialEq, Eq, Default)]
251+
#[derive(Clone, Debug, Args, PartialEq, Eq, Default, Merge)]
217252
#[command(next_help_heading = "DEVELOPER")]
218253
pub struct DeveloperCliOptions {
219254
/// Outputs Onefetch in a specific format
220255
#[arg(long, short, value_name = "FORMAT", value_enum)]
256+
#[merge(skip)]
221257
pub output: Option<SerializationFormat>,
222258
/// If provided, outputs the completion file for given SHELL
223259
#[arg(long = "generate", value_name = "SHELL", value_enum)]
260+
#[merge(skip)]
224261
pub completion: Option<Shell>,
225262
}
226263

227-
#[derive(Clone, Debug, Args, PartialEq, Eq, Default)]
264+
#[derive(Clone, Debug, Args, PartialEq, Eq, Default, Merge)]
228265
#[command(next_help_heading = "OTHER")]
229266
pub struct OtherCliOptions {
230267
/// Prints out supported languages
231268
#[arg(long, short)]
269+
#[merge(skip)]
232270
pub languages: bool,
233271
/// Prints out supported package managers
234272
#[arg(long, short)]
273+
#[merge(skip)]
235274
pub package_managers: bool,
236275
}
237276

238277
impl Default for CliOptions {
239278
fn default() -> CliOptions {
240279
CliOptions {
241280
input: PathBuf::from("."),
281+
config_path: None,
242282
info: InfoCliOptions::default(),
243283
text_formatting: TextForamttingCliOptions::default(),
244284
visuals: VisualsCliOptions::default(),
@@ -302,6 +342,15 @@ impl Default for ImageCliOptions {
302342
}
303343
}
304344

345+
pub fn overwrite<T>(l: &mut T, r: T) {
346+
*l = r;
347+
}
348+
349+
pub fn overwrite_vec<T>(l: &mut Vec<T>, mut r: Vec<T>) {
350+
l.clear();
351+
l.append(&mut r);
352+
}
353+
305354
pub fn print_supported_languages() -> Result<()> {
306355
for l in Language::iter() {
307356
println!("{l}");

0 commit comments

Comments
 (0)