diff --git a/src/color.rs b/src/color.rs index f477d4e..f14a662 100644 --- a/src/color.rs +++ b/src/color.rs @@ -38,6 +38,7 @@ impl Color { } } + #[cfg(test)] pub(crate) fn always() -> Self { Self { use_color: UseColor::Always, @@ -133,6 +134,15 @@ impl Color { } } +impl From for Color { + fn from(use_color: UseColor) -> Self { + Self { + use_color, + ..Default::default() + } + } +} + impl Default for Color { fn default() -> Self { Self { diff --git a/src/command_color.rs b/src/command_color.rs new file mode 100644 index 0000000..6703b10 --- /dev/null +++ b/src/command_color.rs @@ -0,0 +1,26 @@ +use super::*; + +#[derive(Copy, Clone, ValueEnum)] +pub(crate) enum CommandColor { + Black, + Blue, + Cyan, + Green, + Purple, + Red, + Yellow, +} + +impl From for ansi_term::Color { + fn from(command_color: CommandColor) -> Self { + match command_color { + CommandColor::Black => Self::Black, + CommandColor::Blue => Self::Blue, + CommandColor::Cyan => Self::Cyan, + CommandColor::Green => Self::Green, + CommandColor::Purple => Self::Purple, + CommandColor::Red => Self::Red, + CommandColor::Yellow => Self::Yellow, + } + } +} diff --git a/src/completions.rs b/src/completions.rs index 0beb4d1..cb567b3 100644 --- a/src/completions.rs +++ b/src/completions.rs @@ -1,4 +1,4 @@ -use {super::*, clap::ValueEnum}; +use super::*; #[derive(ValueEnum, Debug, Clone, Copy, PartialEq)] pub(crate) enum Shell { diff --git a/src/config.rs b/src/config.rs index c32d62b..2595c89 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,7 +1,7 @@ use { super::*, clap::{ - builder::{styling::AnsiColor, FalseyValueParser, PossibleValuesParser, Styles}, + builder::{styling::AnsiColor, FalseyValueParser, Styles}, parser::ValuesRef, value_parser, Arg, ArgAction, ArgGroup, ArgMatches, Command, }, @@ -108,32 +108,6 @@ mod arg { pub(crate) const VERBOSE: &str = "VERBOSE"; pub(crate) const WORKING_DIRECTORY: &str = "WORKING-DIRECTORY"; pub(crate) const YES: &str = "YES"; - - pub(crate) const COLOR_ALWAYS: &str = "always"; - pub(crate) const COLOR_AUTO: &str = "auto"; - pub(crate) const COLOR_NEVER: &str = "never"; - pub(crate) const COLOR_VALUES: &[&str] = &[COLOR_AUTO, COLOR_ALWAYS, COLOR_NEVER]; - - pub(crate) const COMMAND_COLOR_BLACK: &str = "black"; - pub(crate) const COMMAND_COLOR_BLUE: &str = "blue"; - pub(crate) const COMMAND_COLOR_CYAN: &str = "cyan"; - pub(crate) const COMMAND_COLOR_GREEN: &str = "green"; - pub(crate) const COMMAND_COLOR_PURPLE: &str = "purple"; - pub(crate) const COMMAND_COLOR_RED: &str = "red"; - pub(crate) const COMMAND_COLOR_YELLOW: &str = "yellow"; - pub(crate) const COMMAND_COLOR_VALUES: &[&str] = &[ - COMMAND_COLOR_BLACK, - COMMAND_COLOR_BLUE, - COMMAND_COLOR_CYAN, - COMMAND_COLOR_GREEN, - COMMAND_COLOR_PURPLE, - COMMAND_COLOR_RED, - COMMAND_COLOR_YELLOW, - ]; - - pub(crate) const DUMP_FORMAT_JSON: &str = "json"; - pub(crate) const DUMP_FORMAT_JUST: &str = "just"; - pub(crate) const DUMP_FORMAT_VALUES: &[&str] = &[DUMP_FORMAT_JUST, DUMP_FORMAT_JSON]; } impl Config { @@ -184,8 +158,8 @@ impl Config { .long("color") .env("JUST_COLOR") .action(ArgAction::Set) - .value_parser(PossibleValuesParser::new(arg::COLOR_VALUES)) - .default_value(arg::COLOR_AUTO) + .value_parser(clap::value_parser!(UseColor)) + .default_value("auto") .help("Print colorful output"), ) .arg( @@ -193,7 +167,7 @@ impl Config { .long("command-color") .env("JUST_COMMAND_COLOR") .action(ArgAction::Set) - .value_parser(PossibleValuesParser::new(arg::COMMAND_COLOR_VALUES)) + .value_parser(clap::value_parser!(CommandColor)) .help("Echo recipe lines in "), ) .arg( @@ -225,8 +199,8 @@ impl Config { .long("dump-format") .env("JUST_DUMP_FORMAT") .action(ArgAction::Set) - .value_parser(PossibleValuesParser::new(arg::DUMP_FORMAT_VALUES)) - .default_value(arg::DUMP_FORMAT_JUST) + .value_parser(clap::value_parser!(DumpFormat)) + .default_value("just") .value_name("FORMAT") .help("Dump justfile as "), ) @@ -531,59 +505,6 @@ impl Config { ) } - fn color_from_matches(matches: &ArgMatches) -> ConfigResult { - let value = matches - .get_one::(arg::COLOR) - .ok_or_else(|| ConfigError::Internal { - message: "`--color` had no value".to_string(), - })?; - - match value.as_str() { - arg::COLOR_AUTO => Ok(Color::auto()), - arg::COLOR_ALWAYS => Ok(Color::always()), - arg::COLOR_NEVER => Ok(Color::never()), - _ => Err(ConfigError::Internal { - message: format!("Invalid argument `{value}` to --color."), - }), - } - } - - fn command_color_from_matches(matches: &ArgMatches) -> ConfigResult> { - if let Some(value) = matches.get_one::(arg::COMMAND_COLOR) { - match value.as_str() { - arg::COMMAND_COLOR_BLACK => Ok(Some(ansi_term::Color::Black)), - arg::COMMAND_COLOR_BLUE => Ok(Some(ansi_term::Color::Blue)), - arg::COMMAND_COLOR_CYAN => Ok(Some(ansi_term::Color::Cyan)), - arg::COMMAND_COLOR_GREEN => Ok(Some(ansi_term::Color::Green)), - arg::COMMAND_COLOR_PURPLE => Ok(Some(ansi_term::Color::Purple)), - arg::COMMAND_COLOR_RED => Ok(Some(ansi_term::Color::Red)), - arg::COMMAND_COLOR_YELLOW => Ok(Some(ansi_term::Color::Yellow)), - value => Err(ConfigError::Internal { - message: format!("Invalid argument `{value}` to --command-color."), - }), - } - } else { - Ok(None) - } - } - - fn dump_format_from_matches(matches: &ArgMatches) -> ConfigResult { - let value = - matches - .get_one::(arg::DUMP_FORMAT) - .ok_or_else(|| ConfigError::Internal { - message: "`--dump-format` had no value".to_string(), - })?; - - match value.as_str() { - arg::DUMP_FORMAT_JSON => Ok(DumpFormat::Json), - arg::DUMP_FORMAT_JUST => Ok(DumpFormat::Just), - _ => Err(ConfigError::Internal { - message: format!("Invalid argument `{value}` to --dump-format."), - }), - } - } - fn parse_module_path(values: ValuesRef) -> ConfigResult { let path = values.clone().map(|s| (*s).as_str()).collect::>(); @@ -748,14 +669,20 @@ impl Config { Ok(Self { check: matches.get_flag(arg::CHECK), - color: Self::color_from_matches(matches)?, - command_color: Self::command_color_from_matches(matches)?, + color: (*matches.get_one::(arg::COLOR).unwrap()).into(), + command_color: matches + .get_one::(arg::COMMAND_COLOR) + .copied() + .map(CommandColor::into), dotenv_filename: matches .get_one::(arg::DOTENV_FILENAME) .map(Into::into), dotenv_path: matches.get_one::(arg::DOTENV_PATH).map(Into::into), dry_run: matches.get_flag(arg::DRY_RUN), - dump_format: Self::dump_format_from_matches(matches)?, + dump_format: matches + .get_one::(arg::DUMP_FORMAT) + .unwrap() + .clone(), highlight: !matches.get_flag(arg::NO_HIGHLIGHT), invocation_directory: env::current_dir().context(config_error::CurrentDirContext)?, list_heading: matches diff --git a/src/dump_format.rs b/src/dump_format.rs index e560ae0..b4bd3cc 100644 --- a/src/dump_format.rs +++ b/src/dump_format.rs @@ -1,4 +1,6 @@ -#[derive(Debug, PartialEq)] +use super::*; + +#[derive(Debug, PartialEq, Clone, ValueEnum)] pub(crate) enum DumpFormat { Json, Just, diff --git a/src/lib.rs b/src/lib.rs index d787ab1..50e54e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,29 +23,30 @@ pub(crate) use { crate::{ alias::Alias, analyzer::Analyzer, argument_parser::ArgumentParser, assignment::Assignment, assignment_resolver::AssignmentResolver, ast::Ast, attribute::Attribute, binding::Binding, - color::Color, color_display::ColorDisplay, command_ext::CommandExt, compilation::Compilation, - compile_error::CompileError, compile_error_kind::CompileErrorKind, compiler::Compiler, - condition::Condition, conditional_operator::ConditionalOperator, config::Config, - config_error::ConfigError, constants::constants, count::Count, delimiter::Delimiter, - dependency::Dependency, dump_format::DumpFormat, enclosure::Enclosure, error::Error, - evaluator::Evaluator, execution_context::ExecutionContext, expression::Expression, - fragment::Fragment, function::Function, interrupt_guard::InterruptGuard, - interrupt_handler::InterruptHandler, item::Item, justfile::Justfile, keyed::Keyed, - keyword::Keyword, lexer::Lexer, line::Line, list::List, load_dotenv::load_dotenv, - loader::Loader, module_path::ModulePath, name::Name, namepath::Namepath, ordinal::Ordinal, - output::output, output_error::OutputError, parameter::Parameter, parameter_kind::ParameterKind, - parser::Parser, platform::Platform, platform_interface::PlatformInterface, position::Position, - positional::Positional, ran::Ran, range_ext::RangeExt, recipe::Recipe, - recipe_resolver::RecipeResolver, recipe_signature::RecipeSignature, scope::Scope, - search::Search, search_config::SearchConfig, search_error::SearchError, set::Set, - setting::Setting, settings::Settings, shebang::Shebang, shell::Shell, - show_whitespace::ShowWhitespace, source::Source, string_kind::StringKind, + color::Color, color_display::ColorDisplay, command_color::CommandColor, + command_ext::CommandExt, compilation::Compilation, compile_error::CompileError, + compile_error_kind::CompileErrorKind, compiler::Compiler, condition::Condition, + conditional_operator::ConditionalOperator, config::Config, config_error::ConfigError, + constants::constants, count::Count, delimiter::Delimiter, dependency::Dependency, + dump_format::DumpFormat, enclosure::Enclosure, error::Error, evaluator::Evaluator, + execution_context::ExecutionContext, expression::Expression, fragment::Fragment, + function::Function, interrupt_guard::InterruptGuard, interrupt_handler::InterruptHandler, + item::Item, justfile::Justfile, keyed::Keyed, keyword::Keyword, lexer::Lexer, line::Line, + list::List, load_dotenv::load_dotenv, loader::Loader, module_path::ModulePath, name::Name, + namepath::Namepath, ordinal::Ordinal, output::output, output_error::OutputError, + parameter::Parameter, parameter_kind::ParameterKind, parser::Parser, platform::Platform, + platform_interface::PlatformInterface, position::Position, positional::Positional, ran::Ran, + range_ext::RangeExt, recipe::Recipe, recipe_resolver::RecipeResolver, + recipe_signature::RecipeSignature, scope::Scope, search::Search, search_config::SearchConfig, + search_error::SearchError, set::Set, setting::Setting, settings::Settings, shebang::Shebang, + shell::Shell, show_whitespace::ShowWhitespace, source::Source, string_kind::StringKind, string_literal::StringLiteral, subcommand::Subcommand, suggestion::Suggestion, table::Table, thunk::Thunk, token::Token, token_kind::TokenKind, unresolved_dependency::UnresolvedDependency, unresolved_recipe::UnresolvedRecipe, use_color::UseColor, variables::Variables, verbosity::Verbosity, warning::Warning, }, camino::Utf8Path, + clap::ValueEnum, derivative::Derivative, edit_distance::edit_distance, lexiclean::Lexiclean, @@ -128,6 +129,7 @@ mod attribute; mod binding; mod color; mod color_display; +mod command_color; mod command_ext; mod compilation; mod compile_error; diff --git a/src/use_color.rs b/src/use_color.rs index 131ec6d..8086989 100644 --- a/src/use_color.rs +++ b/src/use_color.rs @@ -1,4 +1,6 @@ -#[derive(Copy, Clone, Debug, PartialEq)] +use super::*; + +#[derive(Copy, Clone, Debug, PartialEq, ValueEnum)] pub(crate) enum UseColor { Auto, Always,