@@ -11,6 +11,7 @@ use onefetch_image::ImageProtocol;
1111use onefetch_manifest:: ManifestType ;
1212use regex:: Regex ;
1313use serde:: Serialize ;
14+ use merge:: Merge ;
1415use std:: env;
1516use std:: io;
1617use std:: path:: PathBuf ;
@@ -20,12 +21,18 @@ use strum::IntoEnumIterator;
2021const COLOR_RESOLUTIONS : [ & str ; 5 ] = [ "16" , "32" , "64" , "128" , "256" ] ;
2122pub 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) ]
2526pub 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" ) ]
4754pub 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" ) ]
116137pub 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" ) ]
153178pub 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" ) ]
174202pub 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" ) ]
202234pub 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" ) ]
218253pub 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" ) ]
229266pub 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
238277impl 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+
305354pub fn print_supported_languages ( ) -> Result < ( ) > {
306355 for l in Language :: iter ( ) {
307356 println ! ( "{l}" ) ;
0 commit comments