@@ -4,7 +4,7 @@ use std::fs;
44
55// non-std crates
66use clap:: builder:: FalseyValueParser ;
7- use clap:: { Arg , ArgAction , Command } ;
7+ use clap:: { Arg , ArgAction , ArgMatches , Command } ;
88
99/// Builds and returns the Command Line Interface's argument parsing object.
1010pub fn get_arg_parser ( ) -> Command {
@@ -323,3 +323,93 @@ pub fn parse_ignore(ignore: &[&str]) -> (Vec<String>, Vec<String>) {
323323 }
324324 ( ignored, not_ignored)
325325}
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