@@ -4,7 +4,7 @@ use std::fs;
4
4
5
5
// non-std crates
6
6
use clap:: builder:: FalseyValueParser ;
7
- use clap:: { Arg , ArgAction , Command } ;
7
+ use clap:: { Arg , ArgAction , ArgMatches , Command } ;
8
8
9
9
/// Builds and returns the Command Line Interface's argument parsing object.
10
10
pub fn get_arg_parser ( ) -> Command {
@@ -323,3 +323,93 @@ pub fn parse_ignore(ignore: &[&str]) -> (Vec<String>, Vec<String>) {
323
323
}
324
324
( ignored, not_ignored)
325
325
}
326
+
327
+ /// Converts the parsed value of the `--extra-arg` option into an optional vector of strings.
328
+ ///
329
+ /// This is for adapting to 2 scenarios where `--extra-arg` is either
330
+ ///
331
+ /// - specified multiple times
332
+ /// - each val is appended to a [`Vec`] (by clap crate)
333
+ /// - specified once with multiple space-separated values
334
+ /// - resulting [`Vec`] is made from splitting at the spaces between
335
+ /// - not specified at all (returns [`None`])
336
+ ///
337
+ /// It is preferred that the values specified in either situation do not contain spaces and are
338
+ /// quoted:
339
+ /// ```shell
340
+ /// --extra-arg="-std=c++17" --extra-arg="-Wall"
341
+ /// # or equivalently
342
+ /// --extra-arg="-std=c++17 -Wall"
343
+ /// ```
344
+ /// The cpp-linter-action (for Github CI workflows) can only use 1 `extra-arg` input option, so
345
+ /// the value will be split at spaces.
346
+ pub fn convert_extra_arg_val ( args : & ArgMatches ) -> Option < Vec < & str > > {
347
+ let raw_val = if let Ok ( extra_args) = args. try_get_many :: < String > ( "extra-arg" ) {
348
+ extra_args. map ( |extras| extras. map ( |val| val. as_str ( ) ) . collect :: < Vec < _ > > ( ) )
349
+ } else {
350
+ None
351
+ } ;
352
+ if let Some ( val) = raw_val {
353
+ if val. len ( ) == 1 {
354
+ // specified once; split and return result
355
+ Some (
356
+ val[ 0 ]
357
+ . trim_matches ( '\'' )
358
+ . trim_matches ( '"' )
359
+ . split ( ' ' )
360
+ . collect ( ) ,
361
+ )
362
+ } else {
363
+ // specified multiple times; just return
364
+ Some ( val)
365
+ }
366
+ } else {
367
+ // no value specified; just return
368
+ None
369
+ }
370
+ }
371
+
372
+ #[ cfg( test) ]
373
+ mod test {
374
+ use clap:: ArgMatches ;
375
+
376
+ use super :: { convert_extra_arg_val, get_arg_parser} ;
377
+
378
+ fn parser_args ( input : Vec < & str > ) -> ArgMatches {
379
+ let arg_parser = get_arg_parser ( ) ;
380
+ arg_parser. get_matches_from ( input)
381
+ }
382
+
383
+ #[ test]
384
+ fn extra_arg_0 ( ) {
385
+ let args = parser_args ( vec ! [ "cpp-linter" ] ) ;
386
+ let extras = convert_extra_arg_val ( & args) ;
387
+ assert ! ( extras. is_none( ) ) ;
388
+ }
389
+
390
+ #[ test]
391
+ fn extra_arg_1 ( ) {
392
+ let args = parser_args ( vec ! [ "cpp-linter" , "--extra-arg='-std=c++17 -Wall'" ] ) ;
393
+ let extras = convert_extra_arg_val ( & args) ;
394
+ assert ! ( extras. is_some( ) ) ;
395
+ if let Some ( extra_args) = extras {
396
+ assert_eq ! ( extra_args. len( ) , 2 ) ;
397
+ assert_eq ! ( extra_args, [ "-std=c++17" , "-Wall" ] )
398
+ }
399
+ }
400
+
401
+ #[ test]
402
+ fn extra_arg_2 ( ) {
403
+ let args = parser_args ( vec ! [
404
+ "cpp-linter" ,
405
+ "--extra-arg=-std=c++17" ,
406
+ "--extra-arg=-Wall" ,
407
+ ] ) ;
408
+ let extras = convert_extra_arg_val ( & args) ;
409
+ assert ! ( extras. is_some( ) ) ;
410
+ if let Some ( extra_args) = extras {
411
+ assert_eq ! ( extra_args. len( ) , 2 ) ;
412
+ assert_eq ! ( extra_args, [ "-std=c++17" , "-Wall" ] )
413
+ }
414
+ }
415
+ }
0 commit comments