@@ -637,6 +637,50 @@ pub trait TypedValueParser: Clone + Send + Sync + 'static {
637
637
) -> Option < Box < dyn Iterator < Item = crate :: PossibleValue < ' static > > + ' _ > > {
638
638
None
639
639
}
640
+
641
+ /// Adapt a `TypedValueParser` from one value to another
642
+ ///
643
+ /// # Example
644
+ ///
645
+ /// ```rust
646
+ /// # use clap::Command;
647
+ /// # use clap::Arg;
648
+ /// # use clap::builder::TypedValueParser as _;
649
+ /// # use clap::builder::BoolishValueParser;
650
+ /// let cmd = Command::new("mycmd")
651
+ /// .arg(
652
+ /// Arg::new("flag")
653
+ /// .long("flag")
654
+ /// .action(clap::ArgAction::Set)
655
+ /// .value_parser(
656
+ /// BoolishValueParser::new()
657
+ /// .map(|b| -> usize {
658
+ /// if b { 10 } else { 5 }
659
+ /// })
660
+ /// )
661
+ /// );
662
+ ///
663
+ /// let matches = cmd.clone().try_get_matches_from(["mycmd", "--flag=true", "--flag=true"]).unwrap();
664
+ /// assert!(matches.contains_id("flag"));
665
+ /// assert_eq!(
666
+ /// matches.get_one::<usize>("flag").copied(),
667
+ /// Some(10)
668
+ /// );
669
+ ///
670
+ /// let matches = cmd.try_get_matches_from(["mycmd", "--flag=false"]).unwrap();
671
+ /// assert!(matches.contains_id("flag"));
672
+ /// assert_eq!(
673
+ /// matches.get_one::<usize>("flag").copied(),
674
+ /// Some(5)
675
+ /// );
676
+ /// ```
677
+ fn map < T , F > ( self , func : F ) -> MapValueParser < Self , F >
678
+ where
679
+ T : Send + Sync + Clone ,
680
+ F : Fn ( Self :: Value ) -> T + Clone ,
681
+ {
682
+ MapValueParser :: new ( self , func)
683
+ }
640
684
}
641
685
642
686
impl < F , T , E > TypedValueParser for F
@@ -1777,6 +1821,59 @@ impl Default for NonEmptyStringValueParser {
1777
1821
}
1778
1822
}
1779
1823
1824
+ /// Adapt a `TypedValueParser` from one value to another
1825
+ ///
1826
+ /// See [`TypedValueParser::map`]
1827
+ #[ derive( Clone , Debug ) ]
1828
+ pub struct MapValueParser < P , F > {
1829
+ parser : P ,
1830
+ func : F ,
1831
+ }
1832
+
1833
+ impl < P , F > MapValueParser < P , F > {
1834
+ fn new ( parser : P , func : F ) -> Self {
1835
+ Self { parser, func }
1836
+ }
1837
+ }
1838
+
1839
+ impl < P , F , T > TypedValueParser for MapValueParser < P , F >
1840
+ where
1841
+ P : TypedValueParser ,
1842
+ P :: Value : Send + Sync + Clone ,
1843
+ F : Fn ( P :: Value ) -> T + Clone + Send + Sync + ' static ,
1844
+ T : Send + Sync + Clone ,
1845
+ {
1846
+ type Value = T ;
1847
+
1848
+ fn parse_ref (
1849
+ & self ,
1850
+ cmd : & crate :: Command ,
1851
+ arg : Option < & crate :: Arg > ,
1852
+ value : & std:: ffi:: OsStr ,
1853
+ ) -> Result < Self :: Value , crate :: Error > {
1854
+ let value = self . parser . parse_ref ( cmd, arg, value) ?;
1855
+ let value = ( self . func ) ( value) ;
1856
+ Ok ( value)
1857
+ }
1858
+
1859
+ fn parse (
1860
+ & self ,
1861
+ cmd : & crate :: Command ,
1862
+ arg : Option < & crate :: Arg > ,
1863
+ value : std:: ffi:: OsString ,
1864
+ ) -> Result < Self :: Value , crate :: Error > {
1865
+ let value = self . parser . parse ( cmd, arg, value) ?;
1866
+ let value = ( self . func ) ( value) ;
1867
+ Ok ( value)
1868
+ }
1869
+
1870
+ fn possible_values (
1871
+ & self ,
1872
+ ) -> Option < Box < dyn Iterator < Item = crate :: builder:: PossibleValue < ' static > > + ' _ > > {
1873
+ self . parser . possible_values ( )
1874
+ }
1875
+ }
1876
+
1780
1877
/// Register a type with [value_parser!][crate::value_parser!]
1781
1878
///
1782
1879
/// # Example
0 commit comments