From 393ab18520eb5019d00822ae744a4d4e65304226 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 8 Dec 2022 10:52:04 +0200 Subject: Add --[no]diag-color options (infrastructure only) --- bpkg/bpkg.cxx | 85 +++++++++++++++++++++++++++++++++++++++++++------------- bpkg/common.cli | 12 ++++++++ bpkg/utility.cxx | 3 +- bpkg/utility.hxx | 12 ++++++-- bpkg/utility.txx | 8 ++++++ 5 files changed, 97 insertions(+), 23 deletions(-) diff --git a/bpkg/bpkg.cxx b/bpkg/bpkg.cxx index 2a9fb6d..3ede99e 100644 --- a/bpkg/bpkg.cxx +++ b/bpkg/bpkg.cxx @@ -2,6 +2,8 @@ // license : MIT; see accompanying LICENSE file #include +#include // getenv() +#include // strcmp() #include #include // set_terminate(), terminate_handler #include // enable_if, is_base_of @@ -161,12 +163,15 @@ namespace bpkg init_diag (bc.verbosity, bo.silent (), - (bc.progress ? bc.progress : - co.progress () ? optional (true) : - co.no_progress () ? optional (false) : nullopt), + (bc.progress ? bc.progress : + co.progress () ? optional (true) : + co.no_progress () ? optional (false) : nullopt), + (bc.diag_color ? bc.diag_color : + co.diag_color () ? optional (true) : + co.no_diag_color () ? optional (false) : nullopt), bo.no_line (), bo.no_column (), - bpkg::stderr_term); + bpkg::stderr_term.has_value ()); // Note that we pretend to be in the serial-stop mode even though we may // build build system modules in parallel in order to get better @@ -465,31 +470,48 @@ init (const common_options& co, // Verify common options. // - // Also merge the --progress/--no-progress options, overriding a less - // specific flag with a more specific. + // Also merge the --*/--no-* options, overriding a less specific flag with + // a more specific. // - optional progress; - auto merge_progress = [&progress] - (const O& o, - const default_options_entry* e = nullptr) + // + optional progress, diag_color; + auto merge_no = [&progress, &diag_color] ( + const O& o, + const default_options_entry* e = nullptr) { - if (o.progress () && o.no_progress ()) { - diag_record dr; - (e != nullptr ? dr << fail (e->file) : dr << fail) + if (o.progress () && o.no_progress ()) + { + diag_record dr; + (e != nullptr ? dr << fail (e->file) : dr << fail) << "both --progress and --no-progress specified"; + } + + if (o.progress ()) + progress = true; + else if (o.no_progress ()) + progress = false; } - if (o.progress ()) - progress = true; - else if (o.no_progress ()) - progress = false; + { + if (o.diag_color () && o.no_diag_color ()) + { + diag_record dr; + (e != nullptr ? dr << fail (e->file) : dr << fail) + << "both --diag-color and --no-diag-color specified"; + } + + if (o.diag_color ()) + diag_color = true; + else if (o.no_diag_color ()) + diag_color = false; + } }; for (const default_options_entry& e: dos) - merge_progress (e.options, &e); + merge_no (e.options, &e); - merge_progress (o); + merge_no (o); o = merge_options (dos, o); @@ -498,6 +520,12 @@ init (const common_options& co, o.progress (*progress); o.no_progress (!*progress); } + + if (diag_color) + { + o.diag_color (*diag_color); + o.no_diag_color (!*diag_color); + } } catch (const invalid_argument& e) { @@ -544,7 +572,24 @@ try default_terminate = set_terminate (custom_terminate); - stderr_term = fdterm (stderr_fd ()); + if (fdterm (stderr_fd ())) + { + stderr_term = std::getenv ("TERM"); + + stderr_term_color = +#ifdef _WIN32 + // For now we disable color on Windows since it's unclear if/where/how + // it is supported. Maybe one day someone will figure this out. + // + false +#else + // This test was lifted from GCC (Emacs shell sets TERM=dumb). + // + *stderr_term != nullptr && strcmp (*stderr_term, "dumb") != 0 +#endif + ; + } + exec_dir = path (argv[0]).directory (); build2_argv0 = argv[0]; diff --git a/bpkg/common.cli b/bpkg/common.cli index ac045d0..d870a8d 100644 --- a/bpkg/common.cli +++ b/bpkg/common.cli @@ -134,6 +134,18 @@ namespace bpkg network transfers, building, etc." } + bool --diag-color + { + "Use color in diagnostics. If printing to a terminal the color is used + by default provided the terminal is not dumb. Use \cb{--no-diag-color} + to suppress." + } + + bool --no-diag-color + { + "Don't use color in diagnostics." + } + path --build { "", diff --git a/bpkg/utility.cxx b/bpkg/utility.cxx index 68d79ad..467e01f 100644 --- a/bpkg/utility.cxx +++ b/bpkg/utility.cxx @@ -161,7 +161,8 @@ namespace bpkg } } - bool stderr_term; + optional stderr_term = nullopt; + bool stderr_term_color = false; bool yn_prompt (const string& p, char d) diff --git a/bpkg/utility.hxx b/bpkg/utility.hxx index 342d608..1f5c725 100644 --- a/bpkg/utility.hxx +++ b/bpkg/utility.hxx @@ -152,9 +152,17 @@ namespace bpkg dir_path current_directory (); - // Progress. + // Diagnostics. // - extern bool stderr_term; // True if stderr is a terminal. + // If stderr is not a terminal, then the value is absent (so can be used as + // bool). Otherwise, it is the value of the TERM environment variable (which + // can be NULL). + // + extern optional stderr_term; + + // True if the color can be used on the stderr terminal. + // + extern bool stderr_term_color; // Y/N prompt. See butl::yn_prompt() for details (this is a thin wrapper). // diff --git a/bpkg/utility.txx b/bpkg/utility.txx index 47619c6..6113e4e 100644 --- a/bpkg/utility.txx +++ b/bpkg/utility.txx @@ -74,6 +74,14 @@ namespace bpkg if (no_progress) ops.push_back ("--no-progress"); + // Forward our --[no]diag-color options. + // + if (co.diag_color ()) + ops.push_back ("--diag-color"); + + if (co.no_diag_color ()) + ops.push_back ("--no-diag-color"); + return process_start_callback ( [] (const char* const args[], size_t n) { -- cgit v1.1