mu: allow color in early command errors

This commit is contained in:
Dirk-Jan C. Binnema
2023-01-18 00:14:02 +02:00
parent 66e332fcf2
commit 4194f17440
3 changed files with 45 additions and 18 deletions

View File

@ -1,5 +1,5 @@
/* /*
** Copyright (C) 2022 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ** Copyright (C) 2022-2023 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** **
** This program is free software; you can redistribute it and/or modify it ** This program is free software; you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by the ** under the terms of the GNU General Public License as published by the
@ -594,24 +594,29 @@ cmd_help(const CLI::App& app, Options& opts)
"no help available for '%s'", opts.help.command.c_str()); "no help available for '%s'", opts.help.command.c_str());
} }
bool
Options::default_no_color()
{
static const auto no_color =
!::isatty(::fileno(stdout)) ||
!::isatty(::fileno(stderr)) ||
::getenv("NO_COLOR") != NULL;
return no_color;
}
static void static void
add_global_options(CLI::App& cli, Options& opts) add_global_options(CLI::App& cli, Options& opts)
{ {
static const auto default_no_color = opts.nocolor = Options::default_no_color();
!::isatty(::fileno(stdout)) ||
!::isatty(::fileno(stderr)) ||
::getenv("NO_COLOR") != NULL;
opts.nocolor = default_no_color;
errno = 0; errno = 0;
cli.add_flag("-q,--quiet", opts.quiet, "Hide non-essential output"); cli.add_flag("-q,--quiet", opts.quiet, "Hide non-essential output");
cli.add_flag("-v,--verbose", opts.verbose, "Show verbose output"); cli.add_flag("-v,--verbose", opts.verbose, "Show verbose output");
cli.add_flag("--log-stderr", opts.log_stderr, "Log to stderr"); cli.add_flag("--log-stderr", opts.log_stderr, "Log to stderr");
cli.add_flag("--nocolor", opts.nocolor, "Don't show ANSI colors") cli.add_flag("--nocolor", opts.nocolor, "Don't show ANSI colors")
->default_val(default_no_color) ->default_val(Options::default_no_color())
->default_str(default_no_color ? "<true>" : "<false>"); ->default_str(Options::default_no_color() ? "<true>" : "<false>");
cli.add_flag("-d,--debug", opts.debug, "Run in debug mode") cli.add_flag("-d,--debug", opts.debug, "Run in debug mode")
->group(""/*always hide*/); ->group(""/*always hide*/);
} }

View File

@ -54,6 +54,13 @@ struct Options {
bool verbose; /**< verbose output */ bool verbose; /**< verbose output */
std::string muhome; /**< alternative mu dir */ std::string muhome; /**< alternative mu dir */
/**
* Whether by default, we should show color
*
* @return true or false
*/
static bool default_no_color();
enum struct SubCommand { enum struct SubCommand {
Add, Cfind, Extract, Fields, Find, Help, Index,Info, Init, Mkdir, Add, Cfind, Extract, Fields, Find, Help, Index,Info, Init, Mkdir,
Remove, Script, Server, Verify, View/*must be last*/ Remove, Script, Server, Verify, View/*must be last*/
@ -274,7 +281,6 @@ struct Options {
}; };
} // namepace Mu } // namepace Mu
#endif /* MU_OPTIONS_HH__ */ #endif /* MU_OPTIONS_HH__ */

View File

@ -1,5 +1,5 @@
/* /*
** Copyright (C) 2008-2022 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> ** Copyright (C) 2008-2023 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
** **
** This program is free software; you can redistribute it and/or modify it ** This program is free software; you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by the ** under the terms of the GNU General Public License as published by the
@ -33,6 +33,19 @@
using namespace Mu; using namespace Mu;
static void
output_error(const std::string& what, bool use_color)
{
using Color = MaybeAnsi::Color;
MaybeAnsi col{use_color};
std::cerr << col.fg(Color::Red) << "error" << col.reset() << ": "
<< col.fg(Color::BrightYellow)
<< what << "\n";
}
static int static int
handle_result(const Result<void>& res, const Mu::Options& opts) handle_result(const Result<void>& res, const Mu::Options& opts)
{ {
@ -43,11 +56,9 @@ handle_result(const Result<void>& res, const Mu::Options& opts)
MaybeAnsi col{!opts.nocolor}; MaybeAnsi col{!opts.nocolor};
// show the error and some help, but not if it's only a softerror. // show the error and some help, but not if it's only a softerror.
if (!res.error().is_soft_error()) { if (!res.error().is_soft_error())
std::cerr << col.fg(Color::Red) << "error" << col.reset() << ": " output_error(res.error().what(), !opts.nocolor);
<< col.fg(Color::BrightYellow) else
<< res.error().what() << "\n";
} else
std::cerr << col.fg(Color::BrightBlue) << res.error().what() << '\n'; std::cerr << col.fg(Color::BrightBlue) << res.error().what() << '\n';
std::cerr << col.fg(Color::Green); std::cerr << col.fg(Color::Green);
@ -82,13 +93,18 @@ main(int argc, char* argv[])
*/ */
const auto opts{Options::make(argc, argv)}; const auto opts{Options::make(argc, argv)};
if (!opts) { if (!opts) {
std::cerr << "error: " << opts.error().what() << "\n"; output_error(opts.error().what(), !Options::default_no_color());
return opts.error().exit_code(); return opts.error().exit_code();
} else if (!opts->sub_command) { } else if (!opts->sub_command) {
// nothing more to do. // nothing more to do.
return 0; return 0;
} }
/*
* there's a subcommand
*/
/* /*
* set up logging * set up logging
*/ */
@ -101,7 +117,7 @@ main(int argc, char* argv[])
const auto logger = Logger::make(opts->runtime_path(RuntimePath::LogFile), const auto logger = Logger::make(opts->runtime_path(RuntimePath::LogFile),
lopts); lopts);
if (!logger) { if (!logger) {
std::cerr << "error:" << logger.error().what() << "\n"; output_error(logger.error().what(), !opts->nocolor);
return logger.error().exit_code(); return logger.error().exit_code();
} }