2017-08-12 10:29:40 +00:00
|
|
|
|
//! Parsing the options for `DirAction`.
|
|
|
|
|
|
2018-12-07 23:43:31 +00:00
|
|
|
|
use crate::options::parser::MatchedFlags;
|
|
|
|
|
use crate::options::{flags, Misfire};
|
2016-04-17 19:38:37 +00:00
|
|
|
|
|
2018-12-07 23:43:31 +00:00
|
|
|
|
use crate::fs::dir_action::{DirAction, RecurseOptions};
|
2016-04-17 19:38:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl DirAction {
|
|
|
|
|
|
|
|
|
|
/// Determine which action to perform when trying to list a directory.
|
2017-08-12 10:29:40 +00:00
|
|
|
|
/// There are three possible actions, and they overlap somewhat: the
|
|
|
|
|
/// `--tree` flag is another form of recursion, so those two are allowed
|
|
|
|
|
/// to both be present, but the `--list-dirs` flag is used separately.
|
2020-10-10 12:55:26 +00:00
|
|
|
|
pub fn deduce(matches: &MatchedFlags) -> Result<Self, Misfire> {
|
Be stricter in strict mode
Now the code actually starts to use the Strictness flag that was added in the earlier commit! Well, the *code* doesn’t, but the tests do: the macros that create the test cases now have a parameter for which tests they should run. It’s usually ‘Both’ for both strict mode and default mode, but can be specified to only run in one, for when the results differ (usually when options override one another)
The downside to strict mode is that, now, *any* call to `matches.has` or `matches.get` could fail, because an option could have been specified twice, and this is the place where those are checked for. This makes the code a little less ergonomic in places, but that’s what the ? operator is for. The only place this has really had an effect is in `Classify::deduce`, which used to just return a boolean but can now fail.
In order to more thoroughly test the mode, some of the older parts of the code can now act more strict. For example, `TerminalColours::deduce` will now use the last-given option rather than searching for “colours” before “colors”.
Help and Version continue doing their own thing.
2017-08-09 08:21:29 +00:00
|
|
|
|
let recurse = matches.has(&flags::RECURSE)?;
|
2017-08-11 21:56:52 +00:00
|
|
|
|
let as_file = matches.has(&flags::LIST_DIRS)?;
|
Be stricter in strict mode
Now the code actually starts to use the Strictness flag that was added in the earlier commit! Well, the *code* doesn’t, but the tests do: the macros that create the test cases now have a parameter for which tests they should run. It’s usually ‘Both’ for both strict mode and default mode, but can be specified to only run in one, for when the results differ (usually when options override one another)
The downside to strict mode is that, now, *any* call to `matches.has` or `matches.get` could fail, because an option could have been specified twice, and this is the place where those are checked for. This makes the code a little less ergonomic in places, but that’s what the ? operator is for. The only place this has really had an effect is in `Classify::deduce`, which used to just return a boolean but can now fail.
In order to more thoroughly test the mode, some of the older parts of the code can now act more strict. For example, `TerminalColours::deduce` will now use the last-given option rather than searching for “colours” before “colors”.
Help and Version continue doing their own thing.
2017-08-09 08:21:29 +00:00
|
|
|
|
let tree = matches.has(&flags::TREE)?;
|
2016-04-17 19:38:37 +00:00
|
|
|
|
|
2017-08-11 21:56:52 +00:00
|
|
|
|
if matches.is_strict() {
|
|
|
|
|
// Early check for --level when it wouldn’t do anything
|
2020-10-10 18:49:46 +00:00
|
|
|
|
if ! recurse && ! tree && matches.count(&flags::LEVEL) > 0 {
|
2017-08-11 21:56:52 +00:00
|
|
|
|
return Err(Misfire::Useless2(&flags::LEVEL, &flags::RECURSE, &flags::TREE));
|
|
|
|
|
}
|
|
|
|
|
else if recurse && as_file {
|
|
|
|
|
return Err(Misfire::Conflict(&flags::RECURSE, &flags::LIST_DIRS));
|
|
|
|
|
}
|
|
|
|
|
else if tree && as_file {
|
|
|
|
|
return Err(Misfire::Conflict(&flags::TREE, &flags::LIST_DIRS));
|
|
|
|
|
}
|
2017-08-05 12:57:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-08-11 21:56:52 +00:00
|
|
|
|
if tree {
|
2020-10-10 12:55:26 +00:00
|
|
|
|
Ok(Self::Recurse(RecurseOptions::deduce(matches, true)?))
|
2017-08-11 21:56:52 +00:00
|
|
|
|
}
|
|
|
|
|
else if recurse {
|
2020-10-10 12:55:26 +00:00
|
|
|
|
Ok(Self::Recurse(RecurseOptions::deduce(matches, false)?))
|
2017-08-11 21:56:52 +00:00
|
|
|
|
}
|
|
|
|
|
else if as_file {
|
2020-10-10 12:55:26 +00:00
|
|
|
|
Ok(Self::AsFile)
|
2017-08-11 21:56:52 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
2020-10-10 12:55:26 +00:00
|
|
|
|
Ok(Self::List)
|
2016-04-17 19:38:37 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl RecurseOptions {
|
|
|
|
|
|
2017-08-12 10:29:40 +00:00
|
|
|
|
/// Determine which files should be recursed into, based on the `--level`
|
|
|
|
|
/// flag’s value, and whether the `--tree` flag was passed, which was
|
|
|
|
|
/// determined earlier. The maximum level should be a number, and this
|
|
|
|
|
/// will fail with an `Err` if it isn’t.
|
2020-10-10 12:55:26 +00:00
|
|
|
|
pub fn deduce(matches: &MatchedFlags, tree: bool) -> Result<Self, Misfire> {
|
Be stricter in strict mode
Now the code actually starts to use the Strictness flag that was added in the earlier commit! Well, the *code* doesn’t, but the tests do: the macros that create the test cases now have a parameter for which tests they should run. It’s usually ‘Both’ for both strict mode and default mode, but can be specified to only run in one, for when the results differ (usually when options override one another)
The downside to strict mode is that, now, *any* call to `matches.has` or `matches.get` could fail, because an option could have been specified twice, and this is the place where those are checked for. This makes the code a little less ergonomic in places, but that’s what the ? operator is for. The only place this has really had an effect is in `Classify::deduce`, which used to just return a boolean but can now fail.
In order to more thoroughly test the mode, some of the older parts of the code can now act more strict. For example, `TerminalColours::deduce` will now use the last-given option rather than searching for “colours” before “colors”.
Help and Version continue doing their own thing.
2017-08-09 08:21:29 +00:00
|
|
|
|
let max_depth = if let Some(level) = matches.get(&flags::LEVEL)? {
|
2017-07-26 16:48:18 +00:00
|
|
|
|
match level.to_string_lossy().parse() {
|
2016-04-17 19:38:37 +00:00
|
|
|
|
Ok(l) => Some(l),
|
|
|
|
|
Err(e) => return Err(Misfire::FailedParse(e)),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
None
|
|
|
|
|
};
|
|
|
|
|
|
2020-10-10 12:55:26 +00:00
|
|
|
|
Ok(Self { tree, max_depth })
|
2016-04-17 19:38:37 +00:00
|
|
|
|
}
|
2017-07-24 07:34:50 +00:00
|
|
|
|
}
|
2017-08-05 12:57:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod test {
|
|
|
|
|
use super::*;
|
2018-12-07 23:43:31 +00:00
|
|
|
|
use crate::options::flags;
|
|
|
|
|
use crate::options::parser::Flag;
|
2017-08-05 12:57:20 +00:00
|
|
|
|
|
|
|
|
|
macro_rules! test {
|
Be stricter in strict mode
Now the code actually starts to use the Strictness flag that was added in the earlier commit! Well, the *code* doesn’t, but the tests do: the macros that create the test cases now have a parameter for which tests they should run. It’s usually ‘Both’ for both strict mode and default mode, but can be specified to only run in one, for when the results differ (usually when options override one another)
The downside to strict mode is that, now, *any* call to `matches.has` or `matches.get` could fail, because an option could have been specified twice, and this is the place where those are checked for. This makes the code a little less ergonomic in places, but that’s what the ? operator is for. The only place this has really had an effect is in `Classify::deduce`, which used to just return a boolean but can now fail.
In order to more thoroughly test the mode, some of the older parts of the code can now act more strict. For example, `TerminalColours::deduce` will now use the last-given option rather than searching for “colours” before “colors”.
Help and Version continue doing their own thing.
2017-08-09 08:21:29 +00:00
|
|
|
|
($name:ident: $type:ident <- $inputs:expr; $stricts:expr => $result:expr) => {
|
2017-08-05 12:57:20 +00:00
|
|
|
|
#[test]
|
|
|
|
|
fn $name() {
|
2018-12-07 23:43:31 +00:00
|
|
|
|
use crate::options::parser::Arg;
|
|
|
|
|
use crate::options::test::parse_for_test;
|
|
|
|
|
use crate::options::test::Strictnesses::*;
|
2017-08-05 12:57:20 +00:00
|
|
|
|
|
2017-08-08 08:18:17 +00:00
|
|
|
|
static TEST_ARGS: &[&Arg] = &[&flags::RECURSE, &flags::LIST_DIRS, &flags::TREE, &flags::LEVEL ];
|
2017-08-09 12:36:06 +00:00
|
|
|
|
for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf)) {
|
|
|
|
|
assert_eq!(result, $result);
|
|
|
|
|
}
|
2017-08-05 12:57:20 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Default behaviour
|
Be stricter in strict mode
Now the code actually starts to use the Strictness flag that was added in the earlier commit! Well, the *code* doesn’t, but the tests do: the macros that create the test cases now have a parameter for which tests they should run. It’s usually ‘Both’ for both strict mode and default mode, but can be specified to only run in one, for when the results differ (usually when options override one another)
The downside to strict mode is that, now, *any* call to `matches.has` or `matches.get` could fail, because an option could have been specified twice, and this is the place where those are checked for. This makes the code a little less ergonomic in places, but that’s what the ? operator is for. The only place this has really had an effect is in `Classify::deduce`, which used to just return a boolean but can now fail.
In order to more thoroughly test the mode, some of the older parts of the code can now act more strict. For example, `TerminalColours::deduce` will now use the last-given option rather than searching for “colours” before “colors”.
Help and Version continue doing their own thing.
2017-08-09 08:21:29 +00:00
|
|
|
|
test!(empty: DirAction <- []; Both => Ok(DirAction::List));
|
2017-08-05 12:57:20 +00:00
|
|
|
|
|
|
|
|
|
// Listing files as directories
|
Be stricter in strict mode
Now the code actually starts to use the Strictness flag that was added in the earlier commit! Well, the *code* doesn’t, but the tests do: the macros that create the test cases now have a parameter for which tests they should run. It’s usually ‘Both’ for both strict mode and default mode, but can be specified to only run in one, for when the results differ (usually when options override one another)
The downside to strict mode is that, now, *any* call to `matches.has` or `matches.get` could fail, because an option could have been specified twice, and this is the place where those are checked for. This makes the code a little less ergonomic in places, but that’s what the ? operator is for. The only place this has really had an effect is in `Classify::deduce`, which used to just return a boolean but can now fail.
In order to more thoroughly test the mode, some of the older parts of the code can now act more strict. For example, `TerminalColours::deduce` will now use the last-given option rather than searching for “colours” before “colors”.
Help and Version continue doing their own thing.
2017-08-09 08:21:29 +00:00
|
|
|
|
test!(dirs_short: DirAction <- ["-d"]; Both => Ok(DirAction::AsFile));
|
|
|
|
|
test!(dirs_long: DirAction <- ["--list-dirs"]; Both => Ok(DirAction::AsFile));
|
2017-08-05 12:57:20 +00:00
|
|
|
|
|
|
|
|
|
// Recursing
|
2017-08-08 08:20:46 +00:00
|
|
|
|
use self::DirAction::Recurse;
|
Be stricter in strict mode
Now the code actually starts to use the Strictness flag that was added in the earlier commit! Well, the *code* doesn’t, but the tests do: the macros that create the test cases now have a parameter for which tests they should run. It’s usually ‘Both’ for both strict mode and default mode, but can be specified to only run in one, for when the results differ (usually when options override one another)
The downside to strict mode is that, now, *any* call to `matches.has` or `matches.get` could fail, because an option could have been specified twice, and this is the place where those are checked for. This makes the code a little less ergonomic in places, but that’s what the ? operator is for. The only place this has really had an effect is in `Classify::deduce`, which used to just return a boolean but can now fail.
In order to more thoroughly test the mode, some of the older parts of the code can now act more strict. For example, `TerminalColours::deduce` will now use the last-given option rather than searching for “colours” before “colors”.
Help and Version continue doing their own thing.
2017-08-09 08:21:29 +00:00
|
|
|
|
test!(rec_short: DirAction <- ["-R"]; Both => Ok(Recurse(RecurseOptions { tree: false, max_depth: None })));
|
|
|
|
|
test!(rec_long: DirAction <- ["--recurse"]; Both => Ok(Recurse(RecurseOptions { tree: false, max_depth: None })));
|
|
|
|
|
test!(rec_lim_short: DirAction <- ["-RL4"]; Both => Ok(Recurse(RecurseOptions { tree: false, max_depth: Some(4) })));
|
|
|
|
|
test!(rec_lim_short_2: DirAction <- ["-RL=5"]; Both => Ok(Recurse(RecurseOptions { tree: false, max_depth: Some(5) })));
|
|
|
|
|
test!(rec_lim_long: DirAction <- ["--recurse", "--level", "666"]; Both => Ok(Recurse(RecurseOptions { tree: false, max_depth: Some(666) })));
|
|
|
|
|
test!(rec_lim_long_2: DirAction <- ["--recurse", "--level=0118"]; Both => Ok(Recurse(RecurseOptions { tree: false, max_depth: Some(118) })));
|
2017-08-11 21:56:52 +00:00
|
|
|
|
test!(tree: DirAction <- ["--tree"]; Both => Ok(Recurse(RecurseOptions { tree: true, max_depth: None })));
|
Be stricter in strict mode
Now the code actually starts to use the Strictness flag that was added in the earlier commit! Well, the *code* doesn’t, but the tests do: the macros that create the test cases now have a parameter for which tests they should run. It’s usually ‘Both’ for both strict mode and default mode, but can be specified to only run in one, for when the results differ (usually when options override one another)
The downside to strict mode is that, now, *any* call to `matches.has` or `matches.get` could fail, because an option could have been specified twice, and this is the place where those are checked for. This makes the code a little less ergonomic in places, but that’s what the ? operator is for. The only place this has really had an effect is in `Classify::deduce`, which used to just return a boolean but can now fail.
In order to more thoroughly test the mode, some of the older parts of the code can now act more strict. For example, `TerminalColours::deduce` will now use the last-given option rather than searching for “colours” before “colors”.
Help and Version continue doing their own thing.
2017-08-09 08:21:29 +00:00
|
|
|
|
test!(rec_tree: DirAction <- ["--recurse", "--tree"]; Both => Ok(Recurse(RecurseOptions { tree: true, max_depth: None })));
|
2017-08-11 21:56:52 +00:00
|
|
|
|
test!(rec_short_tree: DirAction <- ["-TR"]; Both => Ok(Recurse(RecurseOptions { tree: true, max_depth: None })));
|
|
|
|
|
|
|
|
|
|
// Overriding --list-dirs, --recurse, and --tree
|
|
|
|
|
test!(dirs_recurse: DirAction <- ["--list-dirs", "--recurse"]; Last => Ok(Recurse(RecurseOptions { tree: false, max_depth: None })));
|
|
|
|
|
test!(dirs_tree: DirAction <- ["--list-dirs", "--tree"]; Last => Ok(Recurse(RecurseOptions { tree: true, max_depth: None })));
|
|
|
|
|
test!(just_level: DirAction <- ["--level=4"]; Last => Ok(DirAction::List));
|
|
|
|
|
|
|
|
|
|
test!(dirs_recurse_2: DirAction <- ["--list-dirs", "--recurse"]; Complain => Err(Misfire::Conflict(&flags::RECURSE, &flags::LIST_DIRS)));
|
|
|
|
|
test!(dirs_tree_2: DirAction <- ["--list-dirs", "--tree"]; Complain => Err(Misfire::Conflict(&flags::TREE, &flags::LIST_DIRS)));
|
|
|
|
|
test!(just_level_2: DirAction <- ["--level=4"]; Complain => Err(Misfire::Useless2(&flags::LEVEL, &flags::RECURSE, &flags::TREE)));
|
2017-08-05 12:57:20 +00:00
|
|
|
|
|
Be stricter in strict mode
Now the code actually starts to use the Strictness flag that was added in the earlier commit! Well, the *code* doesn’t, but the tests do: the macros that create the test cases now have a parameter for which tests they should run. It’s usually ‘Both’ for both strict mode and default mode, but can be specified to only run in one, for when the results differ (usually when options override one another)
The downside to strict mode is that, now, *any* call to `matches.has` or `matches.get` could fail, because an option could have been specified twice, and this is the place where those are checked for. This makes the code a little less ergonomic in places, but that’s what the ? operator is for. The only place this has really had an effect is in `Classify::deduce`, which used to just return a boolean but can now fail.
In order to more thoroughly test the mode, some of the older parts of the code can now act more strict. For example, `TerminalColours::deduce` will now use the last-given option rather than searching for “colours” before “colors”.
Help and Version continue doing their own thing.
2017-08-09 08:21:29 +00:00
|
|
|
|
|
2017-08-11 21:56:52 +00:00
|
|
|
|
// Overriding levels
|
Be stricter in strict mode
Now the code actually starts to use the Strictness flag that was added in the earlier commit! Well, the *code* doesn’t, but the tests do: the macros that create the test cases now have a parameter for which tests they should run. It’s usually ‘Both’ for both strict mode and default mode, but can be specified to only run in one, for when the results differ (usually when options override one another)
The downside to strict mode is that, now, *any* call to `matches.has` or `matches.get` could fail, because an option could have been specified twice, and this is the place where those are checked for. This makes the code a little less ergonomic in places, but that’s what the ? operator is for. The only place this has really had an effect is in `Classify::deduce`, which used to just return a boolean but can now fail.
In order to more thoroughly test the mode, some of the older parts of the code can now act more strict. For example, `TerminalColours::deduce` will now use the last-given option rather than searching for “colours” before “colors”.
Help and Version continue doing their own thing.
2017-08-09 08:21:29 +00:00
|
|
|
|
test!(overriding_1: DirAction <- ["-RL=6", "-L=7"]; Last => Ok(Recurse(RecurseOptions { tree: false, max_depth: Some(7) })));
|
|
|
|
|
test!(overriding_2: DirAction <- ["-RL=6", "-L=7"]; Complain => Err(Misfire::Duplicate(Flag::Short(b'L'), Flag::Short(b'L'))));
|
2017-08-05 12:57:20 +00:00
|
|
|
|
}
|