4#if defined(__unix__) || defined(__unix) || defined(__linux__)
6#elif defined(WIN32) || defined(_WIN32) || defined(_WIN64)
8#elif defined(__APPLE__) || defined(__MACH__)
11#error Unknown Platform
14#if defined(OS_LINUX) || defined(OS_MAC)
19#if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x0600)
21 "Please include rang.hpp before any windows system headers or set _WIN32_WINNT at least to _WIN32_WINNT_VISTA"
22#elif !defined(_WIN32_WINNT)
23#define _WIN32_WINNT _WIN32_WINNT_VISTA
33#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
34#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
125namespace rang_implementation {
138#if defined(OS_LINUX) || defined(OS_MAC)
140 static const bool result = [] {
141 const char* Terms[] = {
"ansi",
"color",
"console",
"cygwin",
"gnome",
"konsole",
"kterm",
142 "linux",
"msys",
"putty",
"rxvt",
"screen",
"vt100",
"xterm"};
144 const char* env_p = std::getenv(
"TERM");
145 if (env_p ==
nullptr) {
148 return std::any_of(std::begin(Terms), std::end(Terms),
149 [&](
const char* term) {
return std::strstr(env_p, term) !=
nullptr; });
154 static constexpr bool result =
true;
161 inline bool isMsysPty(
int fd)
noexcept {
163 const auto ptrGetFileInformationByHandleEx =
164 reinterpret_cast<decltype(&GetFileInformationByHandleEx)
>(
165 GetProcAddress(GetModuleHandle(TEXT(
"kernel32.dll")),
"GetFileInformationByHandleEx"));
166 if (!ptrGetFileInformationByHandleEx) {
170 HANDLE h =
reinterpret_cast<HANDLE
>(_get_osfhandle(fd));
171 if (h == INVALID_HANDLE_VALUE) {
176 if (GetFileType(h) != FILE_TYPE_PIPE) {
182 struct MY_FILE_NAME_INFO {
183 DWORD FileNameLength;
184 WCHAR FileName[MAX_PATH];
187 auto pNameInfo = std::unique_ptr<MY_FILE_NAME_INFO>(
new (std::nothrow) MY_FILE_NAME_INFO());
194 if (!ptrGetFileInformationByHandleEx(h, FileNameInfo, pNameInfo.get(),
195 sizeof(MY_FILE_NAME_INFO))) {
198 std::wstring
name(pNameInfo->FileName, pNameInfo->FileNameLength /
sizeof(WCHAR));
199 if ((
name.find(
L"msys-") == std::wstring::npos &&
200 name.find(
L"cygwin-") == std::wstring::npos) ||
201 name.find(
L"-pty") == std::wstring::npos) {
210 inline bool isTerminal(
const std::streambuf* osbuf)
noexcept {
214#if defined(OS_LINUX) || defined(OS_MAC)
215 if (osbuf == cout.rdbuf()) {
216 static const bool cout_term = isatty(
fileno(
stdout)) != 0;
218 }
else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
219 static const bool cerr_term = isatty(
fileno(
stderr)) != 0;
223 if (osbuf == cout.rdbuf()) {
224 static const bool cout_term = (_isatty(_fileno(
stdout)) || isMsysPty(_fileno(
stdout)));
226 }
else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
227 static const bool cerr_term = (_isatty(_fileno(
stderr)) || isMsysPty(_fileno(
stderr)));
234 template <
typename T>
236 std::is_same<T, rang::style>::value || std::is_same<T, rang::fg>::value ||
237 std::is_same<T, rang::bg>::value || std::is_same<T, rang::fgB>::value ||
238 std::is_same<T, rang::bgB>::value,
239 std::ostream&>::type;
252 enum class AttrColor : BYTE {
263 inline HANDLE getConsoleHandle(
const std::streambuf* osbuf)
noexcept {
264 if (osbuf == std::cout.rdbuf()) {
265 static const HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
267 }
else if (osbuf == std::cerr.rdbuf() || osbuf == std::clog.rdbuf()) {
268 static const HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
271 return INVALID_HANDLE_VALUE;
274 inline bool setWinTermAnsiColors(
const std::streambuf* osbuf)
noexcept {
275 HANDLE h = getConsoleHandle(osbuf);
276 if (h == INVALID_HANDLE_VALUE) {
280 if (!GetConsoleMode(h, &dwMode)) {
283 dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
284 if (!SetConsoleMode(h, dwMode)) {
290 inline bool supportsAnsi(
const std::streambuf* osbuf)
noexcept {
294 if (osbuf == cout.rdbuf()) {
295 static const bool cout_ansi = (isMsysPty(_fileno(
stdout)) || setWinTermAnsiColors(osbuf));
297 }
else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
298 static const bool cerr_ansi = (isMsysPty(_fileno(
stderr)) || setWinTermAnsiColors(osbuf));
304 inline const SGR& defaultState() noexcept {
305 static const SGR defaultSgr = []() -> SGR {
306 CONSOLE_SCREEN_BUFFER_INFO
info;
307 WORD attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
308 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info) ||
309 GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &info)) {
310 attrib =
info.wAttributes;
312 SGR sgr = {0, 0, 0, 0, FALSE, FALSE};
313 sgr.fgColor = attrib & 0x0F;
314 sgr.bgColor = (attrib & 0xF0) >> 4;
320 inline BYTE ansi2attr(BYTE rgb)
noexcept {
321 static const AttrColor rev[8] = {AttrColor::black, AttrColor::red, AttrColor::green,
322 AttrColor::yellow, AttrColor::blue, AttrColor::magenta,
323 AttrColor::cyan, AttrColor::gray};
324 return static_cast<BYTE
>(rev[rgb]);
327 inline void setWinSGR(
rang::bg col, SGR& state)
noexcept {
329 state.bgColor = ansi2attr(
static_cast<BYTE
>(col) - 40);
331 state.bgColor = defaultState().bgColor;
335 inline void setWinSGR(
rang::fg col, SGR& state)
noexcept {
337 state.fgColor = ansi2attr(
static_cast<BYTE
>(col) - 30);
339 state.fgColor = defaultState().fgColor;
343 inline void setWinSGR(
rang::bgB col, SGR& state)
noexcept {
344 state.bgColor = (BACKGROUND_INTENSITY >> 4) | ansi2attr(
static_cast<BYTE
>(col) - 100);
347 inline void setWinSGR(
rang::fgB col, SGR& state)
noexcept {
348 state.fgColor = FOREGROUND_INTENSITY | ansi2attr(
static_cast<BYTE
>(col) - 90);
354 state = defaultState();
357 state.bold = FOREGROUND_INTENSITY;
361 state.underline = BACKGROUND_INTENSITY;
364 state.inverse = TRUE;
367 state.conceal = TRUE;
374 inline SGR& current_state() noexcept {
375 static SGR state = defaultState();
379 inline WORD SGR2Attr(
const SGR& state)
noexcept {
383 attrib = (state.fgColor << 4) | state.fgColor;
384 if (state.bold) attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
386 attrib = (state.bgColor << 4) | state.bgColor;
387 if (state.underline) attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
389 }
else if (state.inverse) {
390 attrib = (state.fgColor << 4) | state.bgColor;
391 if (state.bold) attrib |= BACKGROUND_INTENSITY;
392 if (state.underline) attrib |= FOREGROUND_INTENSITY;
394 attrib = state.fgColor | (state.bgColor << 4) | state.bold | state.underline;
399 template <
typename T>
400 inline void setWinColorAnsi(std::ostream&
os,
T const value) {
401 os <<
"\033[" <<
static_cast<int>(
value) <<
"m";
404 template <
typename T>
405 inline void setWinColorNative(std::ostream&
os,
T const value) {
406 const HANDLE h = getConsoleHandle(
os.rdbuf());
407 if (h != INVALID_HANDLE_VALUE) {
408 setWinSGR(
value, current_state());
411 SetConsoleTextAttribute(h, SGR2Attr(current_state()));
415 template <
typename T>
418 if (supportsAnsi(
os.rdbuf())) {
431 template <
typename T>
433 return os <<
"\033[" <<
static_cast<int>(
value) <<
"m";
_RWSTD_DLLIMPORT int() fileno(FILE *) _LIBC_THROWS()
std::ostream & info() noexcept
replacement for std::cout for NeBuild logging.
std::atomic< winTerm > & winTermMode() noexcept
bool supportsColor() noexcept
std::atomic< control > & controlMode() noexcept
typename std::enable_if< std::is_same< T, rang::style >::value||std::is_same< T, rang::fg >::value||std::is_same< T, rang::bg >::value||std::is_same< T, rang::fgB >::value||std::is_same< T, rang::bgB >::value, std::ostream & >::type enableStd
enableStd< T > setColor(std::ostream &os, T const value)
bool isTerminal(const std::streambuf *osbuf) noexcept
void setWinTermMode(const rang::winTerm value) noexcept
rang_implementation::enableStd< T > operator<<(std::ostream &os, const T value)
void setControlMode(const control value) noexcept