From 22e103361ffcee9b9e6f837d9e81dc00e8f9ba42 Mon Sep 17 00:00:00 2001 From: N <47500890+avi-cenna@users.noreply.github.com> Date: Tue, 10 Oct 2023 20:04:34 -0400 Subject: [PATCH] Allow setting echoed recipe line color (#1670) --- .gitignore | 1 + completions/just.bash | 6 ++++- completions/just.elvish | 1 + completions/just.fish | 1 + completions/just.powershell | 1 + completions/just.zsh | 1 + src/color.rs | 8 +++++-- src/config.rs | 47 +++++++++++++++++++++++++++++++++++++ src/recipe.rs | 2 +- tests/command.rs | 12 ++++++++++ 10 files changed, 76 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 17ed309..e6c81f9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .DS_Store +.idea /.vagrant /README.html /book/en/build diff --git a/completions/just.bash b/completions/just.bash index 9c7945b..99d7fdb 100644 --- a/completions/just.bash +++ b/completions/just.bash @@ -20,7 +20,7 @@ _just() { case "${cmd}" in just) - opts=" -n -q -u -v -e -l -h -V -f -d -c -s --check --dry-run --highlight --no-dotenv --no-highlight --quiet --shell-command --clear-shell-args --unsorted --unstable --verbose --changelog --choose --dump --edit --evaluate --fmt --init --list --summary --variables --help --version --chooser --color --dump-format --list-heading --list-prefix --justfile --set --shell --shell-arg --working-directory --command --completions --show --dotenv-filename --dotenv-path ... " + opts=" -n -q -u -v -e -l -h -V -f -d -c -s --check --dry-run --highlight --no-dotenv --no-highlight --quiet --shell-command --clear-shell-args --unsorted --unstable --verbose --changelog --choose --dump --edit --evaluate --fmt --init --list --summary --variables --help --version --chooser --color --command-color --dump-format --list-heading --list-prefix --justfile --set --shell --shell-arg --working-directory --command --completions --show --dotenv-filename --dotenv-path ... " if [[ ${cur} == -* ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -48,6 +48,10 @@ _just() { COMPREPLY=($(compgen -W "auto always never" -- "${cur}")) return 0 ;; + --command-color) + COMPREPLY=($(compgen -W "black blue cyan green purple red yellow" -- "${cur}")) + return 0 + ;; --dump-format) COMPREPLY=($(compgen -W "just json" -- "${cur}")) return 0 diff --git a/completions/just.elvish b/completions/just.elvish index 1a208af..1b3be81 100644 --- a/completions/just.elvish +++ b/completions/just.elvish @@ -16,6 +16,7 @@ edit:completion:arg-completer[just] = [@words]{ &'just'= { cand --chooser 'Override binary invoked by `--choose`' cand --color 'Print colorful output' + cand --command-color 'Echo recipe lines in ' cand --dump-format 'Dump justfile as ' cand --list-heading 'Print before list' cand --list-prefix 'Print before each list item' diff --git a/completions/just.fish b/completions/just.fish index 43d4177..0771de0 100644 --- a/completions/just.fish +++ b/completions/just.fish @@ -11,6 +11,7 @@ complete -c just -a '(__fish_just_complete_recipes)' # autogenerated completions complete -c just -n "__fish_use_subcommand" -l chooser -d 'Override binary invoked by `--choose`' complete -c just -n "__fish_use_subcommand" -l color -d 'Print colorful output' -r -f -a "auto always never" +complete -c just -n "__fish_use_subcommand" -l command-color -d 'Echo recipe lines in ' -r -f -a "black blue cyan green purple red yellow" complete -c just -n "__fish_use_subcommand" -l dump-format -d 'Dump justfile as ' -r -f -a "just json" complete -c just -n "__fish_use_subcommand" -l list-heading -d 'Print before list' complete -c just -n "__fish_use_subcommand" -l list-prefix -d 'Print before each list item' diff --git a/completions/just.powershell b/completions/just.powershell index 1ed04d3..0842dc8 100644 --- a/completions/just.powershell +++ b/completions/just.powershell @@ -21,6 +21,7 @@ Register-ArgumentCompleter -Native -CommandName 'just' -ScriptBlock { 'just' { [CompletionResult]::new('--chooser', 'chooser', [CompletionResultType]::ParameterName, 'Override binary invoked by `--choose`') [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'Print colorful output') + [CompletionResult]::new('--command-color', 'command-color', [CompletionResultType]::ParameterName, 'Echo recipe lines in ') [CompletionResult]::new('--dump-format', 'dump-format', [CompletionResultType]::ParameterName, 'Dump justfile as ') [CompletionResult]::new('--list-heading', 'list-heading', [CompletionResultType]::ParameterName, 'Print before list') [CompletionResult]::new('--list-prefix', 'list-prefix', [CompletionResultType]::ParameterName, 'Print before each list item') diff --git a/completions/just.zsh b/completions/just.zsh index a3aff35..4ddfa86 100644 --- a/completions/just.zsh +++ b/completions/just.zsh @@ -17,6 +17,7 @@ _just() { local common=( '--chooser=[Override binary invoked by `--choose`]' \ '--color=[Print colorful output]: :(auto always never)' \ +'--command-color=[Echo recipe lines in ]: :(black blue cyan green purple red yellow)' \ '--dump-format=[Dump justfile as ]: :(just json)' \ '--list-heading=[Print before list]' \ '--list-prefix=[Print before each list item]' \ diff --git a/src/color.rs b/src/color.rs index 2fcad9a..56670ac 100644 --- a/src/color.rs +++ b/src/color.rs @@ -76,8 +76,12 @@ impl Color { self.restyle(Style::new().fg(Cyan).bold()) } - pub(crate) fn command(self) -> Self { - self.restyle(Style::new().bold()) + pub(crate) fn command(self, foreground: Option) -> Self { + self.restyle(Style { + foreground, + is_bold: true, + ..Style::default() + }) } pub(crate) fn parameter(self) -> Self { diff --git a/src/config.rs b/src/config.rs index 14904c5..1e6e86d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -15,6 +15,7 @@ pub(crate) const CHOOSE_HELP: &str = "Select one or more recipes to run using a pub(crate) struct Config { pub(crate) check: bool, pub(crate) color: Color, + pub(crate) command_color: Option, pub(crate) dotenv_filename: Option, pub(crate) dotenv_path: Option, pub(crate) dry_run: bool, @@ -85,6 +86,7 @@ mod arg { pub(crate) const CHOOSER: &str = "CHOOSER"; pub(crate) const CLEAR_SHELL_ARGS: &str = "CLEAR-SHELL-ARGS"; pub(crate) const COLOR: &str = "COLOR"; + pub(crate) const COMMAND_COLOR: &str = "COMMAND-COLOR"; pub(crate) const DOTENV_FILENAME: &str = "DOTENV-FILENAME"; pub(crate) const DOTENV_PATH: &str = "DOTENV-PATH"; pub(crate) const DRY_RUN: &str = "DRY-RUN"; @@ -110,6 +112,23 @@ mod arg { 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]; @@ -142,6 +161,13 @@ impl Config { .default_value(arg::COLOR_AUTO) .help("Print colorful output"), ) + .arg( + Arg::with_name(arg::COMMAND_COLOR) + .long("command-color") + .takes_value(true) + .possible_values(arg::COMMAND_COLOR_VALUES) + .help("Echo recipe lines in "), + ) .arg( Arg::with_name(arg::DRY_RUN) .short("n") @@ -396,6 +422,25 @@ impl Config { } } + fn command_color_from_matches(matches: &ArgMatches) -> ConfigResult> { + if let Some(value) = matches.value_of(arg::COMMAND_COLOR) { + match value { + 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 .value_of(arg::DUMP_FORMAT) @@ -422,6 +467,7 @@ impl Config { }; let color = Self::color_from_matches(matches)?; + let command_color = Self::command_color_from_matches(matches)?; let set_count = matches.occurrences_of(arg::SET); let mut overrides = BTreeMap::new(); @@ -593,6 +639,7 @@ impl Config { .unwrap_or(" ") .to_owned(), color, + command_color, invocation_directory, search_config, shell_args, diff --git a/src/recipe.rs b/src/recipe.rs index aa1c487..c1fa22f 100644 --- a/src/recipe.rs +++ b/src/recipe.rs @@ -182,7 +182,7 @@ impl<'src, D> Recipe<'src, D> { || !((quiet_command ^ self.quiet) || config.verbosity.quiet()) { let color = if config.highlight { - config.color.command() + config.color.command(config.command_color) } else { config.color }; diff --git a/tests/command.rs b/tests/command.rs index 0529958..c1c9473 100644 --- a/tests/command.rs +++ b/tests/command.rs @@ -20,6 +20,18 @@ test! { stdout: "foo", } +test! { + name: command_color, + justfile: " + x: + echo XYZ + ", + args: ("--color", "always", "--command-color", "cyan"), + stdout: "XYZ\n", + stderr: "\u{1b}[1;36mecho XYZ\u{1b}[0m\n", + status: EXIT_SUCCESS, +} + test! { name: no_binary, justfile: "