125namespace rang_implementation {
141#if defined(OS_LINUX) || defined(OS_MAC)
143 static const bool result = [] {
145 = {
"ansi",
"color",
"console",
"cygwin",
"gnome",
146 "konsole",
"kterm",
"linux",
"msys",
"putty",
147 "rxvt",
"screen",
"vt100",
"xterm" };
149 const char *env_p = std::getenv(
"TERM");
150 if (env_p ==
nullptr) {
153 return std::any_of(std::begin(Terms), std::end(Terms),
154 [&](
const char *term) {
155 return std::strstr(env_p, term) !=
nullptr;
161 static constexpr bool result =
true;
169 inline bool isMsysPty(
int fd)
noexcept
172 const auto ptrGetFileInformationByHandleEx
173 =
reinterpret_cast<decltype(&GetFileInformationByHandleEx)
>(
174 GetProcAddress(GetModuleHandle(TEXT(
"kernel32.dll")),
175 "GetFileInformationByHandleEx"));
176 if (!ptrGetFileInformationByHandleEx) {
180 HANDLE h =
reinterpret_cast<HANDLE
>(_get_osfhandle(fd));
181 if (h == INVALID_HANDLE_VALUE) {
186 if (GetFileType(h) != FILE_TYPE_PIPE) {
192 struct MY_FILE_NAME_INFO {
193 DWORD FileNameLength;
194 WCHAR FileName[MAX_PATH];
197 auto pNameInfo = std::unique_ptr<MY_FILE_NAME_INFO>(
198 new (std::nothrow) MY_FILE_NAME_INFO());
205 if (!ptrGetFileInformationByHandleEx(h, FileNameInfo, pNameInfo.get(),
206 sizeof(MY_FILE_NAME_INFO))) {
209 std::wstring name(pNameInfo->FileName, pNameInfo->FileNameLength /
sizeof(WCHAR));
210 if ((name.find(L
"msys-") == std::wstring::npos
211 && name.find(L
"cygwin-") == std::wstring::npos)
212 || name.find(L
"-pty") == std::wstring::npos) {
226#if defined(OS_LINUX) || defined(OS_MAC)
227 if (osbuf == cout.rdbuf()) {
228 static const bool cout_term = isatty(fileno(stdout)) != 0;
230 }
else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
231 static const bool cerr_term = isatty(fileno(stderr)) != 0;
235 if (osbuf == cout.rdbuf()) {
236 static const bool cout_term
237 = (_isatty(_fileno(stdout)) || isMsysPty(_fileno(stdout)));
239 }
else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
240 static const bool cerr_term
241 = (_isatty(_fileno(stderr)) || isMsysPty(_fileno(stderr)));
248 template <
typename T>
250 std::is_same<T, rang::style>::value || std::is_same<T, rang::fg>::value
251 || std::is_same<T, rang::bg>::value || std::is_same<T, rang::fgB>::value
252 || std::is_same<T, rang::bgB>::value,
253 std::ostream &>::type;
267 enum class AttrColor : BYTE {
278 inline HANDLE getConsoleHandle(
const std::streambuf *osbuf)
noexcept
280 if (osbuf == std::cout.rdbuf()) {
281 static const HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
283 }
else if (osbuf == std::cerr.rdbuf() || osbuf == std::clog.rdbuf()) {
284 static const HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
287 return INVALID_HANDLE_VALUE;
290 inline bool setWinTermAnsiColors(
const std::streambuf *osbuf)
noexcept
292 HANDLE h = getConsoleHandle(osbuf);
293 if (h == INVALID_HANDLE_VALUE) {
297 if (!GetConsoleMode(h, &dwMode)) {
300 dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
301 if (!SetConsoleMode(h, dwMode)) {
307 inline bool supportsAnsi(
const std::streambuf *osbuf)
noexcept
312 if (osbuf == cout.rdbuf()) {
313 static const bool cout_ansi
314 = (isMsysPty(_fileno(stdout)) || setWinTermAnsiColors(osbuf));
316 }
else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
317 static const bool cerr_ansi
318 = (isMsysPty(_fileno(stderr)) || setWinTermAnsiColors(osbuf));
324 inline const SGR &defaultState() noexcept
326 static const SGR defaultSgr = []() -> SGR {
327 CONSOLE_SCREEN_BUFFER_INFO
info;
328 WORD attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
329 if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
331 || GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE),
333 attrib =
info.wAttributes;
335 SGR sgr = { 0, 0, 0, 0, FALSE, FALSE };
336 sgr.fgColor = attrib & 0x0F;
337 sgr.bgColor = (attrib & 0xF0) >> 4;
343 inline BYTE ansi2attr(BYTE rgb)
noexcept
345 static const AttrColor rev[8]
346 = { AttrColor::black, AttrColor::red, AttrColor::green,
347 AttrColor::yellow, AttrColor::blue, AttrColor::magenta,
348 AttrColor::cyan, AttrColor::gray };
349 return static_cast<BYTE
>(rev[rgb]);
352 inline void setWinSGR(
rang::bg col, SGR &state)
noexcept
355 state.bgColor = ansi2attr(
static_cast<BYTE
>(col) - 40);
357 state.bgColor = defaultState().bgColor;
361 inline void setWinSGR(
rang::fg col, SGR &state)
noexcept
364 state.fgColor = ansi2attr(
static_cast<BYTE
>(col) - 30);
366 state.fgColor = defaultState().fgColor;
370 inline void setWinSGR(
rang::bgB col, SGR &state)
noexcept
372 state.bgColor = (BACKGROUND_INTENSITY >> 4)
373 | ansi2attr(
static_cast<BYTE
>(col) - 100);
376 inline void setWinSGR(
rang::fgB col, SGR &state)
noexcept
379 = FOREGROUND_INTENSITY | ansi2attr(
static_cast<BYTE
>(col) - 90);
389 state.underline = BACKGROUND_INTENSITY;
397 inline SGR ¤t_state() noexcept
399 static SGR state = defaultState();
403 inline WORD SGR2Attr(
const SGR &state)
noexcept
408 attrib = (state.fgColor << 4) | state.fgColor;
410 attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
412 attrib = (state.bgColor << 4) | state.bgColor;
414 attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
416 }
else if (state.inverse) {
417 attrib = (state.fgColor << 4) | state.bgColor;
418 if (state.bold) attrib |= BACKGROUND_INTENSITY;
419 if (state.underline) attrib |= FOREGROUND_INTENSITY;
421 attrib = state.fgColor | (state.bgColor << 4) | state.bold
427 template <
typename T>
428 inline void setWinColorAnsi(std::ostream &os, T
const value)
430 os <<
"\033[" <<
static_cast<int>(
value) <<
"m";
433 template <
typename T>
434 inline void setWinColorNative(std::ostream &os, T
const value)
436 const HANDLE h = getConsoleHandle(os.rdbuf());
437 if (h != INVALID_HANDLE_VALUE) {
438 setWinSGR(value, current_state());
441 SetConsoleTextAttribute(h, SGR2Attr(current_state()));
445 template <
typename T>
446 inline enableStd<T>
setColor(std::ostream &os, T
const value)
449 if (supportsAnsi(os.rdbuf())) {
450 setWinColorAnsi(os, value);
452 setWinColorNative(os, value);
455 setWinColorAnsi(os, value);
457 setWinColorNative(os, value);
462 template <
typename T>
465 return os <<
"\033[" <<
static_cast<int>(value) <<
"m";