Program Listing for File console.hpp
↰ Return to documentation for file (include/ecl/console.hpp
)
#ifndef ecl_console_TERMCOLOR_HPP_
#define ecl_console_TERMCOLOR_HPP_
// the following snippet of code detects the current OS and
// defines the appropriate macro that is used to wrap some
// platform specific things
#if defined(_WIN32) || defined(_WIN64)
# define OS_WINDOWS
#elif defined(__APPLE__)
# define OS_MACOS
#elif defined(linux) || defined(__linux)
# define OS_LINUX
#else
# error "unsupported platform"
#endif
// This headers provides the `isatty()`/`fileno()` functions,
// which are used for testing whether a standart stream refers
// to the terminal. As for Windows, we also need WinApi funcs
// for changing colors attributes of the terminal.
#if defined(OS_MACOS) || defined(OS_LINUX)
# include <unistd.h>
#elif defined(OS_WINDOWS)
# include <io.h>
# include <windows.h>
#endif
#include <iostream>
#include <cstdio>
namespace ecl
{
// Forward declaration of the `console` namespace.
// All comments are below.
namespace console
{
inline FILE* get_standard_stream(const std::ostream& stream);
inline bool is_atty(const std::ostream& stream);
#if defined(OS_WINDOWS)
void win_change_attributes(std::ostream& stream, int foreground, int background=-1);
#endif
}
inline
std::ostream& reset(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[00m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream, -1, -1);
#endif
}
return stream;
}
inline
std::ostream& bold(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[1m";
#elif defined(OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& dark(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[2m";
#elif defined(OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& underline(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[4m";
#elif defined(OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& blink(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[5m";
#elif defined(OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& reverse(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[7m";
#elif defined(OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& concealed(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[8m";
#elif defined(OS_WINDOWS)
#endif
}
return stream;
}
inline
std::ostream& grey(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[30m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream,
0 // grey (black)
);
#endif
}
return stream;
}
inline
std::ostream& red(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[31m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream,
FOREGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& green(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[32m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream,
FOREGROUND_GREEN
);
#endif
}
return stream;
}
inline
std::ostream& yellow(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[33m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream,
FOREGROUND_GREEN | FOREGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& blue(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[34m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream,
FOREGROUND_BLUE
);
#endif
}
return stream;
}
inline
std::ostream& magenta(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[35m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream,
FOREGROUND_BLUE | FOREGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& cyan(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[36m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream,
FOREGROUND_BLUE | FOREGROUND_GREEN
);
#endif
}
return stream;
}
inline
std::ostream& white(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[37m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream,
FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& on_grey(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[40m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream, -1,
0 // grey (black)
);
#endif
}
return stream;
}
inline
std::ostream& on_red(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[41m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream, -1,
BACKGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& on_green(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[42m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream, -1,
BACKGROUND_GREEN
);
#endif
}
return stream;
}
inline
std::ostream& on_yellow(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[43m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream, -1,
BACKGROUND_GREEN | BACKGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& on_blue(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[44m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream, -1,
BACKGROUND_BLUE
);
#endif
}
return stream;
}
inline
std::ostream& on_magenta(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[45m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream, -1,
BACKGROUND_BLUE | BACKGROUND_RED
);
#endif
}
return stream;
}
inline
std::ostream& on_cyan(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[46m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream, -1,
BACKGROUND_GREEN | BACKGROUND_BLUE
);
#endif
}
return stream;
}
inline
std::ostream& on_white(std::ostream& stream)
{
if (console::is_atty(stream))
{
#if defined(OS_MACOS) || defined(OS_LINUX)
stream << "\033[47m";
#elif defined(OS_WINDOWS)
console::win_change_attributes(stream, -1,
BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED
);
#endif
}
return stream;
}
namespace console
{
inline
FILE* get_standard_stream(const std::ostream& stream)
{
if (&stream == &std::cout)
return stdout;
else if (&stream == &std::cerr)
return stderr;
return nullptr;
}
inline
bool is_atty(const std::ostream& stream)
{
// DJS : don't worry about strict checking so we can use this with
// stringstreams. Upstream issue at https://github.com/ikalnitsky/termcolor/issues/5
return true;
FILE* std_stream = get_standard_stream(stream);
#if defined(OS_MACOS) || defined(OS_LINUX)
return ::isatty(fileno(std_stream));
#elif defined(OS_WINDOWS)
return ::_isatty(_fileno(std_stream));
#endif
}
#if defined(OS_WINDOWS)
void win_change_attributes(std::ostream& stream, int foreground, int background)
{
// yeah, i know.. it's ugly, it's windows.
static WORD defaultAttributes = 0;
// get terminal handle
HANDLE hTerminal = INVALID_HANDLE_VALUE;
if (&stream == &std::cout)
hTerminal = GetStdHandle(STD_OUTPUT_HANDLE);
else if (&stream == &std::cerr)
hTerminal = GetStdHandle(STD_ERROR_HANDLE);
// save default terminal attributes if it unsaved
if (!defaultAttributes)
{
CONSOLE_SCREEN_BUFFER_INFO info;
if (!GetConsoleScreenBufferInfo(hTerminal, &info))
return;
defaultAttributes = info.wAttributes;
}
// restore all default settings
if (foreground == -1 && background == -1)
{
SetConsoleTextAttribute(hTerminal, defaultAttributes);
return;
}
// get current settings
CONSOLE_SCREEN_BUFFER_INFO info;
if (!GetConsoleScreenBufferInfo(hTerminal, &info))
return;
if (foreground != -1)
{
info.wAttributes &= ~(info.wAttributes & 0x0F);
info.wAttributes |= static_cast<WORD>(foreground);
}
if (background != -1)
{
info.wAttributes &= ~(info.wAttributes & 0xF0);
info.wAttributes |= static_cast<WORD>(background);
}
SetConsoleTextAttribute(hTerminal, info.wAttributes);
}
#endif // OS_WINDOWS
} // namespace console
} // namespace ecl
#undef OS_WINDOWS
#undef OS_MACOS
#undef OS_LINUX
#endif // ecl_console_TERMCOLOR_HPP_