From 4194f17440e98011c800baee73e55ceefa79655b Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Wed, 18 Jan 2023 00:14:02 +0200 Subject: [PATCH] mu: allow color in early command errors --- mu/mu-options.cc | 23 ++++++++++++++--------- mu/mu-options.hh | 8 +++++++- mu/mu.cc | 32 ++++++++++++++++++++++++-------- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/mu/mu-options.cc b/mu/mu-options.cc index 8737d561..d116511a 100644 --- a/mu/mu-options.cc +++ b/mu/mu-options.cc @@ -1,5 +1,5 @@ /* -** Copyright (C) 2022 Dirk-Jan C. Binnema +** Copyright (C) 2022-2023 Dirk-Jan C. Binnema ** ** 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 @@ -594,24 +594,29 @@ cmd_help(const CLI::App& app, Options& opts) "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 add_global_options(CLI::App& cli, Options& opts) { - static const auto default_no_color = - !::isatty(::fileno(stdout)) || - !::isatty(::fileno(stderr)) || - ::getenv("NO_COLOR") != NULL; - opts.nocolor = default_no_color; - + opts.nocolor = Options::default_no_color(); errno = 0; cli.add_flag("-q,--quiet", opts.quiet, "Hide non-essential 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("--nocolor", opts.nocolor, "Don't show ANSI colors") - ->default_val(default_no_color) - ->default_str(default_no_color ? "" : ""); + ->default_val(Options::default_no_color()) + ->default_str(Options::default_no_color() ? "" : ""); cli.add_flag("-d,--debug", opts.debug, "Run in debug mode") ->group(""/*always hide*/); } diff --git a/mu/mu-options.hh b/mu/mu-options.hh index 04eff1f0..79366177 100644 --- a/mu/mu-options.hh +++ b/mu/mu-options.hh @@ -54,6 +54,13 @@ struct Options { bool verbose; /**< verbose output */ 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 { Add, Cfind, Extract, Fields, Find, Help, Index,Info, Init, Mkdir, Remove, Script, Server, Verify, View/*must be last*/ @@ -274,7 +281,6 @@ struct Options { }; - } // namepace Mu #endif /* MU_OPTIONS_HH__ */ diff --git a/mu/mu.cc b/mu/mu.cc index 6c790fb1..f119f95b 100644 --- a/mu/mu.cc +++ b/mu/mu.cc @@ -1,5 +1,5 @@ /* -** Copyright (C) 2008-2022 Dirk-Jan C. Binnema +** Copyright (C) 2008-2023 Dirk-Jan C. Binnema ** ** 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 @@ -33,6 +33,19 @@ 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 handle_result(const Result& res, const Mu::Options& opts) { @@ -43,11 +56,9 @@ handle_result(const Result& res, const Mu::Options& opts) MaybeAnsi col{!opts.nocolor}; // show the error and some help, but not if it's only a softerror. - if (!res.error().is_soft_error()) { - std::cerr << col.fg(Color::Red) << "error" << col.reset() << ": " - << col.fg(Color::BrightYellow) - << res.error().what() << "\n"; - } else + if (!res.error().is_soft_error()) + output_error(res.error().what(), !opts.nocolor); + else std::cerr << col.fg(Color::BrightBlue) << res.error().what() << '\n'; std::cerr << col.fg(Color::Green); @@ -82,13 +93,18 @@ main(int argc, char* argv[]) */ const auto opts{Options::make(argc, argv)}; if (!opts) { - std::cerr << "error: " << opts.error().what() << "\n"; + output_error(opts.error().what(), !Options::default_no_color()); return opts.error().exit_code(); } else if (!opts->sub_command) { // nothing more to do. return 0; } + /* + * there's a subcommand + */ + + /* * set up logging */ @@ -101,7 +117,7 @@ main(int argc, char* argv[]) const auto logger = Logger::make(opts->runtime_path(RuntimePath::LogFile), lopts); if (!logger) { - std::cerr << "error:" << logger.error().what() << "\n"; + output_error(logger.error().what(), !opts->nocolor); return logger.error().exit_code(); }