@@ -49,13 +49,10 @@ pub fn parse_params<I: IntoIterator<Item = OsString>>(opts: I) -> Result<Params,
4949 let mut from = None ;
5050 let mut to = None ;
5151 let mut format = None ;
52- let mut context_count = None ;
52+ let mut context = None ;
5353 let tabsize_re = Regex :: new ( r"^--tabsize=(?<num>\d+)$" ) . unwrap ( ) ;
54- let context_re =
55- Regex :: new ( r"^(-[cC](?<num1>\d*)|--context(=(?<num2>\d*))?|-(?<num3>\d+)c)$" ) . unwrap ( ) ;
56- let unified_re =
57- Regex :: new ( r"^(-[uU](?<num1>\d*)|--unified(=(?<num2>\d*))?|-(?<num3>\d+)u)$" ) . unwrap ( ) ;
5854 while let Some ( param) = opts. next ( ) {
55+ let next_param = opts. peek ( ) ;
5956 if param == "--" {
6057 break ;
6158 }
@@ -111,73 +108,43 @@ pub fn parse_params<I: IntoIterator<Item = OsString>>(opts: I) -> Result<Params,
111108 } ;
112109 continue ;
113110 }
114- if context_re. is_match ( param. to_string_lossy ( ) . as_ref ( ) ) {
115- if format. is_some ( ) && format != Some ( Format :: Context ) {
116- return Err ( "Conflicting output style options" . to_string ( ) ) ;
117- }
118- format = Some ( Format :: Context ) ;
119- let captures = context_re. captures ( param. to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
120- let num = captures
121- . name ( "num1" )
122- . or ( captures. name ( "num2" ) )
123- . or ( captures. name ( "num3" ) ) ;
124- if num. is_some ( ) && !num. unwrap ( ) . as_str ( ) . is_empty ( ) {
125- context_count = Some ( num. unwrap ( ) . as_str ( ) . parse :: < usize > ( ) . unwrap ( ) ) ;
126- }
127- if param == "-C" {
128- let next_param = opts. peek ( ) ;
129- if next_param. is_some ( ) {
130- let next_value = next_param
131- . unwrap ( )
132- . to_string_lossy ( )
133- . as_ref ( )
134- . parse :: < usize > ( ) ;
135- if next_value. is_ok ( ) {
136- context_count = Some ( next_value. unwrap ( ) ) ;
111+ match match_context_diff_params ( & param, next_param, format) {
112+ Ok ( DiffStyleMatch {
113+ is_match,
114+ context_count,
115+ next_param_consumed,
116+ } ) => {
117+ if is_match {
118+ format = Some ( Format :: Context ) ;
119+ if context_count. is_some ( ) {
120+ context = context_count;
121+ }
122+ if next_param_consumed {
137123 opts. next ( ) ;
138- } else {
139- return Err ( format ! (
140- "invalid context length '{}'" ,
141- next_param. unwrap( ) . to_string_lossy( )
142- ) ) ;
143124 }
125+ continue ;
144126 }
145127 }
146- continue ;
128+ Err ( error ) => return Err ( error ) ,
147129 }
148- if unified_re. is_match ( param. to_string_lossy ( ) . as_ref ( ) ) {
149- if format. is_some ( ) && format != Some ( Format :: Unified ) {
150- return Err ( "Conflicting output style options" . to_string ( ) ) ;
151- }
152- format = Some ( Format :: Unified ) ;
153- let captures = unified_re. captures ( param. to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
154- let num = captures
155- . name ( "num1" )
156- . or ( captures. name ( "num2" ) )
157- . or ( captures. name ( "num3" ) ) ;
158- if num. is_some ( ) && !num. unwrap ( ) . as_str ( ) . is_empty ( ) {
159- context_count = Some ( num. unwrap ( ) . as_str ( ) . parse :: < usize > ( ) . unwrap ( ) ) ;
160- }
161- if param == "-U" {
162- let next_param = opts. peek ( ) ;
163- if next_param. is_some ( ) {
164- let next_value = next_param
165- . unwrap ( )
166- . to_string_lossy ( )
167- . as_ref ( )
168- . parse :: < usize > ( ) ;
169- if next_value. is_ok ( ) {
170- context_count = Some ( next_value. unwrap ( ) ) ;
130+ match match_unified_diff_params ( & param, next_param, format) {
131+ Ok ( DiffStyleMatch {
132+ is_match,
133+ context_count,
134+ next_param_consumed,
135+ } ) => {
136+ if is_match {
137+ format = Some ( Format :: Unified ) ;
138+ if context_count. is_some ( ) {
139+ context = context_count;
140+ }
141+ if next_param_consumed {
171142 opts. next ( ) ;
172- } else {
173- return Err ( format ! (
174- "invalid context length '{}'" ,
175- next_param. unwrap( ) . to_string_lossy( )
176- ) ) ;
177143 }
144+ continue ;
178145 }
179146 }
180- continue ;
147+ Err ( error ) => return Err ( error ) ,
181148 }
182149 if param. to_string_lossy ( ) . starts_with ( '-' ) {
183150 return Err ( format ! ( "Unknown option: {:?}" , param) ) ;
@@ -205,12 +172,110 @@ pub fn parse_params<I: IntoIterator<Item = OsString>>(opts: I) -> Result<Params,
205172 return Err ( format ! ( "Usage: {} <from> <to>" , exe. to_string_lossy( ) ) ) ;
206173 } ;
207174 params. format = format. unwrap_or ( Format :: default ( ) ) ;
208- if context_count . is_some ( ) {
209- params. context_count = context_count. unwrap ( ) ;
175+ if let Some ( context_count ) = context {
176+ params. context_count = context_count;
210177 }
211178 Ok ( params)
212179}
213180
181+ struct DiffStyleMatch {
182+ is_match : bool ,
183+ context_count : Option < usize > ,
184+ next_param_consumed : bool ,
185+ }
186+
187+ fn match_context_diff_params (
188+ param : & OsString ,
189+ next_param : Option < & OsString > ,
190+ format : Option < Format > ,
191+ ) -> Result < DiffStyleMatch , String > {
192+ const CONTEXT_RE : & str = r"^(-[cC](?<num1>\d*)|--context(=(?<num2>\d*))?|-(?<num3>\d+)c)$" ;
193+ let regex = Regex :: new ( CONTEXT_RE ) . unwrap ( ) ;
194+ let is_match = regex. is_match ( param. to_string_lossy ( ) . as_ref ( ) ) ;
195+ let mut context_count = None ;
196+ let mut next_param_consumed = false ;
197+ if is_match {
198+ if format. is_some ( ) && format != Some ( Format :: Context ) {
199+ return Err ( "Conflicting output style options" . to_string ( ) ) ;
200+ }
201+ let captures = regex. captures ( param. to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
202+ let num = captures
203+ . name ( "num1" )
204+ . or ( captures. name ( "num2" ) )
205+ . or ( captures. name ( "num3" ) ) ;
206+ if let Some ( numvalue) = num {
207+ if !numvalue. as_str ( ) . is_empty ( ) {
208+ context_count = Some ( numvalue. as_str ( ) . parse :: < usize > ( ) . unwrap ( ) ) ;
209+ }
210+ }
211+ if param == "-C" && next_param. is_some ( ) {
212+ match next_param. unwrap ( ) . to_string_lossy ( ) . parse :: < usize > ( ) {
213+ Ok ( context_size) => {
214+ context_count = Some ( context_size) ;
215+ next_param_consumed = true ;
216+ }
217+ Err ( _) => {
218+ return Err ( format ! (
219+ "invalid context length '{}'" ,
220+ next_param. unwrap( ) . to_string_lossy( )
221+ ) )
222+ }
223+ }
224+ }
225+ }
226+ Ok ( DiffStyleMatch {
227+ is_match,
228+ context_count,
229+ next_param_consumed,
230+ } )
231+ }
232+
233+ fn match_unified_diff_params (
234+ param : & OsString ,
235+ next_param : Option < & OsString > ,
236+ format : Option < Format > ,
237+ ) -> Result < DiffStyleMatch , String > {
238+ const UNIFIED_RE : & str = r"^(-[uU](?<num1>\d*)|--unified(=(?<num2>\d*))?|-(?<num3>\d+)u)$" ;
239+ let regex = Regex :: new ( UNIFIED_RE ) . unwrap ( ) ;
240+ let is_match = regex. is_match ( param. to_string_lossy ( ) . as_ref ( ) ) ;
241+ let mut context_count = None ;
242+ let mut next_param_consumed = false ;
243+ if is_match {
244+ if format. is_some ( ) && format != Some ( Format :: Unified ) {
245+ return Err ( "Conflicting output style options" . to_string ( ) ) ;
246+ }
247+ let captures = regex. captures ( param. to_str ( ) . unwrap ( ) ) . unwrap ( ) ;
248+ let num = captures
249+ . name ( "num1" )
250+ . or ( captures. name ( "num2" ) )
251+ . or ( captures. name ( "num3" ) ) ;
252+ if let Some ( numvalue) = num {
253+ if !numvalue. as_str ( ) . is_empty ( ) {
254+ context_count = Some ( numvalue. as_str ( ) . parse :: < usize > ( ) . unwrap ( ) ) ;
255+ }
256+ }
257+ if param == "-U" && next_param. is_some ( ) {
258+ match next_param. unwrap ( ) . to_string_lossy ( ) . parse :: < usize > ( ) {
259+ Ok ( context_size) => {
260+ context_count = Some ( context_size) ;
261+ next_param_consumed = true ;
262+ }
263+ Err ( _) => {
264+ return Err ( format ! (
265+ "invalid context length '{}'" ,
266+ next_param. unwrap( ) . to_string_lossy( )
267+ ) )
268+ }
269+ }
270+ }
271+ }
272+ Ok ( DiffStyleMatch {
273+ is_match,
274+ context_count,
275+ next_param_consumed,
276+ } )
277+ }
278+
214279#[ cfg( test) ]
215280mod tests {
216281 use super :: * ;
0 commit comments