mirror of
https://github.com/Llewellynvdm/exa.git
synced 2025-02-27 22:41:39 +00:00
Move colour options to their own file
This commit is contained in:
parent
30f3c6eb00
commit
4907565baf
201
src/options/colours.rs
Normal file
201
src/options/colours.rs
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
use output::Colours;
|
||||||
|
|
||||||
|
use options::{flags, Misfire};
|
||||||
|
use options::parser::MatchedFlags;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// Under what circumstances we should display coloured, rather than plain,
|
||||||
|
/// output to the terminal.
|
||||||
|
///
|
||||||
|
/// By default, we want to display the colours when stdout can display them.
|
||||||
|
/// Turning them on when output is going to, say, a pipe, would make programs
|
||||||
|
/// such as `grep` or `more` not work properly. So the `Automatic` mode does
|
||||||
|
/// this check and only displays colours when they can be truly appreciated.
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
enum TerminalColours {
|
||||||
|
|
||||||
|
/// Display them even when output isn’t going to a terminal.
|
||||||
|
Always,
|
||||||
|
|
||||||
|
/// Display them when output is going to a terminal, but not otherwise.
|
||||||
|
Automatic,
|
||||||
|
|
||||||
|
/// Never display them, even when output is going to a terminal.
|
||||||
|
Never,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TerminalColours {
|
||||||
|
fn default() -> TerminalColours {
|
||||||
|
TerminalColours::Automatic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const COLOURS: &[&str] = &["always", "auto", "never"];
|
||||||
|
|
||||||
|
impl TerminalColours {
|
||||||
|
|
||||||
|
/// Determine which terminal colour conditions to use.
|
||||||
|
fn deduce(matches: &MatchedFlags) -> Result<TerminalColours, Misfire> {
|
||||||
|
|
||||||
|
let word = match matches.get_where(|f| f.matches(&flags::COLOR) || f.matches(&flags::COLOUR))? {
|
||||||
|
Some(w) => w,
|
||||||
|
None => return Ok(TerminalColours::default()),
|
||||||
|
};
|
||||||
|
|
||||||
|
if word == "always" {
|
||||||
|
Ok(TerminalColours::Always)
|
||||||
|
}
|
||||||
|
else if word == "auto" || word == "automatic" {
|
||||||
|
Ok(TerminalColours::Automatic)
|
||||||
|
}
|
||||||
|
else if word == "never" {
|
||||||
|
Ok(TerminalColours::Never)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Err(Misfire::bad_argument(&flags::COLOR, word, COLOURS))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Colours {
|
||||||
|
pub fn deduce<TW>(matches: &MatchedFlags, widther: TW) -> Result<Colours, Misfire>
|
||||||
|
where TW: Fn() -> Option<usize> {
|
||||||
|
use self::TerminalColours::*;
|
||||||
|
|
||||||
|
let tc = TerminalColours::deduce(matches)?;
|
||||||
|
if tc == Always || (tc == Automatic && widther().is_some()) {
|
||||||
|
let scale = matches.has_where(|f| f.matches(&flags::COLOR_SCALE) || f.matches(&flags::COLOUR_SCALE))?;
|
||||||
|
Ok(Colours::colourful(scale.is_some()))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Ok(Colours::plain())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use std::ffi::OsString;
|
||||||
|
use options::flags;
|
||||||
|
use options::parser::{Flag, Arg};
|
||||||
|
|
||||||
|
use options::test::parse_for_test;
|
||||||
|
use options::test::Strictnesses::*;
|
||||||
|
|
||||||
|
pub fn os(input: &'static str) -> OsString {
|
||||||
|
let mut os = OsString::new();
|
||||||
|
os.push(input);
|
||||||
|
os
|
||||||
|
}
|
||||||
|
|
||||||
|
static TEST_ARGS: &[&Arg] = &[ &flags::COLOR, &flags::COLOUR,
|
||||||
|
&flags::COLOR_SCALE, &flags::COLOUR_SCALE ];
|
||||||
|
|
||||||
|
macro_rules! test {
|
||||||
|
|
||||||
|
($name:ident: $type:ident <- $inputs:expr; $stricts:expr => $result:expr) => {
|
||||||
|
/// Macro that writes a test.
|
||||||
|
/// If testing both strictnesses, they’ll both be done in the same function.
|
||||||
|
#[test]
|
||||||
|
fn $name() {
|
||||||
|
for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf)) {
|
||||||
|
assert_eq!(result, $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
($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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
($name:ident: $type:ident <- $inputs:expr; $stricts:expr => like $pat:pat) => {
|
||||||
|
/// More general macro for testing against a pattern.
|
||||||
|
/// Instead of using PartialEq, this just tests if it matches a pat.
|
||||||
|
#[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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
($name:ident: $type:ident <- $inputs:expr, $vars:expr; $stricts:expr => err $result:expr) => {
|
||||||
|
/// Like above, but with $vars.
|
||||||
|
#[test]
|
||||||
|
fn $name() {
|
||||||
|
for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf, &$vars)) {
|
||||||
|
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() {
|
||||||
|
for result in parse_for_test($inputs.as_ref(), TEST_ARGS, $stricts, |mf| $type::deduce(mf, &$vars)) {
|
||||||
|
println!("Testing {:?}", result);
|
||||||
|
match result {
|
||||||
|
$pat => assert!(true),
|
||||||
|
_ => assert!(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Default
|
||||||
|
test!(empty: TerminalColours <- []; Both => Ok(TerminalColours::default()));
|
||||||
|
|
||||||
|
// --colour
|
||||||
|
test!(u_always: TerminalColours <- ["--colour=always"]; Both => Ok(TerminalColours::Always));
|
||||||
|
test!(u_auto: TerminalColours <- ["--colour", "auto"]; Both => Ok(TerminalColours::Automatic));
|
||||||
|
test!(u_never: TerminalColours <- ["--colour=never"]; Both => Ok(TerminalColours::Never));
|
||||||
|
|
||||||
|
// --color
|
||||||
|
test!(no_u_always: TerminalColours <- ["--color", "always"]; Both => Ok(TerminalColours::Always));
|
||||||
|
test!(no_u_auto: TerminalColours <- ["--color=auto"]; Both => Ok(TerminalColours::Automatic));
|
||||||
|
test!(no_u_never: TerminalColours <- ["--color", "never"]; Both => Ok(TerminalColours::Never));
|
||||||
|
|
||||||
|
// Errors
|
||||||
|
test!(no_u_error: TerminalColours <- ["--color=upstream"]; Both => err Misfire::bad_argument(&flags::COLOR, &os("upstream"), super::COLOURS)); // the error is for --color
|
||||||
|
test!(u_error: TerminalColours <- ["--colour=lovers"]; Both => err Misfire::bad_argument(&flags::COLOR, &os("lovers"), super::COLOURS)); // and so is this one!
|
||||||
|
|
||||||
|
// Overriding
|
||||||
|
test!(overridden_1: TerminalColours <- ["--colour=auto", "--colour=never"]; Last => Ok(TerminalColours::Never));
|
||||||
|
test!(overridden_2: TerminalColours <- ["--color=auto", "--colour=never"]; Last => Ok(TerminalColours::Never));
|
||||||
|
test!(overridden_3: TerminalColours <- ["--colour=auto", "--color=never"]; Last => Ok(TerminalColours::Never));
|
||||||
|
test!(overridden_4: TerminalColours <- ["--color=auto", "--color=never"]; Last => Ok(TerminalColours::Never));
|
||||||
|
|
||||||
|
test!(overridden_5: TerminalColours <- ["--colour=auto", "--colour=never"]; Complain => err Misfire::Duplicate(Flag::Long("colour"), Flag::Long("colour")));
|
||||||
|
test!(overridden_6: TerminalColours <- ["--color=auto", "--colour=never"]; Complain => err Misfire::Duplicate(Flag::Long("color"), Flag::Long("colour")));
|
||||||
|
test!(overridden_7: TerminalColours <- ["--colour=auto", "--color=never"]; Complain => err Misfire::Duplicate(Flag::Long("colour"), Flag::Long("color")));
|
||||||
|
test!(overridden_8: TerminalColours <- ["--color=auto", "--color=never"]; Complain => err Misfire::Duplicate(Flag::Long("color"), Flag::Long("color")));
|
||||||
|
|
||||||
|
test!(scale_1: Colours <- ["--color=always", "--color-scale", "--colour-scale"], || None; Last => like Ok(Colours { scale: true, .. }));
|
||||||
|
test!(scale_2: Colours <- ["--color=always", "--color-scale", ], || None; Last => like Ok(Colours { scale: true, .. }));
|
||||||
|
test!(scale_3: Colours <- ["--color=always", "--colour-scale"], || None; Last => like Ok(Colours { scale: true, .. }));
|
||||||
|
test!(scale_4: Colours <- ["--color=always", ], || None; Last => like Ok(Colours { scale: false, .. }));
|
||||||
|
|
||||||
|
test!(scale_5: Colours <- ["--color=always", "--color-scale", "--colour-scale"], || None; Complain => err Misfire::Duplicate(Flag::Long("color-scale"), Flag::Long("colour-scale")));
|
||||||
|
test!(scale_6: Colours <- ["--color=always", "--color-scale", ], || None; Complain => like Ok(Colours { scale: true, .. }));
|
||||||
|
test!(scale_7: Colours <- ["--color=always", "--colour-scale"], || None; Complain => like Ok(Colours { scale: true, .. }));
|
||||||
|
test!(scale_8: Colours <- ["--color=always", ], || None; Complain => like Ok(Colours { scale: false, .. }));
|
||||||
|
}
|
@ -75,6 +75,7 @@ use fs::dir_action::DirAction;
|
|||||||
use fs::filter::FileFilter;
|
use fs::filter::FileFilter;
|
||||||
use output::{View, Mode, details, grid_details};
|
use output::{View, Mode, details, grid_details};
|
||||||
|
|
||||||
|
mod colours;
|
||||||
mod dir_action;
|
mod dir_action;
|
||||||
mod filter;
|
mod filter;
|
||||||
mod view;
|
mod view;
|
||||||
|
@ -11,12 +11,13 @@ use options::parser::MatchedFlags;
|
|||||||
use fs::feature::xattr;
|
use fs::feature::xattr;
|
||||||
use info::filetype::FileExtensions;
|
use info::filetype::FileExtensions;
|
||||||
|
|
||||||
|
|
||||||
impl View {
|
impl View {
|
||||||
|
|
||||||
/// Determine which view to use and all of that view’s arguments.
|
/// Determine which view to use and all of that view’s arguments.
|
||||||
pub fn deduce<V: Vars>(matches: &MatchedFlags, vars: &V) -> Result<View, Misfire> {
|
pub fn deduce<V: Vars>(matches: &MatchedFlags, vars: &V) -> Result<View, Misfire> {
|
||||||
let mode = Mode::deduce(matches, vars)?;
|
let mode = Mode::deduce(matches, vars)?;
|
||||||
let colours = Colours::deduce(matches)?;
|
let colours = Colours::deduce(matches, || *TERM_WIDTH)?;
|
||||||
let style = FileStyle::deduce(matches)?;
|
let style = FileStyle::deduce(matches)?;
|
||||||
Ok(View { mode, colours, style })
|
Ok(View { mode, colours, style })
|
||||||
}
|
}
|
||||||
@ -330,77 +331,6 @@ impl TimeTypes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Under what circumstances we should display coloured, rather than plain,
|
|
||||||
/// output to the terminal.
|
|
||||||
///
|
|
||||||
/// By default, we want to display the colours when stdout can display them.
|
|
||||||
/// Turning them on when output is going to, say, a pipe, would make programs
|
|
||||||
/// such as `grep` or `more` not work properly. So the `Automatic` mode does
|
|
||||||
/// this check and only displays colours when they can be truly appreciated.
|
|
||||||
#[derive(PartialEq, Debug)]
|
|
||||||
enum TerminalColours {
|
|
||||||
|
|
||||||
/// Display them even when output isn’t going to a terminal.
|
|
||||||
Always,
|
|
||||||
|
|
||||||
/// Display them when output is going to a terminal, but not otherwise.
|
|
||||||
Automatic,
|
|
||||||
|
|
||||||
/// Never display them, even when output is going to a terminal.
|
|
||||||
Never,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for TerminalColours {
|
|
||||||
fn default() -> TerminalColours {
|
|
||||||
TerminalColours::Automatic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const COLOURS: &[&str] = &["always", "auto", "never"];
|
|
||||||
|
|
||||||
impl TerminalColours {
|
|
||||||
|
|
||||||
/// Determine which terminal colour conditions to use.
|
|
||||||
fn deduce(matches: &MatchedFlags) -> Result<TerminalColours, Misfire> {
|
|
||||||
|
|
||||||
let word = match matches.get_where(|f| f.matches(&flags::COLOR) || f.matches(&flags::COLOUR))? {
|
|
||||||
Some(w) => w,
|
|
||||||
None => return Ok(TerminalColours::default()),
|
|
||||||
};
|
|
||||||
|
|
||||||
if word == "always" {
|
|
||||||
Ok(TerminalColours::Always)
|
|
||||||
}
|
|
||||||
else if word == "auto" || word == "automatic" {
|
|
||||||
Ok(TerminalColours::Automatic)
|
|
||||||
}
|
|
||||||
else if word == "never" {
|
|
||||||
Ok(TerminalColours::Never)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Err(Misfire::bad_argument(&flags::COLOR, word, COLOURS))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl Colours {
|
|
||||||
fn deduce(matches: &MatchedFlags) -> Result<Colours, Misfire> {
|
|
||||||
use self::TerminalColours::*;
|
|
||||||
|
|
||||||
let tc = TerminalColours::deduce(matches)?;
|
|
||||||
if tc == Always || (tc == Automatic && TERM_WIDTH.is_some()) {
|
|
||||||
let scale = matches.has_where(|f| f.matches(&flags::COLOR_SCALE) || f.matches(&flags::COLOUR_SCALE))?;
|
|
||||||
Ok(Colours::colourful(scale.is_some()))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Ok(Colours::plain())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl FileStyle {
|
impl FileStyle {
|
||||||
fn deduce(matches: &MatchedFlags) -> Result<FileStyle, Misfire> {
|
fn deduce(matches: &MatchedFlags) -> Result<FileStyle, Misfire> {
|
||||||
let classify = Classify::deduce(matches)?;
|
let classify = Classify::deduce(matches)?;
|
||||||
@ -452,7 +382,6 @@ mod test {
|
|||||||
|
|
||||||
static TEST_ARGS: &[&Arg] = &[ &flags::BINARY, &flags::BYTES, &flags::TIME_STYLE,
|
static TEST_ARGS: &[&Arg] = &[ &flags::BINARY, &flags::BYTES, &flags::TIME_STYLE,
|
||||||
&flags::TIME, &flags::MODIFIED, &flags::CREATED, &flags::ACCESSED,
|
&flags::TIME, &flags::MODIFIED, &flags::CREATED, &flags::ACCESSED,
|
||||||
&flags::COLOR, &flags::COLOUR, &flags::COLOR_SCALE, &flags::COLOUR_SCALE,
|
|
||||||
&flags::HEADER, &flags::GROUP, &flags::INODE, &flags::GIT,
|
&flags::HEADER, &flags::GROUP, &flags::INODE, &flags::GIT,
|
||||||
&flags::LINKS, &flags::BLOCKS, &flags::LONG, &flags::LEVEL,
|
&flags::LINKS, &flags::BLOCKS, &flags::LONG, &flags::LEVEL,
|
||||||
&flags::GRID, &flags::ACROSS, &flags::ONE_LINE ];
|
&flags::GRID, &flags::ACROSS, &flags::ONE_LINE ];
|
||||||
@ -611,49 +540,6 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mod colourses {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
// Default
|
|
||||||
test!(empty: TerminalColours <- []; Both => Ok(TerminalColours::default()));
|
|
||||||
|
|
||||||
// --colour
|
|
||||||
test!(u_always: TerminalColours <- ["--colour=always"]; Both => Ok(TerminalColours::Always));
|
|
||||||
test!(u_auto: TerminalColours <- ["--colour", "auto"]; Both => Ok(TerminalColours::Automatic));
|
|
||||||
test!(u_never: TerminalColours <- ["--colour=never"]; Both => Ok(TerminalColours::Never));
|
|
||||||
|
|
||||||
// --color
|
|
||||||
test!(no_u_always: TerminalColours <- ["--color", "always"]; Both => Ok(TerminalColours::Always));
|
|
||||||
test!(no_u_auto: TerminalColours <- ["--color=auto"]; Both => Ok(TerminalColours::Automatic));
|
|
||||||
test!(no_u_never: TerminalColours <- ["--color", "never"]; Both => Ok(TerminalColours::Never));
|
|
||||||
|
|
||||||
// Errors
|
|
||||||
test!(no_u_error: TerminalColours <- ["--color=upstream"]; Both => err Misfire::bad_argument(&flags::COLOR, &os("upstream"), super::COLOURS)); // the error is for --color
|
|
||||||
test!(u_error: TerminalColours <- ["--colour=lovers"]; Both => err Misfire::bad_argument(&flags::COLOR, &os("lovers"), super::COLOURS)); // and so is this one!
|
|
||||||
|
|
||||||
// Overriding
|
|
||||||
test!(overridden_1: TerminalColours <- ["--colour=auto", "--colour=never"]; Last => Ok(TerminalColours::Never));
|
|
||||||
test!(overridden_2: TerminalColours <- ["--color=auto", "--colour=never"]; Last => Ok(TerminalColours::Never));
|
|
||||||
test!(overridden_3: TerminalColours <- ["--colour=auto", "--color=never"]; Last => Ok(TerminalColours::Never));
|
|
||||||
test!(overridden_4: TerminalColours <- ["--color=auto", "--color=never"]; Last => Ok(TerminalColours::Never));
|
|
||||||
|
|
||||||
test!(overridden_5: TerminalColours <- ["--colour=auto", "--colour=never"]; Complain => err Misfire::Duplicate(Flag::Long("colour"), Flag::Long("colour")));
|
|
||||||
test!(overridden_6: TerminalColours <- ["--color=auto", "--colour=never"]; Complain => err Misfire::Duplicate(Flag::Long("color"), Flag::Long("colour")));
|
|
||||||
test!(overridden_7: TerminalColours <- ["--colour=auto", "--color=never"]; Complain => err Misfire::Duplicate(Flag::Long("colour"), Flag::Long("color")));
|
|
||||||
test!(overridden_8: TerminalColours <- ["--color=auto", "--color=never"]; Complain => err Misfire::Duplicate(Flag::Long("color"), Flag::Long("color")));
|
|
||||||
|
|
||||||
test!(scale_1: Colours <- ["--color=always", "--color-scale", "--colour-scale"]; Last => like Ok(Colours { scale: true, .. }));
|
|
||||||
test!(scale_2: Colours <- ["--color=always", "--color-scale", ]; Last => like Ok(Colours { scale: true, .. }));
|
|
||||||
test!(scale_3: Colours <- ["--color=always", "--colour-scale"]; Last => like Ok(Colours { scale: true, .. }));
|
|
||||||
test!(scale_4: Colours <- ["--color=always", ]; Last => like Ok(Colours { scale: false, .. }));
|
|
||||||
|
|
||||||
test!(scale_5: Colours <- ["--color=always", "--color-scale", "--colour-scale"]; Complain => err Misfire::Duplicate(Flag::Long("color-scale"), Flag::Long("colour-scale")));
|
|
||||||
test!(scale_6: Colours <- ["--color=always", "--color-scale", ]; Complain => like Ok(Colours { scale: true, .. }));
|
|
||||||
test!(scale_7: Colours <- ["--color=always", "--colour-scale"]; Complain => like Ok(Colours { scale: true, .. }));
|
|
||||||
test!(scale_8: Colours <- ["--color=always", ]; Complain => like Ok(Colours { scale: false, .. }));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
mod views {
|
mod views {
|
||||||
use super::*;
|
use super::*;
|
||||||
use output::grid::Options as GridOptions;
|
use output::grid::Options as GridOptions;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user