Skip to content

Commit b7261a4

Browse files
committed
Break out the logic to match context/unified diff params into separate functions, for improved readability
1 parent 37fe1ae commit b7261a4

File tree

1 file changed

+130
-65
lines changed

1 file changed

+130
-65
lines changed

src/params.rs

Lines changed: 130 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -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)]
215280
mod tests {
216281
use super::*;

0 commit comments

Comments
 (0)