exa/src/options/dir_action.rs
Benjamin Sago 9872eba821 Separate the matched flags from the free strings
Originally, both the matched flags and the list of free strings were returned from the parsing function and then passed around to every type that had a ‘deduce’ method. This worked, but the list of free strings was carried around with it, never used.

Now, only the flags are passed around. They’re in a new struct which has the methods the Matches had.

Both of Matches’s fields are now just data, and all of the methods on MatchedFlags don’t ignore any fields, so it’s more cohesive, at least I think that’s the word.

Building up the MatchedFlags is a bit more annoying though because the vector is now hidden behind a field.
2017-08-05 19:11:00 +01:00

106 lines
4.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use options::parser::MatchedFlags;
use options::{flags, Misfire};
use fs::dir_action::{DirAction, RecurseOptions};
impl DirAction {
/// Determine which action to perform when trying to list a directory.
pub fn deduce(matches: &MatchedFlags) -> Result<DirAction, Misfire> {
let recurse = matches.has(&flags::RECURSE);
let list = matches.has(&flags::LIST_DIRS);
let tree = matches.has(&flags::TREE);
// Early check for --level when it wouldnt do anything
if !recurse && !tree && matches.get(&flags::LEVEL).is_some() {
return Err(Misfire::Useless2(&flags::LEVEL, &flags::RECURSE, &flags::TREE));
}
match (recurse, list, tree) {
// You can't --list-dirs along with --recurse or --tree because
// they already automatically list directories.
(true, true, _ ) => Err(Misfire::Conflict(&flags::RECURSE, &flags::LIST_DIRS)),
(_, true, true ) => Err(Misfire::Conflict(&flags::TREE, &flags::LIST_DIRS)),
(_ , _, true ) => Ok(DirAction::Recurse(RecurseOptions::deduce(matches, true)?)),
(true, false, false) => Ok(DirAction::Recurse(RecurseOptions::deduce(matches, false)?)),
(false, true, _ ) => Ok(DirAction::AsFile),
(false, false, _ ) => Ok(DirAction::List),
}
}
}
impl RecurseOptions {
/// Determine which files should be recursed into.
pub fn deduce(matches: &MatchedFlags, tree: bool) -> Result<RecurseOptions, Misfire> {
let max_depth = if let Some(level) = matches.get(&flags::LEVEL) {
match level.to_string_lossy().parse() {
Ok(l) => Some(l),
Err(e) => return Err(Misfire::FailedParse(e)),
}
}
else {
None
};
Ok(RecurseOptions { tree, max_depth })
}
}
#[cfg(test)]
mod test {
use super::*;
use std::ffi::OsString;
use options::flags;
pub fn os(input: &'static str) -> OsString {
let mut os = OsString::new();
os.push(input);
os
}
macro_rules! test {
($name:ident: $type:ident <- $inputs:expr => $result:expr) => {
#[test]
fn $name() {
use options::parser::{Args, Arg};
use std::ffi::OsString;
static TEST_ARGS: &[&Arg] = &[ &flags::RECURSE, &flags::LIST_DIRS, &flags::TREE, &flags::LEVEL ];
let bits = $inputs.as_ref().into_iter().map(|&o| os(o)).collect::<Vec<OsString>>();
let results = Args(TEST_ARGS).parse(bits.iter());
assert_eq!($type::deduce(&results.unwrap().flags), $result);
}
};
}
// Default behaviour
test!(empty: DirAction <- [] => Ok(DirAction::List));
// Listing files as directories
test!(dirs_short: DirAction <- ["-d"] => Ok(DirAction::AsFile));
test!(dirs_long: DirAction <- ["--list-dirs"] => Ok(DirAction::AsFile));
// Recursing
test!(rec_short: DirAction <- ["-R"] => Ok(DirAction::Recurse(RecurseOptions { tree: false, max_depth: None })));
test!(rec_long: DirAction <- ["--recurse"] => Ok(DirAction::Recurse(RecurseOptions { tree: false, max_depth: None })));
test!(rec_lim_short: DirAction <- ["-RL4"] => Ok(DirAction::Recurse(RecurseOptions { tree: false, max_depth: Some(4) })));
test!(rec_lim_short_2: DirAction <- ["-RL=5"] => Ok(DirAction::Recurse(RecurseOptions { tree: false, max_depth: Some(5) })));
test!(rec_lim_long: DirAction <- ["--recurse", "--level", "666"] => Ok(DirAction::Recurse(RecurseOptions { tree: false, max_depth: Some(666) })));
test!(rec_lim_long_2: DirAction <- ["--recurse", "--level=0118"] => Ok(DirAction::Recurse(RecurseOptions { tree: false, max_depth: Some(118) })));
test!(rec_tree: DirAction <- ["--recurse", "--tree"] => Ok(DirAction::Recurse(RecurseOptions { tree: true, max_depth: None })));
test!(rec_short_tree: DirAction <- ["--tree", "--recurse"] => Ok(DirAction::Recurse(RecurseOptions { tree: true, max_depth: None })));
// Errors
test!(error: DirAction <- ["--list-dirs", "--recurse"] => Err(Misfire::Conflict(&flags::RECURSE, &flags::LIST_DIRS)));
test!(error_2: DirAction <- ["--list-dirs", "--tree"] => Err(Misfire::Conflict(&flags::TREE, &flags::LIST_DIRS)));
test!(underwaterlevel: DirAction <- ["--level=4"] => Err(Misfire::Useless2(&flags::LEVEL, &flags::RECURSE, &flags::TREE)));
}