@@ -709,21 +709,28 @@ pub(crate) fn build_positional<T>(metavar: &'static str) -> ParsePositional<T> {
709
709
ParsePositional {
710
710
metavar,
711
711
help : None ,
712
- result_type : PhantomData ,
713
- strict : false ,
712
+ position : Position :: Unrestricted ,
713
+ ty : PhantomData ,
714
714
}
715
715
}
716
716
717
- /// Parse a positional item, created with [`positional`]
717
+ /// Parse a positional item, created with [`positional`](crate::positional)
718
718
///
719
- /// You can add extra information to positional parsers with [`help`](Self::help)
720
- /// and [`strict`](Self::strict) on this struct.
719
+ /// You can add extra information to positional parsers with [`help`](Self::help),
720
+ /// [`strict`](Self::strict), or [`non_strict`](Self::non_strict ) on this struct.
721
721
#[ derive( Clone ) ]
722
722
pub struct ParsePositional < T > {
723
723
metavar : & ' static str ,
724
724
help : Option < Doc > ,
725
- result_type : PhantomData < T > ,
726
- strict : bool ,
725
+ position : Position ,
726
+ ty : PhantomData < T > ,
727
+ }
728
+
729
+ #[ derive( Clone , PartialEq , Eq ) ]
730
+ enum Position {
731
+ Unrestricted ,
732
+ Strict ,
733
+ NonStrict ,
727
734
}
728
735
729
736
impl < T > ParsePositional < T > {
@@ -769,39 +776,59 @@ impl<T> ParsePositional<T> {
769
776
/// `bpaf` would display such positional elements differently in usage line as well.
770
777
#[ cfg_attr( not( doctest) , doc = include_str!( "docs2/positional_strict.md" ) ) ]
771
778
#[ must_use]
772
- pub fn strict ( mut self ) -> Self {
773
- self . strict = true ;
779
+ #[ inline( always) ]
780
+ pub fn strict ( mut self ) -> ParsePositional < T > {
781
+ self . position = Position :: Strict ;
782
+ self
783
+ }
784
+
785
+ /// Changes positional parser to be a "not strict" positional
786
+ ///
787
+ /// Ensures the parser always rejects "strict" positions to the right of the separator, `--`.
788
+ /// Essentially the inverse operation to [`ParsePositional::strict`], which can be used to ensure
789
+ /// adjacent strict and nonstrict args never conflict with eachother.
790
+ #[ must_use]
791
+ #[ inline( always) ]
792
+ pub fn non_strict ( mut self ) -> Self {
793
+ self . position = Position :: NonStrict ;
774
794
self
775
795
}
776
796
797
+ #[ inline( always) ]
777
798
fn meta ( & self ) -> Meta {
778
799
let meta = Meta :: from ( Item :: Positional {
779
800
metavar : Metavar ( self . metavar ) ,
780
801
help : self . help . clone ( ) ,
781
802
} ) ;
782
- if self . strict {
783
- Meta :: Strict ( Box :: new ( meta) )
784
- } else {
785
- meta
803
+ match self . position {
804
+ Position :: Strict => Meta :: Strict ( Box :: new ( meta) ) ,
805
+ _ => meta,
786
806
}
787
807
}
788
808
}
789
809
790
810
fn parse_pos_word (
791
811
args : & mut State ,
792
- strict : bool ,
793
- metavar : & ' static str ,
812
+ metavar : Metavar ,
794
813
help : & Option < Doc > ,
814
+ position : & Position ,
795
815
) -> Result < OsString , Error > {
796
- let metavar = Metavar ( metavar) ;
797
816
match args. take_positional_word ( metavar) {
798
817
Ok ( ( ix, is_strict, word) ) => {
799
- if strict && !is_strict {
800
- #[ cfg( feature = "autocomplete" ) ]
801
- args. push_pos_sep ( ) ;
802
-
803
- return Err ( Error ( Message :: StrictPos ( ix, metavar) ) ) ;
818
+ match position {
819
+ & Position :: Strict if !is_strict => {
820
+ #[ cfg( feature = "autocomplete" ) ]
821
+ args. push_pos_sep ( ) ;
822
+ return Err ( Error ( Message :: StrictPos ( ix, metavar) ) ) ;
823
+ }
824
+ & Position :: NonStrict if is_strict => {
825
+ #[ cfg( feature = "autocomplete" ) ]
826
+ args. push_pos_sep ( ) ;
827
+ return Err ( Error ( Message :: NonStrictPos ( ix, metavar) ) ) ;
828
+ }
829
+ _ => { }
804
830
}
831
+
805
832
#[ cfg( feature = "autocomplete" ) ]
806
833
if args. touching_last_remove ( ) && !args. check_no_pos_ahead ( ) {
807
834
args. push_metavar ( metavar. 0 , help, false ) ;
@@ -826,13 +853,14 @@ where
826
853
<T as std:: str:: FromStr >:: Err : std:: fmt:: Display ,
827
854
{
828
855
fn eval ( & self , args : & mut State ) -> Result < T , Error > {
829
- let os = parse_pos_word ( args, self . strict , self . metavar , & self . help ) ?;
856
+ let os = parse_pos_word ( args, Metavar ( self . metavar ) , & self . help , & self . position ) ?;
830
857
match parse_os_str :: < T > ( os) {
831
858
Ok ( ok) => Ok ( ok) ,
832
859
Err ( err) => Err ( Error ( Message :: ParseFailed ( args. current , err) ) ) ,
833
860
}
834
861
}
835
862
863
+ #[ inline( always) ]
836
864
fn meta ( & self ) -> Meta {
837
865
self . meta ( )
838
866
}
0 commit comments