Program Listing for File rang.hxx¶
↰ Return to documentation for file (Utils/rang.hxx)
/*\
Taken from: https://github.com/agauniyal/rang/blob/master/include/rang.hpp
\*/
#include <algorithm>
#include <atomic>
#include <cstdlib>
#include <cstring>
#include <iostream>
namespace rang {
#ifndef DOXYGEN_SHOULD_SKIP_THIS
using std::ostream;
#endif
/* For better compability with most of terminals do not use any style settings
* except of reset, bold and reversed.
* Note that on Windows terminals bold style is same as fgB color.
*/
enum class style {
reset = 0,
bold = 1,
dim = 2,
italic = 3,
underline = 4,
blink = 5,
rblink = 6,
reversed = 7,
conceal = 8,
crossed = 9
};
enum class fg {
black = 30,
red = 31,
green = 32,
yellow = 33,
blue = 34,
magenta = 35,
cyan = 36,
gray = 37,
reset = 39
};
enum class bg {
black = 40,
red = 41,
green = 42,
yellow = 43,
blue = 44,
magenta = 45,
cyan = 46,
gray = 47,
reset = 49
};
enum class fgB {
black = 90,
red = 91,
green = 92,
yellow = 93,
blue = 94,
magenta = 95,
cyan = 96,
gray = 97
};
enum class bgB {
black = 100,
red = 101,
green = 102,
yellow = 103,
blue = 104,
magenta = 105,
cyan = 106,
gray = 107
};
enum class control { // Behaviour of rang function calls
Off = 0, // toggle off rang style/color calls
Auto = 1, // (Default) autodect terminal and colorize if needed
Force = 2 // force ansi color output to non terminal streams
};
// Use rang::setControlMode to set rang control mode
enum class winTerm { // Windows Terminal Mode
Auto = 0, // (Default) automatically detects wheter Ansi or Native API
Ansi = 1, // Force use Ansi API
Native = 2 // Force use Native API
};
// Use rang::setWinTermMode to explicitly set terminal API for Windows
// Calling rang::setWinTermMode have no effect on other OS
#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace rang_implementation {
#ifndef DOXYGEN_SHOULD_SKIP_THIS
using std::atomic;
using std::enable_if;
using std::is_same;
using std::ostream;
using std::streambuf;
#endif
inline
atomic<control> &
controlMode() noexcept {
static atomic<control> value(control::Auto);
return value;
}
inline
atomic<winTerm> &
winTermMode() noexcept {
static atomic<winTerm> termMode(winTerm::Auto);
return termMode;
}
template <typename T>
using enableStd = typename enable_if<
is_same<T, rang::style>::value ||
is_same<T, rang::fg>::value ||
is_same<T, rang::bg>::value ||
is_same<T, rang::fgB>::value ||
is_same<T, rang::bgB>::value,
ostream &
>::type;
extern bool isTerminal( streambuf const * ) noexcept;
extern bool supportsAnsi( streambuf const * ) noexcept;
extern bool supportsColor() noexcept;
#ifdef UTILS_OS_WINDOWS
template <typename T>
inline
void
setWinColorAnsi( ostream &os, T const value ) {
os << "\033[" << static_cast<int>(value) << "m";
}
void setWinColorNative( ostream &os, enum rang::style value );
void setWinColorNative( ostream &os, enum rang::bg value );
void setWinColorNative( ostream &os, enum rang::fg value );
void setWinColorNative( ostream &os, enum rang::bgB value );
void setWinColorNative( ostream &os, enum rang::fgB value );
template <typename T>
inline
enableStd<T>
setColor( ostream &os, T const value ) {
if (winTermMode() == winTerm::Auto) {
if (supportsAnsi(os.rdbuf())) {
setWinColorAnsi(os, value);
} else {
setWinColorNative(os, value);
}
} else if (winTermMode() == winTerm::Ansi) {
setWinColorAnsi(os, value);
} else {
setWinColorNative(os, value);
}
return os;
}
#else
template <typename T>
inline
enableStd<T>
setColor( ostream &os, T const value ) {
return os << "\033[" << static_cast<int>(value) << "m";
}
#endif
} // namespace rang_implementation
template <typename T>
inline
rang_implementation::enableStd<T>
operator << ( ostream &os, T const value ) {
control const option = rang_implementation::controlMode();
switch (option) {
case control::Auto:
return rang_implementation::supportsColor()
&& rang_implementation::isTerminal(os.rdbuf())
? rang_implementation::setColor(os, value)
: os;
case control::Force:
return rang_implementation::setColor(os, value);
default:
return os;
}
}
inline
void
setWinTermMode( rang::winTerm const value ) noexcept {
rang_implementation::winTermMode() = value;
}
inline
void
setControlMode( control const value ) noexcept {
rang_implementation::controlMode() = value;
}
#endif
} // namespace rang