2020-10-10 19:49:46 +01:00
|
|
|
|
use crate::fs::feature::xattr;
|
2021-04-12 21:42:45 +01:00
|
|
|
|
use crate::options::{flags, OptionsError, NumberSource, Vars};
|
2018-12-08 00:43:31 +01:00
|
|
|
|
use crate::options::parser::MatchedFlags;
|
2020-10-23 23:57:10 +01:00
|
|
|
|
use crate::output::{View, Mode, TerminalWidth, grid, details};
|
2018-12-08 00:43:31 +01:00
|
|
|
|
use crate::output::grid_details::{self, RowThreshold};
|
Massive theming and view options refactor
This commit significantly refactors the way that options are parsed. It introduces the Theme type which contains both styling and extension configuration, converts the option-parsing process into a being a pure function, and removes some rather gnarly old code.
The main purpose of the refactoring is to fix GH-318, "Tests fail when not connected to a terminal". Even though exa was compiling fine on my machine and on Travis, it was failing for automated build scripts. This was because of what the option-parsing code was trying to accomplish: it wasn't just providing a struct of the user's settings, it was also checking the terminal, providing a View directly.
This has been changed so that the options module now _only_ looks at the command-line arguments and environment variables. Instead of returning a View, it returns the user's _preference_, and it's then up to the 'main' module to examine the terminal width and figure out if the view is doable, downgrading it if necessary.
The code that used to determine the view was horrible and I'm pleased it can be cut out. Also, the terminal width used to be in a lazy_static because it was queried multiple times, and now it's not in one because it's only queried once, which is a good sign for things going in the right direction.
There are also some naming and organisational changes around themes. The blanket terms "Colours" and "Styles" have been yeeted in favour of "Theme", which handles both extensions and UI colours. The FileStyle struct has been replaced with file_name::Options, making it similar to the views in how it has an Options struct and a Render struct.
Finally, eight unit tests have been removed because they turned out to be redundant (testing --colour and --color) after examining the tangled code, and the default theme has been put in its own file in preparation for more themes.
2020-10-22 22:34:00 +01:00
|
|
|
|
use crate::output::file_name::Options as FileStyle;
|
2021-03-19 08:46:03 +08:00
|
|
|
|
use crate::output::table::{TimeTypes, SizeFormat, UserFormat, Columns, Options as TableOptions};
|
2018-12-08 00:43:31 +01:00
|
|
|
|
use crate::output::time::TimeFormat;
|
2017-07-26 17:48:18 +01:00
|
|
|
|
|
2017-08-24 23:38:26 +01:00
|
|
|
|
|
2017-06-25 12:31:46 +01:00
|
|
|
|
impl View {
|
2020-10-13 01:36:41 +01:00
|
|
|
|
pub fn deduce<V: Vars>(matches: &MatchedFlags<'_>, vars: &V) -> Result<Self, OptionsError> {
|
2017-08-10 17:54:28 +01:00
|
|
|
|
let mode = Mode::deduce(matches, vars)?;
|
Massive theming and view options refactor
This commit significantly refactors the way that options are parsed. It introduces the Theme type which contains both styling and extension configuration, converts the option-parsing process into a being a pure function, and removes some rather gnarly old code.
The main purpose of the refactoring is to fix GH-318, "Tests fail when not connected to a terminal". Even though exa was compiling fine on my machine and on Travis, it was failing for automated build scripts. This was because of what the option-parsing code was trying to accomplish: it wasn't just providing a struct of the user's settings, it was also checking the terminal, providing a View directly.
This has been changed so that the options module now _only_ looks at the command-line arguments and environment variables. Instead of returning a View, it returns the user's _preference_, and it's then up to the 'main' module to examine the terminal width and figure out if the view is doable, downgrading it if necessary.
The code that used to determine the view was horrible and I'm pleased it can be cut out. Also, the terminal width used to be in a lazy_static because it was queried multiple times, and now it's not in one because it's only queried once, which is a good sign for things going in the right direction.
There are also some naming and organisational changes around themes. The blanket terms "Colours" and "Styles" have been yeeted in favour of "Theme", which handles both extensions and UI colours. The FileStyle struct has been replaced with file_name::Options, making it similar to the views in how it has an Options struct and a Render struct.
Finally, eight unit tests have been removed because they turned out to be redundant (testing --colour and --color) after examining the tangled code, and the default theme has been put in its own file in preparation for more themes.
2020-10-22 22:34:00 +01:00
|
|
|
|
let width = TerminalWidth::deduce(vars)?;
|
2020-10-24 19:39:22 +01:00
|
|
|
|
let file_style = FileStyle::deduce(matches, vars)?;
|
Massive theming and view options refactor
This commit significantly refactors the way that options are parsed. It introduces the Theme type which contains both styling and extension configuration, converts the option-parsing process into a being a pure function, and removes some rather gnarly old code.
The main purpose of the refactoring is to fix GH-318, "Tests fail when not connected to a terminal". Even though exa was compiling fine on my machine and on Travis, it was failing for automated build scripts. This was because of what the option-parsing code was trying to accomplish: it wasn't just providing a struct of the user's settings, it was also checking the terminal, providing a View directly.
This has been changed so that the options module now _only_ looks at the command-line arguments and environment variables. Instead of returning a View, it returns the user's _preference_, and it's then up to the 'main' module to examine the terminal width and figure out if the view is doable, downgrading it if necessary.
The code that used to determine the view was horrible and I'm pleased it can be cut out. Also, the terminal width used to be in a lazy_static because it was queried multiple times, and now it's not in one because it's only queried once, which is a good sign for things going in the right direction.
There are also some naming and organisational changes around themes. The blanket terms "Colours" and "Styles" have been yeeted in favour of "Theme", which handles both extensions and UI colours. The FileStyle struct has been replaced with file_name::Options, making it similar to the views in how it has an Options struct and a Render struct.
Finally, eight unit tests have been removed because they turned out to be redundant (testing --colour and --color) after examining the tangled code, and the default theme has been put in its own file in preparation for more themes.
2020-10-22 22:34:00 +01:00
|
|
|
|
Ok(Self { mode, width, file_style })
|
2017-06-25 12:31:46 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Mode {
|
Make View command-line args position-dependent
This commit changes the way the View (long mode, lines mode, grid mode, etc) is parsed from the command-line arguments.
Previously, it checked for long and long-grid, then tree, then lines, then grid, in that order, no matter which order the arguments were given in on the command-line. Now, it bases the view on whichever argument comes last in the list.
Unfortunately, the options-parsing code for Views is getting really complicated, but I can't see a way to simplify it while retaining the existing functionality.
It also links the parsing of DirAction to the result of parsing the View, so that you can't use tree mode if your view isn't Details. This is to fix an issue where `exa --tree --oneline` would just emit ".", because the DirAction was treating directories as files, and the argument was ".", and the View made it use lines view. Now, the --tree is ignored, as the view isn't Details.
Fixes GH-407 and GH-583.
2020-10-23 23:04:22 +01:00
|
|
|
|
|
|
|
|
|
/// Determine which viewing mode to use based on the user’s options.
|
|
|
|
|
///
|
|
|
|
|
/// As with the other options, arguments are scanned right-to-left and the
|
|
|
|
|
/// first flag found is matched, so `exa --oneline --long` will pick a
|
|
|
|
|
/// details view, and `exa --long --oneline` will pick the lines view.
|
|
|
|
|
///
|
|
|
|
|
/// This is complicated a little by the fact that `--grid` and `--tree`
|
|
|
|
|
/// can also combine with `--long`, so care has to be taken to use the
|
2020-10-13 01:36:41 +01:00
|
|
|
|
pub fn deduce<V: Vars>(matches: &MatchedFlags<'_>, vars: &V) -> Result<Self, OptionsError> {
|
Make View command-line args position-dependent
This commit changes the way the View (long mode, lines mode, grid mode, etc) is parsed from the command-line arguments.
Previously, it checked for long and long-grid, then tree, then lines, then grid, in that order, no matter which order the arguments were given in on the command-line. Now, it bases the view on whichever argument comes last in the list.
Unfortunately, the options-parsing code for Views is getting really complicated, but I can't see a way to simplify it while retaining the existing functionality.
It also links the parsing of DirAction to the result of parsing the View, so that you can't use tree mode if your view isn't Details. This is to fix an issue where `exa --tree --oneline` would just emit ".", because the DirAction was treating directories as files, and the argument was ".", and the View made it use lines view. Now, the --tree is ignored, as the view isn't Details.
Fixes GH-407 and GH-583.
2020-10-23 23:04:22 +01:00
|
|
|
|
let flag = matches.has_where_any(|f| f.matches(&flags::LONG) || f.matches(&flags::ONE_LINE)
|
|
|
|
|
|| f.matches(&flags::GRID) || f.matches(&flags::TREE));
|
|
|
|
|
|
|
|
|
|
let flag = match flag {
|
|
|
|
|
Some(f) => f,
|
|
|
|
|
None => {
|
|
|
|
|
Self::strict_check_long_flags(matches)?;
|
|
|
|
|
let grid = grid::Options::deduce(matches)?;
|
|
|
|
|
return Ok(Self::Grid(grid));
|
|
|
|
|
}
|
|
|
|
|
};
|
2016-04-17 20:38:37 +01:00
|
|
|
|
|
Make View command-line args position-dependent
This commit changes the way the View (long mode, lines mode, grid mode, etc) is parsed from the command-line arguments.
Previously, it checked for long and long-grid, then tree, then lines, then grid, in that order, no matter which order the arguments were given in on the command-line. Now, it bases the view on whichever argument comes last in the list.
Unfortunately, the options-parsing code for Views is getting really complicated, but I can't see a way to simplify it while retaining the existing functionality.
It also links the parsing of DirAction to the result of parsing the View, so that you can't use tree mode if your view isn't Details. This is to fix an issue where `exa --tree --oneline` would just emit ".", because the DirAction was treating directories as files, and the argument was ".", and the View made it use lines view. Now, the --tree is ignored, as the view isn't Details.
Fixes GH-407 and GH-583.
2020-10-23 23:04:22 +01:00
|
|
|
|
if flag.matches(&flags::LONG)
|
|
|
|
|
|| (flag.matches(&flags::TREE) && matches.has(&flags::LONG)?)
|
|
|
|
|
|| (flag.matches(&flags::GRID) && matches.has(&flags::LONG)?)
|
|
|
|
|
{
|
|
|
|
|
let _ = matches.has(&flags::LONG)?;
|
Massive theming and view options refactor
This commit significantly refactors the way that options are parsed. It introduces the Theme type which contains both styling and extension configuration, converts the option-parsing process into a being a pure function, and removes some rather gnarly old code.
The main purpose of the refactoring is to fix GH-318, "Tests fail when not connected to a terminal". Even though exa was compiling fine on my machine and on Travis, it was failing for automated build scripts. This was because of what the option-parsing code was trying to accomplish: it wasn't just providing a struct of the user's settings, it was also checking the terminal, providing a View directly.
This has been changed so that the options module now _only_ looks at the command-line arguments and environment variables. Instead of returning a View, it returns the user's _preference_, and it's then up to the 'main' module to examine the terminal width and figure out if the view is doable, downgrading it if necessary.
The code that used to determine the view was horrible and I'm pleased it can be cut out. Also, the terminal width used to be in a lazy_static because it was queried multiple times, and now it's not in one because it's only queried once, which is a good sign for things going in the right direction.
There are also some naming and organisational changes around themes. The blanket terms "Colours" and "Styles" have been yeeted in favour of "Theme", which handles both extensions and UI colours. The FileStyle struct has been replaced with file_name::Options, making it similar to the views in how it has an Options struct and a Render struct.
Finally, eight unit tests have been removed because they turned out to be redundant (testing --colour and --color) after examining the tangled code, and the default theme has been put in its own file in preparation for more themes.
2020-10-22 22:34:00 +01:00
|
|
|
|
let details = details::Options::deduce_long(matches, vars)?;
|
|
|
|
|
|
Make View command-line args position-dependent
This commit changes the way the View (long mode, lines mode, grid mode, etc) is parsed from the command-line arguments.
Previously, it checked for long and long-grid, then tree, then lines, then grid, in that order, no matter which order the arguments were given in on the command-line. Now, it bases the view on whichever argument comes last in the list.
Unfortunately, the options-parsing code for Views is getting really complicated, but I can't see a way to simplify it while retaining the existing functionality.
It also links the parsing of DirAction to the result of parsing the View, so that you can't use tree mode if your view isn't Details. This is to fix an issue where `exa --tree --oneline` would just emit ".", because the DirAction was treating directories as files, and the argument was ".", and the View made it use lines view. Now, the --tree is ignored, as the view isn't Details.
Fixes GH-407 and GH-583.
2020-10-23 23:04:22 +01:00
|
|
|
|
let flag = matches.has_where_any(|f| f.matches(&flags::GRID) || f.matches(&flags::TREE));
|
|
|
|
|
|
|
|
|
|
if flag.is_some() && flag.unwrap().matches(&flags::GRID) {
|
|
|
|
|
let _ = matches.has(&flags::GRID)?;
|
Massive theming and view options refactor
This commit significantly refactors the way that options are parsed. It introduces the Theme type which contains both styling and extension configuration, converts the option-parsing process into a being a pure function, and removes some rather gnarly old code.
The main purpose of the refactoring is to fix GH-318, "Tests fail when not connected to a terminal". Even though exa was compiling fine on my machine and on Travis, it was failing for automated build scripts. This was because of what the option-parsing code was trying to accomplish: it wasn't just providing a struct of the user's settings, it was also checking the terminal, providing a View directly.
This has been changed so that the options module now _only_ looks at the command-line arguments and environment variables. Instead of returning a View, it returns the user's _preference_, and it's then up to the 'main' module to examine the terminal width and figure out if the view is doable, downgrading it if necessary.
The code that used to determine the view was horrible and I'm pleased it can be cut out. Also, the terminal width used to be in a lazy_static because it was queried multiple times, and now it's not in one because it's only queried once, which is a good sign for things going in the right direction.
There are also some naming and organisational changes around themes. The blanket terms "Colours" and "Styles" have been yeeted in favour of "Theme", which handles both extensions and UI colours. The FileStyle struct has been replaced with file_name::Options, making it similar to the views in how it has an Options struct and a Render struct.
Finally, eight unit tests have been removed because they turned out to be redundant (testing --colour and --color) after examining the tangled code, and the default theme has been put in its own file in preparation for more themes.
2020-10-22 22:34:00 +01:00
|
|
|
|
let grid = grid::Options::deduce(matches)?;
|
|
|
|
|
let row_threshold = RowThreshold::deduce(vars)?;
|
|
|
|
|
let grid_details = grid_details::Options { grid, details, row_threshold };
|
|
|
|
|
return Ok(Self::GridDetails(grid_details));
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
Cleanup clippy warnings
warning: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration)
--> src/output/escape.rs:4:1
|
4 | pub fn escape<'a>(string: String, bits: &mut Vec<ANSIString<'a>>, good: Style, bad: Style) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
warning: this lifetime isn't used in the function definition
--> src/output/escape.rs:4:15
|
4 | pub fn escape<'a>(string: String, bits: &mut Vec<ANSIString<'_>>, good: Style, bad: Style) {
| ^^
|
warning: single-character string constant used as pattern
--> src/output/table.rs:310:41
|
310 | if file.starts_with(":") {
| ^^^ help: try using a `char` instead: `':'`
|
warning: single-character string constant used as pattern
--> src/output/table.rs:310:41
|
310 | if file.starts_with(":") {
| ^^^ help: try using a `char` instead: `':'`
|
warning: methods called `new` usually return `Self`
--> src/output/render/git.rs:38:5
|
38 | fn new(&self) -> Style;
| ^^^^^^^^^^^^^^^^^^^^^^^
|
warning: this lifetime isn't used in the function definition
--> src/output/icons.rs:40:22
|
40 | pub fn iconify_style<'a>(style: Style) -> Style {
| ^^
|
warning: lint `clippy::find_map` has been removed: this lint has been replaced by `manual_find_map`, a more specific lint
--> src/main.rs:11:10
|
11 | #![allow(clippy::find_map)]
| ^^^^^^^^^^^^^^^^
|
warning: redundant else block
--> src/fs/dir.rs:124:18
|
124 | else {
| __________________^
125 | | return None
126 | | }
| |_____________^
|
warning: redundant else block
--> src/options/view.rs:60:18
|
60 | else {
| __________________^
61 | | // the --tree case is handled by the DirAction parser later
62 | | return Ok(Self::Details(details));
63 | | }
| |_____________^
|
warning: all variants have the same postfix: `Bytes`
--> src/output/table.rs:170:1
|
170 | / pub enum SizeFormat {
171 | |
172 | | /// Format the file size using **decimal** prefixes, such as “kilo”,
173 | | /// “mega”, or “giga”.
... |
181 | | JustBytes,
182 | | }
| |_^
|
warning: all variants have the same postfix: `Bytes`
--> src/output/table.rs:171:1
|
171 | / pub enum SizeFormat {
172 | |
173 | | /// Format the file size using **decimal** prefixes, such as “kilo”,
174 | | /// “mega”, or “giga”.
... |
182 | | JustBytes,
183 | | }
| |_^
|
warning: useless use of `format!`
--> src/options/mod.rs:181:50
|
181 | return Err(OptionsError::Unsupported(format!(
| __________________________________________________^
182 | | "Options --git and --git-ignore can't be used because `git` feature was disabled in this build of exa"
183 | | )));
| |_____________^ help: consider using `.to_string()`: `"Options --git and --git-ignore can't be used because `git` feature was disabled in this build of exa".to_string()`
|
warning: stripping a prefix manually
--> src/fs/filter.rs:287:33
|
287 | if n.starts_with('.') { &n[1..] }
| ^^^^^^^
|
warning: case-sensitive file extension comparison
--> src/info/filetype.rs:24:19
|
24 | file.name.ends_with(".ninja") ||
| ^^^^^^^^^^^^^^^^^^^
|
2021-04-30 15:37:31 +02:00
|
|
|
|
|
|
|
|
|
// the --tree case is handled by the DirAction parser later
|
|
|
|
|
return Ok(Self::Details(details));
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
|
|
|
|
|
Make View command-line args position-dependent
This commit changes the way the View (long mode, lines mode, grid mode, etc) is parsed from the command-line arguments.
Previously, it checked for long and long-grid, then tree, then lines, then grid, in that order, no matter which order the arguments were given in on the command-line. Now, it bases the view on whichever argument comes last in the list.
Unfortunately, the options-parsing code for Views is getting really complicated, but I can't see a way to simplify it while retaining the existing functionality.
It also links the parsing of DirAction to the result of parsing the View, so that you can't use tree mode if your view isn't Details. This is to fix an issue where `exa --tree --oneline` would just emit ".", because the DirAction was treating directories as files, and the argument was ".", and the View made it use lines view. Now, the --tree is ignored, as the view isn't Details.
Fixes GH-407 and GH-583.
2020-10-23 23:04:22 +01:00
|
|
|
|
Self::strict_check_long_flags(matches)?;
|
|
|
|
|
|
|
|
|
|
if flag.matches(&flags::TREE) {
|
|
|
|
|
let _ = matches.has(&flags::TREE)?;
|
|
|
|
|
let details = details::Options::deduce_tree(matches)?;
|
|
|
|
|
return Ok(Self::Details(details));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if flag.matches(&flags::ONE_LINE) {
|
|
|
|
|
let _ = matches.has(&flags::ONE_LINE)?;
|
2020-10-23 23:57:10 +01:00
|
|
|
|
return Ok(Self::Lines);
|
Make View command-line args position-dependent
This commit changes the way the View (long mode, lines mode, grid mode, etc) is parsed from the command-line arguments.
Previously, it checked for long and long-grid, then tree, then lines, then grid, in that order, no matter which order the arguments were given in on the command-line. Now, it bases the view on whichever argument comes last in the list.
Unfortunately, the options-parsing code for Views is getting really complicated, but I can't see a way to simplify it while retaining the existing functionality.
It also links the parsing of DirAction to the result of parsing the View, so that you can't use tree mode if your view isn't Details. This is to fix an issue where `exa --tree --oneline` would just emit ".", because the DirAction was treating directories as files, and the argument was ".", and the View made it use lines view. Now, the --tree is ignored, as the view isn't Details.
Fixes GH-407 and GH-583.
2020-10-23 23:04:22 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let grid = grid::Options::deduce(matches)?;
|
|
|
|
|
Ok(Self::Grid(grid))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn strict_check_long_flags(matches: &MatchedFlags<'_>) -> Result<(), OptionsError> {
|
2017-08-11 21:43:56 +01:00
|
|
|
|
// If --long hasn’t been passed, then check if we need to warn the
|
|
|
|
|
// user about flags that won’t have any effect.
|
|
|
|
|
if matches.is_strict() {
|
|
|
|
|
for option in &[ &flags::BINARY, &flags::BYTES, &flags::INODE, &flags::LINKS,
|
2021-03-31 21:46:24 +08:00
|
|
|
|
&flags::HEADER, &flags::BLOCKS, &flags::TIME, &flags::GROUP, &flags::NUMERIC ] {
|
2017-08-11 21:43:56 +01:00
|
|
|
|
if matches.has(option)? {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
return Err(OptionsError::Useless(*option, false, &flags::LONG));
|
2017-08-11 21:43:56 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-03 02:06:29 +01:00
|
|
|
|
if matches.has(&flags::GIT)? {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
return Err(OptionsError::Useless(&flags::GIT, false, &flags::LONG));
|
2017-08-11 21:43:56 +01:00
|
|
|
|
}
|
2020-10-10 19:49:46 +01:00
|
|
|
|
else if matches.has(&flags::LEVEL)? && ! matches.has(&flags::RECURSE)? && ! matches.has(&flags::TREE)? {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
return Err(OptionsError::Useless2(&flags::LEVEL, &flags::RECURSE, &flags::TREE));
|
2017-08-11 21:43:56 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-17 20:38:37 +01:00
|
|
|
|
|
Make View command-line args position-dependent
This commit changes the way the View (long mode, lines mode, grid mode, etc) is parsed from the command-line arguments.
Previously, it checked for long and long-grid, then tree, then lines, then grid, in that order, no matter which order the arguments were given in on the command-line. Now, it bases the view on whichever argument comes last in the list.
Unfortunately, the options-parsing code for Views is getting really complicated, but I can't see a way to simplify it while retaining the existing functionality.
It also links the parsing of DirAction to the result of parsing the View, so that you can't use tree mode if your view isn't Details. This is to fix an issue where `exa --tree --oneline` would just emit ".", because the DirAction was treating directories as files, and the argument was ".", and the View made it use lines view. Now, the --tree is ignored, as the view isn't Details.
Fixes GH-407 and GH-583.
2020-10-23 23:04:22 +01:00
|
|
|
|
Ok(())
|
Massive theming and view options refactor
This commit significantly refactors the way that options are parsed. It introduces the Theme type which contains both styling and extension configuration, converts the option-parsing process into a being a pure function, and removes some rather gnarly old code.
The main purpose of the refactoring is to fix GH-318, "Tests fail when not connected to a terminal". Even though exa was compiling fine on my machine and on Travis, it was failing for automated build scripts. This was because of what the option-parsing code was trying to accomplish: it wasn't just providing a struct of the user's settings, it was also checking the terminal, providing a View directly.
This has been changed so that the options module now _only_ looks at the command-line arguments and environment variables. Instead of returning a View, it returns the user's _preference_, and it's then up to the 'main' module to examine the terminal width and figure out if the view is doable, downgrading it if necessary.
The code that used to determine the view was horrible and I'm pleased it can be cut out. Also, the terminal width used to be in a lazy_static because it was queried multiple times, and now it's not in one because it's only queried once, which is a good sign for things going in the right direction.
There are also some naming and organisational changes around themes. The blanket terms "Colours" and "Styles" have been yeeted in favour of "Theme", which handles both extensions and UI colours. The FileStyle struct has been replaced with file_name::Options, making it similar to the views in how it has an Options struct and a Render struct.
Finally, eight unit tests have been removed because they turned out to be redundant (testing --colour and --color) after examining the tangled code, and the default theme has been put in its own file in preparation for more themes.
2020-10-22 22:34:00 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl grid::Options {
|
|
|
|
|
fn deduce(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> {
|
|
|
|
|
let grid = grid::Options {
|
|
|
|
|
across: matches.has(&flags::ACROSS)?,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Ok(grid)
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
Massive theming and view options refactor
This commit significantly refactors the way that options are parsed. It introduces the Theme type which contains both styling and extension configuration, converts the option-parsing process into a being a pure function, and removes some rather gnarly old code.
The main purpose of the refactoring is to fix GH-318, "Tests fail when not connected to a terminal". Even though exa was compiling fine on my machine and on Travis, it was failing for automated build scripts. This was because of what the option-parsing code was trying to accomplish: it wasn't just providing a struct of the user's settings, it was also checking the terminal, providing a View directly.
This has been changed so that the options module now _only_ looks at the command-line arguments and environment variables. Instead of returning a View, it returns the user's _preference_, and it's then up to the 'main' module to examine the terminal width and figure out if the view is doable, downgrading it if necessary.
The code that used to determine the view was horrible and I'm pleased it can be cut out. Also, the terminal width used to be in a lazy_static because it was queried multiple times, and now it's not in one because it's only queried once, which is a good sign for things going in the right direction.
There are also some naming and organisational changes around themes. The blanket terms "Colours" and "Styles" have been yeeted in favour of "Theme", which handles both extensions and UI colours. The FileStyle struct has been replaced with file_name::Options, making it similar to the views in how it has an Options struct and a Render struct.
Finally, eight unit tests have been removed because they turned out to be redundant (testing --colour and --color) after examining the tangled code, and the default theme has been put in its own file in preparation for more themes.
2020-10-22 22:34:00 +01:00
|
|
|
|
impl details::Options {
|
|
|
|
|
fn deduce_tree(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> {
|
|
|
|
|
let details = details::Options {
|
|
|
|
|
table: None,
|
|
|
|
|
header: false,
|
|
|
|
|
xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?,
|
|
|
|
|
};
|
2016-04-17 20:38:37 +01:00
|
|
|
|
|
Massive theming and view options refactor
This commit significantly refactors the way that options are parsed. It introduces the Theme type which contains both styling and extension configuration, converts the option-parsing process into a being a pure function, and removes some rather gnarly old code.
The main purpose of the refactoring is to fix GH-318, "Tests fail when not connected to a terminal". Even though exa was compiling fine on my machine and on Travis, it was failing for automated build scripts. This was because of what the option-parsing code was trying to accomplish: it wasn't just providing a struct of the user's settings, it was also checking the terminal, providing a View directly.
This has been changed so that the options module now _only_ looks at the command-line arguments and environment variables. Instead of returning a View, it returns the user's _preference_, and it's then up to the 'main' module to examine the terminal width and figure out if the view is doable, downgrading it if necessary.
The code that used to determine the view was horrible and I'm pleased it can be cut out. Also, the terminal width used to be in a lazy_static because it was queried multiple times, and now it's not in one because it's only queried once, which is a good sign for things going in the right direction.
There are also some naming and organisational changes around themes. The blanket terms "Colours" and "Styles" have been yeeted in favour of "Theme", which handles both extensions and UI colours. The FileStyle struct has been replaced with file_name::Options, making it similar to the views in how it has an Options struct and a Render struct.
Finally, eight unit tests have been removed because they turned out to be redundant (testing --colour and --color) after examining the tangled code, and the default theme has been put in its own file in preparation for more themes.
2020-10-22 22:34:00 +01:00
|
|
|
|
Ok(details)
|
|
|
|
|
}
|
2016-04-17 20:38:37 +01:00
|
|
|
|
|
Massive theming and view options refactor
This commit significantly refactors the way that options are parsed. It introduces the Theme type which contains both styling and extension configuration, converts the option-parsing process into a being a pure function, and removes some rather gnarly old code.
The main purpose of the refactoring is to fix GH-318, "Tests fail when not connected to a terminal". Even though exa was compiling fine on my machine and on Travis, it was failing for automated build scripts. This was because of what the option-parsing code was trying to accomplish: it wasn't just providing a struct of the user's settings, it was also checking the terminal, providing a View directly.
This has been changed so that the options module now _only_ looks at the command-line arguments and environment variables. Instead of returning a View, it returns the user's _preference_, and it's then up to the 'main' module to examine the terminal width and figure out if the view is doable, downgrading it if necessary.
The code that used to determine the view was horrible and I'm pleased it can be cut out. Also, the terminal width used to be in a lazy_static because it was queried multiple times, and now it's not in one because it's only queried once, which is a good sign for things going in the right direction.
There are also some naming and organisational changes around themes. The blanket terms "Colours" and "Styles" have been yeeted in favour of "Theme", which handles both extensions and UI colours. The FileStyle struct has been replaced with file_name::Options, making it similar to the views in how it has an Options struct and a Render struct.
Finally, eight unit tests have been removed because they turned out to be redundant (testing --colour and --color) after examining the tangled code, and the default theme has been put in its own file in preparation for more themes.
2020-10-22 22:34:00 +01:00
|
|
|
|
fn deduce_long<V: Vars>(matches: &MatchedFlags<'_>, vars: &V) -> Result<Self, OptionsError> {
|
|
|
|
|
if matches.is_strict() {
|
|
|
|
|
if matches.has(&flags::ACROSS)? && ! matches.has(&flags::GRID)? {
|
|
|
|
|
return Err(OptionsError::Useless(&flags::ACROSS, true, &flags::LONG));
|
|
|
|
|
}
|
|
|
|
|
else if matches.has(&flags::ONE_LINE)? {
|
|
|
|
|
return Err(OptionsError::Useless(&flags::ONE_LINE, true, &flags::LONG));
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-17 20:38:37 +01:00
|
|
|
|
|
Massive theming and view options refactor
This commit significantly refactors the way that options are parsed. It introduces the Theme type which contains both styling and extension configuration, converts the option-parsing process into a being a pure function, and removes some rather gnarly old code.
The main purpose of the refactoring is to fix GH-318, "Tests fail when not connected to a terminal". Even though exa was compiling fine on my machine and on Travis, it was failing for automated build scripts. This was because of what the option-parsing code was trying to accomplish: it wasn't just providing a struct of the user's settings, it was also checking the terminal, providing a View directly.
This has been changed so that the options module now _only_ looks at the command-line arguments and environment variables. Instead of returning a View, it returns the user's _preference_, and it's then up to the 'main' module to examine the terminal width and figure out if the view is doable, downgrading it if necessary.
The code that used to determine the view was horrible and I'm pleased it can be cut out. Also, the terminal width used to be in a lazy_static because it was queried multiple times, and now it's not in one because it's only queried once, which is a good sign for things going in the right direction.
There are also some naming and organisational changes around themes. The blanket terms "Colours" and "Styles" have been yeeted in favour of "Theme", which handles both extensions and UI colours. The FileStyle struct has been replaced with file_name::Options, making it similar to the views in how it has an Options struct and a Render struct.
Finally, eight unit tests have been removed because they turned out to be redundant (testing --colour and --color) after examining the tangled code, and the default theme has been put in its own file in preparation for more themes.
2020-10-22 22:34:00 +01:00
|
|
|
|
Ok(details::Options {
|
|
|
|
|
table: Some(TableOptions::deduce(matches, vars)?),
|
|
|
|
|
header: matches.has(&flags::HEADER)?,
|
|
|
|
|
xattr: xattr::ENABLED && matches.has(&flags::EXTENDED)?,
|
|
|
|
|
})
|
|
|
|
|
}
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
Massive theming and view options refactor
This commit significantly refactors the way that options are parsed. It introduces the Theme type which contains both styling and extension configuration, converts the option-parsing process into a being a pure function, and removes some rather gnarly old code.
The main purpose of the refactoring is to fix GH-318, "Tests fail when not connected to a terminal". Even though exa was compiling fine on my machine and on Travis, it was failing for automated build scripts. This was because of what the option-parsing code was trying to accomplish: it wasn't just providing a struct of the user's settings, it was also checking the terminal, providing a View directly.
This has been changed so that the options module now _only_ looks at the command-line arguments and environment variables. Instead of returning a View, it returns the user's _preference_, and it's then up to the 'main' module to examine the terminal width and figure out if the view is doable, downgrading it if necessary.
The code that used to determine the view was horrible and I'm pleased it can be cut out. Also, the terminal width used to be in a lazy_static because it was queried multiple times, and now it's not in one because it's only queried once, which is a good sign for things going in the right direction.
There are also some naming and organisational changes around themes. The blanket terms "Colours" and "Styles" have been yeeted in favour of "Theme", which handles both extensions and UI colours. The FileStyle struct has been replaced with file_name::Options, making it similar to the views in how it has an Options struct and a Render struct.
Finally, eight unit tests have been removed because they turned out to be redundant (testing --colour and --color) after examining the tangled code, and the default theme has been put in its own file in preparation for more themes.
2020-10-22 22:34:00 +01:00
|
|
|
|
impl TerminalWidth {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
fn deduce<V: Vars>(vars: &V) -> Result<Self, OptionsError> {
|
2018-12-08 00:43:31 +01:00
|
|
|
|
use crate::options::vars;
|
2017-08-26 21:19:06 +01:00
|
|
|
|
|
|
|
|
|
if let Some(columns) = vars.get(vars::COLUMNS).and_then(|s| s.into_string().ok()) {
|
2016-04-17 20:38:37 +01:00
|
|
|
|
match columns.parse() {
|
2021-04-12 21:42:45 +01:00
|
|
|
|
Ok(width) => {
|
|
|
|
|
Ok(Self::Set(width))
|
|
|
|
|
}
|
|
|
|
|
Err(e) => {
|
|
|
|
|
let source = NumberSource::Env(vars::COLUMNS);
|
|
|
|
|
Err(OptionsError::FailedParse(columns, source, e))
|
|
|
|
|
}
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
Massive theming and view options refactor
This commit significantly refactors the way that options are parsed. It introduces the Theme type which contains both styling and extension configuration, converts the option-parsing process into a being a pure function, and removes some rather gnarly old code.
The main purpose of the refactoring is to fix GH-318, "Tests fail when not connected to a terminal". Even though exa was compiling fine on my machine and on Travis, it was failing for automated build scripts. This was because of what the option-parsing code was trying to accomplish: it wasn't just providing a struct of the user's settings, it was also checking the terminal, providing a View directly.
This has been changed so that the options module now _only_ looks at the command-line arguments and environment variables. Instead of returning a View, it returns the user's _preference_, and it's then up to the 'main' module to examine the terminal width and figure out if the view is doable, downgrading it if necessary.
The code that used to determine the view was horrible and I'm pleased it can be cut out. Also, the terminal width used to be in a lazy_static because it was queried multiple times, and now it's not in one because it's only queried once, which is a good sign for things going in the right direction.
There are also some naming and organisational changes around themes. The blanket terms "Colours" and "Styles" have been yeeted in favour of "Theme", which handles both extensions and UI colours. The FileStyle struct has been replaced with file_name::Options, making it similar to the views in how it has an Options struct and a Render struct.
Finally, eight unit tests have been removed because they turned out to be redundant (testing --colour and --color) after examining the tangled code, and the default theme has been put in its own file in preparation for more themes.
2020-10-22 22:34:00 +01:00
|
|
|
|
Ok(Self::Automatic)
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-08-13 11:15:40 +01:00
|
|
|
|
impl RowThreshold {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
fn deduce<V: Vars>(vars: &V) -> Result<Self, OptionsError> {
|
2018-12-08 00:43:31 +01:00
|
|
|
|
use crate::options::vars;
|
2017-08-26 21:19:06 +01:00
|
|
|
|
|
|
|
|
|
if let Some(columns) = vars.get(vars::EXA_GRID_ROWS).and_then(|s| s.into_string().ok()) {
|
2017-08-13 11:15:40 +01:00
|
|
|
|
match columns.parse() {
|
2021-04-12 21:42:45 +01:00
|
|
|
|
Ok(rows) => {
|
|
|
|
|
Ok(Self::MinimumRows(rows))
|
|
|
|
|
}
|
|
|
|
|
Err(e) => {
|
|
|
|
|
let source = NumberSource::Env(vars::EXA_GRID_ROWS);
|
|
|
|
|
Err(OptionsError::FailedParse(columns, source, e))
|
|
|
|
|
}
|
2017-08-13 11:15:40 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
2020-10-10 13:55:26 +01:00
|
|
|
|
Ok(Self::AlwaysGrid)
|
2017-08-13 11:15:40 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-07-05 20:16:04 +01:00
|
|
|
|
impl TableOptions {
|
2020-10-13 01:36:41 +01:00
|
|
|
|
fn deduce<V: Vars>(matches: &MatchedFlags<'_>, vars: &V) -> Result<Self, OptionsError> {
|
2018-06-15 04:38:32 +09:00
|
|
|
|
let time_format = TimeFormat::deduce(matches, vars)?;
|
2017-08-09 22:25:16 +01:00
|
|
|
|
let size_format = SizeFormat::deduce(matches)?;
|
2021-03-19 08:46:03 +08:00
|
|
|
|
let user_format = UserFormat::deduce(matches)?;
|
2019-08-29 14:34:30 +02:00
|
|
|
|
let columns = Columns::deduce(matches)?;
|
2021-03-19 08:46:03 +08:00
|
|
|
|
Ok(Self { time_format, size_format, columns , user_format})
|
2017-08-09 22:25:16 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl Columns {
|
2020-10-13 01:36:41 +01:00
|
|
|
|
fn deduce(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> {
|
2017-08-09 22:25:16 +01:00
|
|
|
|
let time_types = TimeTypes::deduce(matches)?;
|
2020-12-03 02:06:29 +01:00
|
|
|
|
let git = matches.has(&flags::GIT)?;
|
2017-08-09 22:25:16 +01:00
|
|
|
|
|
|
|
|
|
let blocks = matches.has(&flags::BLOCKS)?;
|
|
|
|
|
let group = matches.has(&flags::GROUP)?;
|
|
|
|
|
let inode = matches.has(&flags::INODE)?;
|
|
|
|
|
let links = matches.has(&flags::LINKS)?;
|
2020-07-24 13:47:34 +02:00
|
|
|
|
let octal = matches.has(&flags::OCTAL)?;
|
2017-08-09 22:25:16 +01:00
|
|
|
|
|
2020-10-10 19:49:46 +01:00
|
|
|
|
let permissions = ! matches.has(&flags::NO_PERMISSIONS)?;
|
|
|
|
|
let filesize = ! matches.has(&flags::NO_FILESIZE)?;
|
|
|
|
|
let user = ! matches.has(&flags::NO_USER)?;
|
2019-08-29 14:34:30 +02:00
|
|
|
|
|
2020-10-10 13:55:26 +01:00
|
|
|
|
Ok(Self { time_types, git, octal, blocks, group, inode, links, permissions, filesize, user })
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl SizeFormat {
|
|
|
|
|
|
|
|
|
|
/// Determine which file size to use in the file size column based on
|
|
|
|
|
/// the user’s options.
|
|
|
|
|
///
|
|
|
|
|
/// The default mode is to use the decimal prefixes, as they are the
|
|
|
|
|
/// most commonly-understood, and don’t involve trying to parse large
|
|
|
|
|
/// strings of digits in your head. Changing the format to anything else
|
|
|
|
|
/// involves the `--binary` or `--bytes` flags, and these conflict with
|
|
|
|
|
/// each other.
|
2020-10-13 01:36:41 +01:00
|
|
|
|
fn deduce(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> {
|
2017-08-09 19:18:31 +01:00
|
|
|
|
let flag = matches.has_where(|f| f.matches(&flags::BINARY) || f.matches(&flags::BYTES))?;
|
|
|
|
|
|
|
|
|
|
Ok(match flag {
|
2020-10-10 13:55:26 +01:00
|
|
|
|
Some(f) if f.matches(&flags::BINARY) => Self::BinaryBytes,
|
|
|
|
|
Some(f) if f.matches(&flags::BYTES) => Self::JustBytes,
|
|
|
|
|
_ => Self::DecimalBytes,
|
2017-08-09 19:18:31 +01:00
|
|
|
|
})
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-07-05 23:27:48 +01:00
|
|
|
|
impl TimeFormat {
|
|
|
|
|
|
|
|
|
|
/// Determine how time should be formatted in timestamp columns.
|
2020-10-13 01:36:41 +01:00
|
|
|
|
fn deduce<V: Vars>(matches: &MatchedFlags<'_>, vars: &V) -> Result<Self, OptionsError> {
|
2020-10-13 01:46:17 +01:00
|
|
|
|
let word =
|
|
|
|
|
if let Some(w) = matches.get(&flags::TIME_STYLE)? {
|
2020-10-10 19:49:46 +01:00
|
|
|
|
w.to_os_string()
|
|
|
|
|
}
|
2020-10-13 01:46:17 +01:00
|
|
|
|
else {
|
2018-12-08 00:43:31 +01:00
|
|
|
|
use crate::options::vars;
|
2018-06-15 04:38:32 +09:00
|
|
|
|
match vars.get(vars::TIME_STYLE) {
|
2020-10-10 19:49:46 +01:00
|
|
|
|
Some(ref t) if ! t.is_empty() => t.clone(),
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
_ => return Ok(Self::DefaultFormat)
|
2018-06-15 04:38:32 +09:00
|
|
|
|
}
|
2020-10-13 01:46:17 +01:00
|
|
|
|
};
|
2017-07-26 17:48:18 +01:00
|
|
|
|
|
2018-06-15 04:38:32 +09:00
|
|
|
|
if &word == "default" {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
Ok(Self::DefaultFormat)
|
2017-07-26 17:48:18 +01:00
|
|
|
|
}
|
2018-06-15 04:38:32 +09:00
|
|
|
|
else if &word == "iso" {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
Ok(Self::ISOFormat)
|
2017-07-26 17:48:18 +01:00
|
|
|
|
}
|
2018-06-15 04:38:32 +09:00
|
|
|
|
else if &word == "long-iso" {
|
2020-10-10 13:55:26 +01:00
|
|
|
|
Ok(Self::LongISO)
|
2017-07-26 17:48:18 +01:00
|
|
|
|
}
|
2018-06-15 04:38:32 +09:00
|
|
|
|
else if &word == "full-iso" {
|
2020-10-10 13:55:26 +01:00
|
|
|
|
Ok(Self::FullISO)
|
2017-07-06 00:01:45 +01:00
|
|
|
|
}
|
|
|
|
|
else {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
Err(OptionsError::BadArgument(&flags::TIME_STYLE, word))
|
2017-07-06 00:01:45 +01:00
|
|
|
|
}
|
2017-07-05 23:27:48 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-03-19 08:46:03 +08:00
|
|
|
|
impl UserFormat {
|
|
|
|
|
fn deduce(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> {
|
2021-03-31 21:46:24 +08:00
|
|
|
|
let flag = matches.has(&flags::NUMERIC)?;
|
2021-03-19 08:46:03 +08:00
|
|
|
|
Ok(if flag { Self::Numeric } else { Self::Name })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-05 23:27:48 +01:00
|
|
|
|
|
2016-04-17 20:38:37 +01:00
|
|
|
|
impl TimeTypes {
|
|
|
|
|
|
|
|
|
|
/// Determine which of a file’s time fields should be displayed for it
|
|
|
|
|
/// based on the user’s options.
|
|
|
|
|
///
|
|
|
|
|
/// There are two separate ways to pick which fields to show: with a
|
|
|
|
|
/// flag (such as `--modified`) or with a parameter (such as
|
|
|
|
|
/// `--time=modified`). An error is signaled if both ways are used.
|
|
|
|
|
///
|
|
|
|
|
/// It’s valid to show more than one column by passing in more than one
|
|
|
|
|
/// option, but passing *no* options means that the user just wants to
|
|
|
|
|
/// see the default set.
|
2020-10-13 01:36:41 +01:00
|
|
|
|
fn deduce(matches: &MatchedFlags<'_>) -> Result<Self, OptionsError> {
|
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 09:21:29 +01:00
|
|
|
|
let possible_word = matches.get(&flags::TIME)?;
|
|
|
|
|
let modified = matches.has(&flags::MODIFIED)?;
|
2018-12-17 05:46:50 +01:00
|
|
|
|
let changed = matches.has(&flags::CHANGED)?;
|
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 09:21:29 +01:00
|
|
|
|
let accessed = matches.has(&flags::ACCESSED)?;
|
2018-12-17 05:46:50 +01:00
|
|
|
|
let created = matches.has(&flags::CREATED)?;
|
2016-04-17 20:38:37 +01:00
|
|
|
|
|
2019-08-29 14:34:30 +02:00
|
|
|
|
let no_time = matches.has(&flags::NO_TIME)?;
|
|
|
|
|
|
|
|
|
|
let time_types = if no_time {
|
2020-10-10 13:55:26 +01:00
|
|
|
|
Self { modified: false, changed: false, accessed: false, created: false }
|
2019-08-29 14:34:30 +02:00
|
|
|
|
} else if let Some(word) = possible_word {
|
2016-04-17 20:38:37 +01:00
|
|
|
|
if modified {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
return Err(OptionsError::Useless(&flags::MODIFIED, true, &flags::TIME));
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
2018-12-17 05:46:50 +01:00
|
|
|
|
else if changed {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
return Err(OptionsError::Useless(&flags::CHANGED, true, &flags::TIME));
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
|
|
|
|
else if accessed {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
return Err(OptionsError::Useless(&flags::ACCESSED, true, &flags::TIME));
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
2018-12-17 05:46:50 +01:00
|
|
|
|
else if created {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
return Err(OptionsError::Useless(&flags::CREATED, true, &flags::TIME));
|
2018-12-17 05:46:50 +01:00
|
|
|
|
}
|
2017-08-05 11:55:41 +01:00
|
|
|
|
else if word == "mod" || word == "modified" {
|
2020-10-10 13:55:26 +01:00
|
|
|
|
Self { modified: true, changed: false, accessed: false, created: false }
|
2018-12-17 05:46:50 +01:00
|
|
|
|
}
|
|
|
|
|
else if word == "ch" || word == "changed" {
|
2020-10-10 13:55:26 +01:00
|
|
|
|
Self { modified: false, changed: true, accessed: false, created: false }
|
2017-07-26 17:48:18 +01:00
|
|
|
|
}
|
|
|
|
|
else if word == "acc" || word == "accessed" {
|
2020-10-10 13:55:26 +01:00
|
|
|
|
Self { modified: false, changed: false, accessed: true, created: false }
|
2017-07-26 17:48:18 +01:00
|
|
|
|
}
|
|
|
|
|
else if word == "cr" || word == "created" {
|
2020-10-10 13:55:26 +01:00
|
|
|
|
Self { modified: false, changed: false, accessed: false, created: true }
|
2017-07-26 17:48:18 +01:00
|
|
|
|
}
|
|
|
|
|
else {
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
return Err(OptionsError::BadArgument(&flags::TIME, word.into()));
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-12-17 05:46:50 +01:00
|
|
|
|
else if modified || changed || accessed || created {
|
2020-10-10 13:55:26 +01:00
|
|
|
|
Self { modified, changed, accessed, created }
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
|
|
|
|
else {
|
2020-10-10 13:55:26 +01:00
|
|
|
|
Self::default()
|
2018-12-17 05:48:49 +01:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Ok(time_types)
|
2016-04-17 20:38:37 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-07-26 23:05:45 +01:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod test {
|
|
|
|
|
use super::*;
|
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 09:21:29 +01:00
|
|
|
|
use std::ffi::OsString;
|
2018-12-08 00:43:31 +01:00
|
|
|
|
use crate::options::flags;
|
|
|
|
|
use crate::options::parser::{Flag, Arg};
|
2017-08-09 17:14:16 +01:00
|
|
|
|
|
2018-12-08 00:43:31 +01:00
|
|
|
|
use crate::options::test::parse_for_test;
|
|
|
|
|
use crate::options::test::Strictnesses::*;
|
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 09:21:29 +01:00
|
|
|
|
|
2017-08-09 17:14:16 +01:00
|
|
|
|
static TEST_ARGS: &[&Arg] = &[ &flags::BINARY, &flags::BYTES, &flags::TIME_STYLE,
|
2018-12-17 11:05:25 +01:00
|
|
|
|
&flags::TIME, &flags::MODIFIED, &flags::CHANGED,
|
2020-10-23 23:57:10 +01:00
|
|
|
|
&flags::CREATED, &flags::ACCESSED,
|
2017-08-11 21:43:56 +01:00
|
|
|
|
&flags::HEADER, &flags::GROUP, &flags::INODE, &flags::GIT,
|
|
|
|
|
&flags::LINKS, &flags::BLOCKS, &flags::LONG, &flags::LEVEL,
|
2021-03-28 18:30:01 +08:00
|
|
|
|
&flags::GRID, &flags::ACROSS, &flags::ONE_LINE, &flags::TREE,
|
2021-03-31 21:46:24 +08:00
|
|
|
|
&flags::NUMERIC ];
|
2017-08-09 17:14:16 +01:00
|
|
|
|
|
2017-07-26 23:05:45 +01:00
|
|
|
|
macro_rules! test {
|
2017-08-10 13:52:49 +01: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 09:21:29 +01:00
|
|
|
|
($name:ident: $type:ident <- $inputs:expr; $stricts:expr => $result:expr) => {
|
2017-08-10 13:52:49 +01:00
|
|
|
|
/// Macro that writes a test.
|
|
|
|
|
/// If testing both strictnesses, they’ll both be done in the same function.
|
2017-07-26 23:05:45 +01:00
|
|
|
|
#[test]
|
|
|
|
|
fn $name() {
|
2017-08-09 13:36:06 +01:00
|
|
|
|
for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf)) {
|
|
|
|
|
assert_eq!(result, $result);
|
|
|
|
|
}
|
2017-07-26 23:05:45 +01:00
|
|
|
|
}
|
|
|
|
|
};
|
2017-08-09 17:14:16 +01:00
|
|
|
|
|
2017-08-10 13:52:49 +01:00
|
|
|
|
($name:ident: $type:ident <- $inputs:expr; $stricts:expr => err $result:expr) => {
|
|
|
|
|
/// Special macro for testing Err results.
|
|
|
|
|
/// This is needed because sometimes the Ok type doesn’t implement PartialEq.
|
|
|
|
|
#[test]
|
|
|
|
|
fn $name() {
|
|
|
|
|
for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf)) {
|
|
|
|
|
assert_eq!(result.unwrap_err(), $result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-08-09 17:14:16 +01:00
|
|
|
|
($name:ident: $type:ident <- $inputs:expr; $stricts:expr => like $pat:pat) => {
|
2017-08-10 13:52:49 +01:00
|
|
|
|
/// More general macro for testing against a pattern.
|
|
|
|
|
/// Instead of using PartialEq, this just tests if it matches a pat.
|
2017-08-09 17:14:16 +01:00
|
|
|
|
#[test]
|
|
|
|
|
fn $name() {
|
|
|
|
|
for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf)) {
|
|
|
|
|
println!("Testing {:?}", result);
|
|
|
|
|
match result {
|
|
|
|
|
$pat => assert!(true),
|
|
|
|
|
_ => assert!(false),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2017-08-10 17:54:28 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
($name:ident: $type:ident <- $inputs:expr, $vars:expr; $stricts:expr => err $result:expr) => {
|
|
|
|
|
/// Like above, but with $vars.
|
|
|
|
|
#[test]
|
|
|
|
|
fn $name() {
|
2017-08-13 11:14:58 +01:00
|
|
|
|
for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf, &$vars)) {
|
2017-08-10 17:54:28 +01:00
|
|
|
|
assert_eq!(result.unwrap_err(), $result);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
($name:ident: $type:ident <- $inputs:expr, $vars:expr; $stricts:expr => like $pat:pat) => {
|
|
|
|
|
/// Like further above, but with $vars.
|
|
|
|
|
#[test]
|
|
|
|
|
fn $name() {
|
2017-08-13 11:14:58 +01:00
|
|
|
|
for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf, &$vars)) {
|
2017-08-10 17:54:28 +01:00
|
|
|
|
println!("Testing {:?}", result);
|
|
|
|
|
match result {
|
|
|
|
|
$pat => assert!(true),
|
|
|
|
|
_ => assert!(false),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2017-07-26 23:05:45 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-26 23:37:58 +01:00
|
|
|
|
|
2017-07-26 23:05:45 +01:00
|
|
|
|
mod size_formats {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
2017-08-09 17:14:16 +01: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 09:21:29 +01:00
|
|
|
|
test!(empty: SizeFormat <- []; Both => Ok(SizeFormat::DecimalBytes));
|
2017-08-09 17:14:16 +01:00
|
|
|
|
|
|
|
|
|
// Individual flags
|
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 09:21:29 +01:00
|
|
|
|
test!(binary: SizeFormat <- ["--binary"]; Both => Ok(SizeFormat::BinaryBytes));
|
|
|
|
|
test!(bytes: SizeFormat <- ["--bytes"]; Both => Ok(SizeFormat::JustBytes));
|
2017-08-09 17:14:16 +01:00
|
|
|
|
|
2017-08-09 19:18:31 +01:00
|
|
|
|
// Overriding
|
|
|
|
|
test!(both_1: SizeFormat <- ["--binary", "--binary"]; Last => Ok(SizeFormat::BinaryBytes));
|
|
|
|
|
test!(both_2: SizeFormat <- ["--bytes", "--binary"]; Last => Ok(SizeFormat::BinaryBytes));
|
|
|
|
|
test!(both_3: SizeFormat <- ["--binary", "--bytes"]; Last => Ok(SizeFormat::JustBytes));
|
|
|
|
|
test!(both_4: SizeFormat <- ["--bytes", "--bytes"]; Last => Ok(SizeFormat::JustBytes));
|
|
|
|
|
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
test!(both_5: SizeFormat <- ["--binary", "--binary"]; Complain => err OptionsError::Duplicate(Flag::Long("binary"), Flag::Long("binary")));
|
|
|
|
|
test!(both_6: SizeFormat <- ["--bytes", "--binary"]; Complain => err OptionsError::Duplicate(Flag::Long("bytes"), Flag::Long("binary")));
|
|
|
|
|
test!(both_7: SizeFormat <- ["--binary", "--bytes"]; Complain => err OptionsError::Duplicate(Flag::Long("binary"), Flag::Long("bytes")));
|
|
|
|
|
test!(both_8: SizeFormat <- ["--bytes", "--bytes"]; Complain => err OptionsError::Duplicate(Flag::Long("bytes"), Flag::Long("bytes")));
|
2017-07-26 23:05:45 +01:00
|
|
|
|
}
|
2017-07-26 23:37:58 +01:00
|
|
|
|
|
|
|
|
|
|
2017-08-09 17:14:16 +01:00
|
|
|
|
mod time_formats {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
// These tests use pattern matching because TimeFormat doesn’t
|
|
|
|
|
// implement PartialEq.
|
|
|
|
|
|
|
|
|
|
// Default behaviour
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
test!(empty: TimeFormat <- [], None; Both => like Ok(TimeFormat::DefaultFormat));
|
2017-08-09 17:14:16 +01:00
|
|
|
|
|
|
|
|
|
// Individual settings
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
test!(default: TimeFormat <- ["--time-style=default"], None; Both => like Ok(TimeFormat::DefaultFormat));
|
|
|
|
|
test!(iso: TimeFormat <- ["--time-style", "iso"], None; Both => like Ok(TimeFormat::ISOFormat));
|
2018-06-15 04:38:32 +09:00
|
|
|
|
test!(long_iso: TimeFormat <- ["--time-style=long-iso"], None; Both => like Ok(TimeFormat::LongISO));
|
|
|
|
|
test!(full_iso: TimeFormat <- ["--time-style", "full-iso"], None; Both => like Ok(TimeFormat::FullISO));
|
2017-08-09 17:14:16 +01:00
|
|
|
|
|
|
|
|
|
// Overriding
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
test!(actually: TimeFormat <- ["--time-style=default", "--time-style", "iso"], None; Last => like Ok(TimeFormat::ISOFormat));
|
|
|
|
|
test!(actual_2: TimeFormat <- ["--time-style=default", "--time-style", "iso"], None; Complain => err OptionsError::Duplicate(Flag::Long("time-style"), Flag::Long("time-style")));
|
2017-08-09 17:14:16 +01:00
|
|
|
|
|
2018-06-15 04:38:32 +09:00
|
|
|
|
test!(nevermind: TimeFormat <- ["--time-style", "long-iso", "--time-style=full-iso"], None; Last => like Ok(TimeFormat::FullISO));
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
test!(nevermore: TimeFormat <- ["--time-style", "long-iso", "--time-style=full-iso"], None; Complain => err OptionsError::Duplicate(Flag::Long("time-style"), Flag::Long("time-style")));
|
2017-08-09 17:14:16 +01:00
|
|
|
|
|
|
|
|
|
// Errors
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
test!(daily: TimeFormat <- ["--time-style=24-hour"], None; Both => err OptionsError::BadArgument(&flags::TIME_STYLE, OsString::from("24-hour")));
|
2018-06-15 04:38:32 +09:00
|
|
|
|
|
|
|
|
|
// `TIME_STYLE` environment variable is defined.
|
|
|
|
|
// If the time-style argument is not given, `TIME_STYLE` is used.
|
|
|
|
|
test!(use_env: TimeFormat <- [], Some("long-iso".into()); Both => like Ok(TimeFormat::LongISO));
|
|
|
|
|
|
|
|
|
|
// If the time-style argument is given, `TIME_STYLE` is overriding.
|
|
|
|
|
test!(override_env: TimeFormat <- ["--time-style=full-iso"], Some("long-iso".into()); Both => like Ok(TimeFormat::FullISO));
|
2017-08-09 17:14:16 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-07-26 23:37:58 +01:00
|
|
|
|
mod time_types {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
// 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 09:21:29 +01:00
|
|
|
|
test!(empty: TimeTypes <- []; Both => Ok(TimeTypes::default()));
|
2017-08-09 13:36:06 +01:00
|
|
|
|
|
|
|
|
|
// Modified
|
2018-12-17 11:05:25 +01:00
|
|
|
|
test!(modified: TimeTypes <- ["--modified"]; Both => Ok(TimeTypes { modified: true, changed: false, accessed: false, created: false }));
|
|
|
|
|
test!(m: TimeTypes <- ["-m"]; Both => Ok(TimeTypes { modified: true, changed: false, accessed: false, created: false }));
|
|
|
|
|
test!(time_mod: TimeTypes <- ["--time=modified"]; Both => Ok(TimeTypes { modified: true, changed: false, accessed: false, created: false }));
|
2019-07-15 03:37:05 +01:00
|
|
|
|
test!(t_m: TimeTypes <- ["-tmod"]; Both => Ok(TimeTypes { modified: true, changed: false, accessed: false, created: false }));
|
2018-12-17 11:05:25 +01:00
|
|
|
|
|
|
|
|
|
// Changed
|
|
|
|
|
#[cfg(target_family = "unix")]
|
|
|
|
|
test!(changed: TimeTypes <- ["--changed"]; Both => Ok(TimeTypes { modified: false, changed: true, accessed: false, created: false }));
|
|
|
|
|
#[cfg(target_family = "unix")]
|
|
|
|
|
test!(time_ch: TimeTypes <- ["--time=changed"]; Both => Ok(TimeTypes { modified: false, changed: true, accessed: false, created: false }));
|
|
|
|
|
#[cfg(target_family = "unix")]
|
2020-10-20 22:42:04 +01:00
|
|
|
|
test!(t_ch: TimeTypes <- ["-t", "ch"]; Both => Ok(TimeTypes { modified: false, changed: true, accessed: false, created: false }));
|
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 09:21:29 +01:00
|
|
|
|
|
2017-08-09 13:36:06 +01:00
|
|
|
|
// Accessed
|
2018-12-17 11:05:25 +01:00
|
|
|
|
test!(acc: TimeTypes <- ["--accessed"]; Both => Ok(TimeTypes { modified: false, changed: false, accessed: true, created: false }));
|
|
|
|
|
test!(a: TimeTypes <- ["-u"]; Both => Ok(TimeTypes { modified: false, changed: false, accessed: true, created: false }));
|
|
|
|
|
test!(time_acc: TimeTypes <- ["--time", "accessed"]; Both => Ok(TimeTypes { modified: false, changed: false, accessed: true, created: false }));
|
|
|
|
|
test!(time_a: TimeTypes <- ["-t", "acc"]; Both => Ok(TimeTypes { modified: false, changed: false, accessed: true, created: false }));
|
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 09:21:29 +01:00
|
|
|
|
|
2017-08-09 13:36:06 +01:00
|
|
|
|
// Created
|
2018-12-17 11:05:25 +01:00
|
|
|
|
test!(cr: TimeTypes <- ["--created"]; Both => Ok(TimeTypes { modified: false, changed: false, accessed: false, created: true }));
|
|
|
|
|
test!(c: TimeTypes <- ["-U"]; Both => Ok(TimeTypes { modified: false, changed: false, accessed: false, created: true }));
|
|
|
|
|
test!(time_cr: TimeTypes <- ["--time=created"]; Both => Ok(TimeTypes { modified: false, changed: false, accessed: false, created: true }));
|
2019-07-15 03:37:05 +01:00
|
|
|
|
test!(t_cr: TimeTypes <- ["-tcr"]; Both => Ok(TimeTypes { modified: false, changed: false, accessed: false, created: true }));
|
2017-07-26 23:37:58 +01:00
|
|
|
|
|
|
|
|
|
// Multiples
|
2020-10-20 22:42:04 +01:00
|
|
|
|
test!(time_uu: TimeTypes <- ["-u", "--modified"]; Both => Ok(TimeTypes { modified: true, changed: false, accessed: true, created: false }));
|
2018-12-17 11:05:25 +01: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 09:21:29 +01:00
|
|
|
|
|
|
|
|
|
// Errors
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
test!(time_tea: TimeTypes <- ["--time=tea"]; Both => err OptionsError::BadArgument(&flags::TIME, OsString::from("tea")));
|
|
|
|
|
test!(t_ea: TimeTypes <- ["-tea"]; Both => err OptionsError::BadArgument(&flags::TIME, OsString::from("ea")));
|
2017-07-26 23:37:58 +01:00
|
|
|
|
|
|
|
|
|
// Overriding
|
2018-12-17 11:05:25 +01:00
|
|
|
|
test!(overridden: TimeTypes <- ["-tcr", "-tmod"]; Last => Ok(TimeTypes { modified: true, changed: false, accessed: false, created: false }));
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
test!(overridden_2: TimeTypes <- ["-tcr", "-tmod"]; Complain => err OptionsError::Duplicate(Flag::Short(b't'), Flag::Short(b't')));
|
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 09:21:29 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2017-08-10 13:59:39 +01:00
|
|
|
|
mod views {
|
|
|
|
|
use super::*;
|
2018-12-08 00:43:31 +01:00
|
|
|
|
|
|
|
|
|
use crate::output::grid::Options as GridOptions;
|
|
|
|
|
|
2017-08-10 13:59:39 +01:00
|
|
|
|
|
2017-08-10 17:54:28 +01:00
|
|
|
|
// Default
|
|
|
|
|
test!(empty: Mode <- [], None; Both => like Ok(Mode::Grid(_)));
|
|
|
|
|
|
|
|
|
|
// Grid views
|
2020-10-20 22:42:04 +01:00
|
|
|
|
test!(original_g: Mode <- ["-G"], None; Both => like Ok(Mode::Grid(GridOptions { across: false, .. })));
|
|
|
|
|
test!(grid: Mode <- ["--grid"], None; Both => like Ok(Mode::Grid(GridOptions { across: false, .. })));
|
|
|
|
|
test!(across: Mode <- ["--across"], None; Both => like Ok(Mode::Grid(GridOptions { across: true, .. })));
|
|
|
|
|
test!(gracross: Mode <- ["-xG"], None; Both => like Ok(Mode::Grid(GridOptions { across: true, .. })));
|
2017-08-10 17:54:28 +01:00
|
|
|
|
|
|
|
|
|
// Lines views
|
2020-10-23 23:57:10 +01:00
|
|
|
|
test!(lines: Mode <- ["--oneline"], None; Both => like Ok(Mode::Lines));
|
|
|
|
|
test!(prima: Mode <- ["-1"], None; Both => like Ok(Mode::Lines));
|
2017-08-10 17:54:28 +01:00
|
|
|
|
|
|
|
|
|
// Details views
|
|
|
|
|
test!(long: Mode <- ["--long"], None; Both => like Ok(Mode::Details(_)));
|
|
|
|
|
test!(ell: Mode <- ["-l"], None; Both => like Ok(Mode::Details(_)));
|
|
|
|
|
|
|
|
|
|
// Grid-details views
|
2017-08-12 22:49:16 +01:00
|
|
|
|
test!(lid: Mode <- ["--long", "--grid"], None; Both => like Ok(Mode::GridDetails(_)));
|
|
|
|
|
test!(leg: Mode <- ["-lG"], None; Both => like Ok(Mode::GridDetails(_)));
|
2017-08-10 17:54:28 +01:00
|
|
|
|
|
2020-10-20 22:48:05 +01:00
|
|
|
|
// Options that do nothing with --long
|
|
|
|
|
test!(long_across: Mode <- ["--long", "--across"], None; Last => like Ok(Mode::Details(_)));
|
2017-08-10 17:54:28 +01:00
|
|
|
|
|
|
|
|
|
// Options that do nothing without --long
|
2021-03-31 21:46:24 +08:00
|
|
|
|
test!(just_header: Mode <- ["--header"], None; Last => like Ok(Mode::Grid(_)));
|
|
|
|
|
test!(just_group: Mode <- ["--group"], None; Last => like Ok(Mode::Grid(_)));
|
|
|
|
|
test!(just_inode: Mode <- ["--inode"], None; Last => like Ok(Mode::Grid(_)));
|
|
|
|
|
test!(just_links: Mode <- ["--links"], None; Last => like Ok(Mode::Grid(_)));
|
|
|
|
|
test!(just_blocks: Mode <- ["--blocks"], None; Last => like Ok(Mode::Grid(_)));
|
|
|
|
|
test!(just_binary: Mode <- ["--binary"], None; Last => like Ok(Mode::Grid(_)));
|
|
|
|
|
test!(just_bytes: Mode <- ["--bytes"], None; Last => like Ok(Mode::Grid(_)));
|
|
|
|
|
test!(just_numeric: Mode <- ["--numeric"], None; Last => like Ok(Mode::Grid(_)));
|
2017-08-10 17:54:28 +01:00
|
|
|
|
|
2020-10-10 19:49:46 +01:00
|
|
|
|
#[cfg(feature = "git")]
|
2017-08-11 21:43:56 +01:00
|
|
|
|
test!(just_git: Mode <- ["--git"], None; Last => like Ok(Mode::Grid(_)));
|
|
|
|
|
|
2021-03-31 21:46:24 +08:00
|
|
|
|
test!(just_header_2: Mode <- ["--header"], None; Complain => err OptionsError::Useless(&flags::HEADER, false, &flags::LONG));
|
|
|
|
|
test!(just_group_2: Mode <- ["--group"], None; Complain => err OptionsError::Useless(&flags::GROUP, false, &flags::LONG));
|
|
|
|
|
test!(just_inode_2: Mode <- ["--inode"], None; Complain => err OptionsError::Useless(&flags::INODE, false, &flags::LONG));
|
|
|
|
|
test!(just_links_2: Mode <- ["--links"], None; Complain => err OptionsError::Useless(&flags::LINKS, false, &flags::LONG));
|
|
|
|
|
test!(just_blocks_2: Mode <- ["--blocks"], None; Complain => err OptionsError::Useless(&flags::BLOCKS, false, &flags::LONG));
|
|
|
|
|
test!(just_binary_2: Mode <- ["--binary"], None; Complain => err OptionsError::Useless(&flags::BINARY, false, &flags::LONG));
|
|
|
|
|
test!(just_bytes_2: Mode <- ["--bytes"], None; Complain => err OptionsError::Useless(&flags::BYTES, false, &flags::LONG));
|
|
|
|
|
test!(just_numeric2: Mode <- ["--numeric"], None; Complain => err OptionsError::Useless(&flags::NUMERIC, false, &flags::LONG));
|
2017-08-11 21:43:56 +01:00
|
|
|
|
|
2020-10-10 19:49:46 +01:00
|
|
|
|
#[cfg(feature = "git")]
|
Replace Misfire with a testable OptionsResult
This was meant to be a small change, but it spiralled into a big one.
The original intention was to separate OptionsResult and OptionsError. With these types separated, the Help and Version variants can only be returned from the Options::parse function, and the later option-parsing functions can only return success or errors.
Also, Misfire was a silly name.
As a side-effect of Options::parse returning OptionsResult instead of Result<Options, Misfire>, we could no longer use unwrap() or unwrap_err() to get the contents out. This commit makes OptionsResult into a value type, and Options::parse a pure function. It feels like it should be one, having its return value entirely dependent on its arguments, but it also loaded locales and time zones. These parts have been moved into lazy_static references, and the code still passes tests without much change.
OptionsResult isn't PartialEq yet, because the file colouring uses a Box internally.
2020-10-12 23:47:36 +01:00
|
|
|
|
test!(just_git_2: Mode <- ["--git"], None; Complain => err OptionsError::Useless(&flags::GIT, false, &flags::LONG));
|
Make View command-line args position-dependent
This commit changes the way the View (long mode, lines mode, grid mode, etc) is parsed from the command-line arguments.
Previously, it checked for long and long-grid, then tree, then lines, then grid, in that order, no matter which order the arguments were given in on the command-line. Now, it bases the view on whichever argument comes last in the list.
Unfortunately, the options-parsing code for Views is getting really complicated, but I can't see a way to simplify it while retaining the existing functionality.
It also links the parsing of DirAction to the result of parsing the View, so that you can't use tree mode if your view isn't Details. This is to fix an issue where `exa --tree --oneline` would just emit ".", because the DirAction was treating directories as files, and the argument was ".", and the View made it use lines view. Now, the --tree is ignored, as the view isn't Details.
Fixes GH-407 and GH-583.
2020-10-23 23:04:22 +01:00
|
|
|
|
|
|
|
|
|
// Contradictions and combinations
|
2020-10-23 23:57:10 +01:00
|
|
|
|
test!(lgo: Mode <- ["--long", "--grid", "--oneline"], None; Both => like Ok(Mode::Lines));
|
Make View command-line args position-dependent
This commit changes the way the View (long mode, lines mode, grid mode, etc) is parsed from the command-line arguments.
Previously, it checked for long and long-grid, then tree, then lines, then grid, in that order, no matter which order the arguments were given in on the command-line. Now, it bases the view on whichever argument comes last in the list.
Unfortunately, the options-parsing code for Views is getting really complicated, but I can't see a way to simplify it while retaining the existing functionality.
It also links the parsing of DirAction to the result of parsing the View, so that you can't use tree mode if your view isn't Details. This is to fix an issue where `exa --tree --oneline` would just emit ".", because the DirAction was treating directories as files, and the argument was ".", and the View made it use lines view. Now, the --tree is ignored, as the view isn't Details.
Fixes GH-407 and GH-583.
2020-10-23 23:04:22 +01:00
|
|
|
|
test!(lgt: Mode <- ["--long", "--grid", "--tree"], None; Both => like Ok(Mode::Details(_)));
|
|
|
|
|
test!(tgl: Mode <- ["--tree", "--grid", "--long"], None; Both => like Ok(Mode::GridDetails(_)));
|
|
|
|
|
test!(tlg: Mode <- ["--tree", "--long", "--grid"], None; Both => like Ok(Mode::GridDetails(_)));
|
|
|
|
|
test!(ot: Mode <- ["--oneline", "--tree"], None; Both => like Ok(Mode::Details(_)));
|
|
|
|
|
test!(og: Mode <- ["--oneline", "--grid"], None; Both => like Ok(Mode::Grid(_)));
|
|
|
|
|
test!(tg: Mode <- ["--tree", "--grid"], None; Both => like Ok(Mode::Grid(_)));
|
2017-08-10 13:59:39 +01:00
|
|
|
|
}
|
2017-07-26 23:05:45 +01:00
|
|
|
|
}
|