@@ -774,31 +774,41 @@ pub mod shell {
774
774
775
775
#[ derive( Clone , PartialEq , Debug ) ]
776
776
pub enum Substitution < ' a > {
777
- Ordinal ( u8 ) ,
778
- Name ( & ' a str ) ,
779
- Escape ,
777
+ Ordinal ( u8 , ( usize , usize ) ) ,
778
+ Name ( & ' a str , ( usize , usize ) ) ,
779
+ Escape ( ( usize , usize ) ) ,
780
780
}
781
781
782
782
impl < ' a > Substitution < ' a > {
783
783
pub fn as_str ( & self ) -> String {
784
- match * self {
785
- Substitution :: Ordinal ( n) => format ! ( "${}" , n) ,
786
- Substitution :: Name ( n) => format ! ( "${}" , n) ,
787
- Substitution :: Escape => "$$" . into ( ) ,
784
+ match self {
785
+ Substitution :: Ordinal ( n, _ ) => format ! ( "${}" , n) ,
786
+ Substitution :: Name ( n, _ ) => format ! ( "${}" , n) ,
787
+ Substitution :: Escape ( _ ) => "$$" . into ( ) ,
788
788
}
789
789
}
790
790
791
791
pub fn position ( & self ) -> Option < ( usize , usize ) > {
792
- match * self {
793
- _ => None ,
792
+ match self {
793
+ Substitution :: Ordinal ( _, pos) |
794
+ Substitution :: Name ( _, pos) |
795
+ Substitution :: Escape ( pos) => Some ( * pos) ,
796
+ }
797
+ }
798
+
799
+ pub fn set_position ( & mut self , start : usize , end : usize ) {
800
+ match self {
801
+ Substitution :: Ordinal ( _, ref mut pos) |
802
+ Substitution :: Name ( _, ref mut pos) |
803
+ Substitution :: Escape ( ref mut pos) => * pos = ( start, end) ,
794
804
}
795
805
}
796
806
797
807
pub fn translate ( & self ) -> Option < String > {
798
808
match * self {
799
- Substitution :: Ordinal ( n) => Some ( format ! ( "{{{}}}" , n) ) ,
800
- Substitution :: Name ( n) => Some ( format ! ( "{{{}}}" , n) ) ,
801
- Substitution :: Escape => None ,
809
+ Substitution :: Ordinal ( n, _ ) => Some ( format ! ( "{{{}}}" , n) ) ,
810
+ Substitution :: Name ( n, _ ) => Some ( format ! ( "{{{}}}" , n) ) ,
811
+ Substitution :: Escape ( _ ) => None ,
802
812
}
803
813
}
804
814
}
@@ -807,20 +817,26 @@ pub mod shell {
807
817
pub fn iter_subs ( s : & str ) -> Substitutions {
808
818
Substitutions {
809
819
s,
820
+ pos : 0 ,
810
821
}
811
822
}
812
823
813
824
/// Iterator over substitutions in a string.
814
825
pub struct Substitutions < ' a > {
815
826
s : & ' a str ,
827
+ pos : usize ,
816
828
}
817
829
818
830
impl < ' a > Iterator for Substitutions < ' a > {
819
831
type Item = Substitution < ' a > ;
820
832
fn next ( & mut self ) -> Option < Self :: Item > {
821
833
match parse_next_substitution ( self . s ) {
822
- Some ( ( sub, tail) ) => {
834
+ Some ( ( mut sub, tail) ) => {
823
835
self . s = tail;
836
+ if let Some ( ( start, end) ) = sub. position ( ) {
837
+ sub. set_position ( start + self . pos , end + self . pos ) ;
838
+ self . pos += end;
839
+ }
824
840
Some ( sub)
825
841
} ,
826
842
None => None ,
@@ -837,15 +853,15 @@ pub mod shell {
837
853
let at = {
838
854
let start = s. find ( '$' ) ?;
839
855
match s[ start+1 ..] . chars ( ) . next ( ) ? {
840
- '$' => return Some ( ( Substitution :: Escape , & s[ start+2 ..] ) ) ,
856
+ '$' => return Some ( ( Substitution :: Escape ( ( start , start+ 2 ) ) , & s[ start+2 ..] ) ) ,
841
857
c @ '0' ..= '9' => {
842
858
let n = ( c as u8 ) - b'0' ;
843
- return Some ( ( Substitution :: Ordinal ( n) , & s[ start+2 ..] ) ) ;
859
+ return Some ( ( Substitution :: Ordinal ( n, ( start , start+ 2 ) ) , & s[ start+2 ..] ) ) ;
844
860
} ,
845
861
_ => { /* fall-through */ } ,
846
862
}
847
863
848
- Cur :: new_at_start ( & s[ start ..] )
864
+ Cur :: new_at ( & s[ ..] , start )
849
865
} ;
850
866
851
867
let at = at. at_next_cp ( ) ?;
@@ -855,7 +871,10 @@ pub mod shell {
855
871
None
856
872
} else {
857
873
let end = at_next_cp_while ( inner, is_ident_tail) ;
858
- Some ( ( Substitution :: Name ( at. slice_between ( end) . unwrap ( ) ) , end. slice_after ( ) ) )
874
+ let slice = at. slice_between ( end) . unwrap ( ) ;
875
+ let start = at. at - 1 ;
876
+ let end_pos = at. at + slice. len ( ) ;
877
+ Some ( ( Substitution :: Name ( slice, ( start, end_pos) ) , end. slice_after ( ) ) )
859
878
}
860
879
}
861
880
@@ -907,24 +926,24 @@ pub mod shell {
907
926
fn test_escape ( ) {
908
927
assert_eq ! ( pns( "has no escapes" ) , None ) ;
909
928
assert_eq ! ( pns( "has no escapes, either $" ) , None ) ;
910
- assert_eq ! ( pns( "*so* has a $$ escape" ) , Some ( ( S :: Escape , " escape" ) ) ) ;
911
- assert_eq ! ( pns( "$$ leading escape" ) , Some ( ( S :: Escape , " leading escape" ) ) ) ;
912
- assert_eq ! ( pns( "trailing escape $$" ) , Some ( ( S :: Escape , "" ) ) ) ;
929
+ assert_eq ! ( pns( "*so* has a $$ escape" ) , Some ( ( S :: Escape ( ( 11 , 13 ) ) , " escape" ) ) ) ;
930
+ assert_eq ! ( pns( "$$ leading escape" ) , Some ( ( S :: Escape ( ( 0 , 2 ) ) , " leading escape" ) ) ) ;
931
+ assert_eq ! ( pns( "trailing escape $$" ) , Some ( ( S :: Escape ( ( 16 , 18 ) ) , "" ) ) ) ;
913
932
}
914
933
915
934
#[ test]
916
935
fn test_parse ( ) {
917
936
macro_rules! assert_pns_eq_sub {
918
- ( $in_: expr, $kind: ident( $arg: expr) ) => {
919
- assert_eq!( pns( concat!( $in_, "!" ) ) , Some ( ( S :: $kind( $arg. into( ) ) , "!" ) ) )
937
+ ( $in_: expr, $kind: ident( $arg: expr, $pos : expr ) ) => {
938
+ assert_eq!( pns( concat!( $in_, "!" ) ) , Some ( ( S :: $kind( $arg. into( ) , $pos ) , "!" ) ) )
920
939
} ;
921
940
}
922
941
923
- assert_pns_eq_sub ! ( "$0" , Ordinal ( 0 ) ) ;
924
- assert_pns_eq_sub ! ( "$1" , Ordinal ( 1 ) ) ;
925
- assert_pns_eq_sub ! ( "$9" , Ordinal ( 9 ) ) ;
926
- assert_pns_eq_sub ! ( "$N" , Name ( "N" ) ) ;
927
- assert_pns_eq_sub ! ( "$NAME" , Name ( "NAME" ) ) ;
942
+ assert_pns_eq_sub ! ( "$0" , Ordinal ( 0 , ( 0 , 2 ) ) ) ;
943
+ assert_pns_eq_sub ! ( "$1" , Ordinal ( 1 , ( 0 , 2 ) ) ) ;
944
+ assert_pns_eq_sub ! ( "$9" , Ordinal ( 9 , ( 0 , 2 ) ) ) ;
945
+ assert_pns_eq_sub ! ( "$N" , Name ( "N" , ( 0 , 2 ) ) ) ;
946
+ assert_pns_eq_sub ! ( "$NAME" , Name ( "NAME" , ( 0 , 5 ) ) ) ;
928
947
}
929
948
930
949
#[ test]
@@ -961,13 +980,6 @@ mod strcursor {
961
980
}
962
981
963
982
impl < ' a > StrCursor < ' a > {
964
- pub fn new_at_start ( s : & ' a str ) -> StrCursor < ' a > {
965
- StrCursor {
966
- s,
967
- at : 0 ,
968
- }
969
- }
970
-
971
983
pub fn new_at ( s : & ' a str , at : usize ) -> StrCursor < ' a > {
972
984
StrCursor {
973
985
s,
0 commit comments