ccmake: Improve coloring, allow customization

Change the default color for strings from BLUE (which is nearly
illegible on any terminals using the standard color palette which has
been around since at least CGA, almost 40 years ago) to CYAN. Add
ability to customize the colors via an environment variable (inspired by
LS_COLORS and using similar syntax).

Fixes: #20596
This commit is contained in:
Matthew Woehlke
2020-04-18 12:49:51 -04:00
committed by Brad King
parent f56a695440
commit 671fe28313
5 changed files with 104 additions and 5 deletions

View File

@@ -0,0 +1,34 @@
CCMAKE_COLORS
-------------
Determines what colors are used by the CMake curses interface,
when run on a terminal that supports colors.
The syntax follows the same conventions as ``LS_COLORS``;
that is, a list of key/value pairs separated by ``:``.
Keys are a single letter corresponding to a CMake cache variable type:
- ``s``: A ``STRING``.
- ``p``: A ``FILEPATH``.
- ``c``: A value which has an associated list of choices.
- ``y``: A ``BOOL`` which has a true-like value (e.g. ``ON``, ``YES``).
- ``n``: A ``BOOL`` which has a false-like value (e.g. ``OFF``, ``NO``).
Values are an integer number that specifies what color to use.
``0`` is black (you probably don't want to use that).
Others are determined by your terminal's color support.
Most (color) terminals will support at least 8 or 16 colors.
Some will support up to 256 colors. The colors will likely match
`this chart <https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg>`_,
although the first 16 colors may match the original
`CGA color palette <https://en.wikipedia.org/wiki/Color_Graphics_Adapter#Color_palette>`_.
(Many modern terminal emulators also allow their color palette,
at least for the first 16 colors, to be configured by the user.)
Note that fairly minimal checking is done for bad colors
(although a value higher than what curses believes your terminal supports
will be silently ignored) or bad syntax.
For example::
CCMAKE_COLORS='s=39:p=220:c=207:n=196:y=46'

View File

@@ -80,3 +80,11 @@ Environment Variables for CTest
/envvar/CTEST_PROGRESS_OUTPUT
/envvar/CTEST_USE_LAUNCHERS_DEFAULT
/envvar/DASHBOARD_TEST_FROM_CTEST
Environment Variables for the CMake curses interface
====================================================
.. toctree::
:maxdepth: 1
/envvar/CCMAKE_COLORS

View File

@@ -0,0 +1,5 @@
ccmake-custom-colors
--------------------
* :manual:`ccmake(1)` learned to read a :envvar:`CCMAKE_COLORS`
environment variable to customize colors.

View File

@@ -2,6 +2,12 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCursesColor.h"
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <unordered_map>
#include <utility>
#include "cmCursesStandardIncludes.h"
bool cmCursesColor::HasColors()
@@ -19,11 +25,54 @@ void cmCursesColor::InitColors()
if (HasColors()) {
start_color();
use_default_colors();
init_pair(cmCursesColor::BoolOff, COLOR_RED, -1);
init_pair(cmCursesColor::BoolOn, COLOR_GREEN, -1);
init_pair(cmCursesColor::String, COLOR_BLUE, -1);
init_pair(cmCursesColor::Path, COLOR_YELLOW, -1);
init_pair(cmCursesColor::Choice, COLOR_MAGENTA, -1);
init_pair(BoolOff, GetColor('N', COLOR_RED), -1);
init_pair(BoolOn, GetColor('Y', COLOR_GREEN), -1);
init_pair(String, GetColor('S', COLOR_CYAN), -1);
init_pair(Path, GetColor('P', COLOR_YELLOW), -1);
init_pair(Choice, GetColor('C', COLOR_MAGENTA), -1);
}
#endif
}
short cmCursesColor::GetColor(char id, short fallback)
{
static bool initialized = false;
static std::unordered_map<char, short> env;
if (!initialized) {
if (auto* v = getenv("CCMAKE_COLORS")) {
while (v[0] && v[1] && v[1] == '=') {
auto const n = std::toupper(*v);
char buffer[12];
memset(buffer, 0, sizeof(buffer));
if (auto* const e = strchr(v, ':')) {
if (static_cast<size_t>(e - v) > sizeof(buffer)) {
break;
}
strncpy(buffer, v + 2, static_cast<size_t>(e - v - 2));
v = e + 1;
} else {
auto const l = strlen(v);
if (l > sizeof(buffer)) {
break;
}
strncpy(buffer, v + 2, l - 2);
v += l;
}
auto const c = atoi(buffer);
if (c && c < COLORS) {
env.emplace(n, static_cast<short>(c));
}
}
}
initialized = true;
}
auto const iter = env.find(id);
return (iter == env.end() ? fallback : iter->second);
}

View File

@@ -19,6 +19,9 @@ public:
static bool HasColors();
static void InitColors();
protected:
static short GetColor(char id, short fallback);
};
#endif // cmCursesColor_h