// This is a color lib made by cosf.
// Please include this text while using this lib.
// (2024-2-23 by cosf)
// Defined colors:
// black, red, green, yellow, blue, magenta,
// cyan, white, light_black, light_red,
// light_green, light_yellow, light_blue,
// light_magenta, light_cyan, light_white,
// reset.
//
// Defined function:
// endc(used by stream operators) (endl + reset)
// color(fore, back, light): to create a color with specified color values (ANSI).
// DEFINE_COLOR(name, fore, back, light): same as "Color name = color(fore, back, light);" but with static and const features.
//
// Settings:
// USE_COLOR : to determine whether to use color (1) or to set all color to "reset" (0).
// SET_ANSI_COLOR_IF_AVAILABLE: to determine whether to use ANSI meaning-transferring char codes to perform color (1) or not (0).
// REVERSE_COLOR : to determine whether to set the background to black (0) or white (1).
// USE_NAMESOACE : to determine whether to declare a namespace called "color" to store the variables (1) or not (0).
//
// Types & Classes:
// Color { int fore, back, light; }: a structure to store a color.
//
// Notice:
// ANSI codes and windows' text attributes are slightly different:
// color(31, 47, 0) may perform a white-based red color in ANSI codes,
// but it may perform a white-based blue color in windows' text attributes.
//
// (2024-2-23 by cosf)
#ifndef COLOR_LIB
#define COLOR_LIB
// These are settings
#define USE_COLOR 1
#if (defined(__WINDOWS_) || defined(_WIN32))
#define SET_ANSI_COLOR_IF_AVAILABLE 0
#else // (defined(__WINDOWS) || defined(_WIN32))
#define SET_ANSI_COLOR_IF_AVAILABLE 1 // do NOT set
#endif // (defined(__WINDOWS) || defined(_WIN32))
// settings end
#define REVERSE_COLOR 1
#define USE_NAMESPACE 1
#include <iostream>
#include <string>
#if (defined(__WINDOWS) || defined(_WIN32))
#include <windows.h>
#endif // (defined(__WINDOWS) || defined(_WIN32))
#if USE_NAMESPACE
namespace color
{
#endif // USE_NAMESPACE
struct Color
{
int fore, back, light;
};
static Color color(int fore, int back, int light)
{
return {fore, back, light};
}
#define DEFINE_COLOR(name, fore, back, light) static const Color name = {fore, back, light};
#if USE_COLOR
#if SET_ANSI_COLOR_IF_AVAILABLE
#if REVERSE_COLOR
DEFINE_COLOR(black, 30, 47, 0);
DEFINE_COLOR(red, 31, 47, 0);
DEFINE_COLOR(green, 32, 47, 0);
DEFINE_COLOR(yellow, 33, 47, 0);
DEFINE_COLOR(blue, 34, 47, 0);
DEFINE_COLOR(magenta, 35, 47, 0);
DEFINE_COLOR(cyan, 36, 47, 0);
DEFINE_COLOR(white, 37, 47, 0);
DEFINE_COLOR(light_black, 30, 47, 1);
DEFINE_COLOR(light_red, 31, 47, 1);
DEFINE_COLOR(light_green, 32, 47, 1);
DEFINE_COLOR(light_yellow, 33, 47, 1);
DEFINE_COLOR(light_blue, 34, 47, 1);
DEFINE_COLOR(light_magenta, 35, 47, 1);
DEFINE_COLOR(light_cyan, 36, 47, 1);
DEFINE_COLOR(light_white, 37, 47, 1);
#else // REVERSE_COLOR
DEFINE_COLOR(black, 30, 40, 0);
DEFINE_COLOR(red, 31, 40, 0);
DEFINE_COLOR(green, 32, 40, 0);
DEFINE_COLOR(yellow, 33, 40, 0);
DEFINE_COLOR(blue, 34, 40, 0);
DEFINE_COLOR(magenta, 35, 40, 0);
DEFINE_COLOR(cyan, 36, 40, 0);
DEFINE_COLOR(white, 37, 40, 0);
DEFINE_COLOR(light_black, 30, 40, 1);
DEFINE_COLOR(light_red, 31, 40, 1);
DEFINE_COLOR(light_green, 32, 40, 1);
DEFINE_COLOR(light_yellow, 33, 40, 1);
DEFINE_COLOR(light_blue, 34, 40, 1);
DEFINE_COLOR(light_magenta, 35, 40, 1);
DEFINE_COLOR(light_cyan, 36, 40, 1);
DEFINE_COLOR(light_white, 37, 40, 1);
#endif // REVERSE_COLOR
#else // SET_ANSI_COLOR_IF_AVAILABLE
#if REVERSE_COLOR
DEFINE_COLOR(black, 30, 47, 0);
DEFINE_COLOR(blue, 31, 47, 0);
DEFINE_COLOR(green, 32, 47, 0);
DEFINE_COLOR(cyan, 33, 47, 0);
DEFINE_COLOR(red, 34, 47, 0);
DEFINE_COLOR(magenta, 35, 47, 0);
DEFINE_COLOR(yellow, 36, 47, 0);
DEFINE_COLOR(white, 37, 47, 0);
DEFINE_COLOR(light_black, 30, 47, 1);
DEFINE_COLOR(light_blue, 31, 47, 1);
DEFINE_COLOR(light_green, 32, 47, 1);
DEFINE_COLOR(light_cyan, 33, 47, 1);
DEFINE_COLOR(light_red, 34, 47, 1);
DEFINE_COLOR(light_magenta, 35, 47, 1);
DEFINE_COLOR(light_yellow, 36, 47, 1);
DEFINE_COLOR(light_white, 37, 47, 1);
#else // REVERSE_COLOR
DEFINE_COLOR(black, 30, 40, 0);
DEFINE_COLOR(blue, 31, 40, 0);
DEFINE_COLOR(green, 32, 40, 0);
DEFINE_COLOR(cyan, 33, 40, 0);
DEFINE_COLOR(red, 34, 40, 0);
DEFINE_COLOR(magenta, 35, 40, 0);
DEFINE_COLOR(yellow, 36, 40, 0);
DEFINE_COLOR(white, 37, 40, 0);
DEFINE_COLOR(light_black, 30, 40, 1);
DEFINE_COLOR(light_blue, 31, 40, 1);
DEFINE_COLOR(light_green, 32, 40, 1);
DEFINE_COLOR(light_cyan, 33, 40, 1);
DEFINE_COLOR(light_red, 34, 40, 1);
DEFINE_COLOR(light_magenta, 35, 40, 1);
DEFINE_COLOR(light_yellow, 36, 40, 1);
DEFINE_COLOR(light_white, 37, 40, 1);
#endif // REVERSE_COLOR
#endif // SET_ANSI_COLOR_IF_AVAILABLE
#else // USE_COLOR
DEFINE_COLOR(black, 0, 0, 0);
DEFINE_COLOR(red, 0, 0, 0);
DEFINE_COLOR(green, 0, 0, 0);
DEFINE_COLOR(yellow, 0, 0, 0);
DEFINE_COLOR(blue, 0, 0, 0);
DEFINE_COLOR(magenta, 0, 0, 0);
DEFINE_COLOR(cyan, 0, 0, 0);
DEFINE_COLOR(white, 0, 0, 0);
DEFINE_COLOR(light_black, 0, 0, 0);
DEFINE_COLOR(light_red, 0, 0, 0);
DEFINE_COLOR(light_green, 0, 0, 0);
DEFINE_COLOR(light_yellow, 0, 0, 0);
DEFINE_COLOR(light_blue, 0, 0, 0);
DEFINE_COLOR(light_magenta, 0, 0, 0);
DEFINE_COLOR(light_cyan, 0, 0, 0);
DEFINE_COLOR(light_white, 0, 0, 0);
#endif // USE_COLOR
DEFINE_COLOR(reset, 0, 0, 0);
#if USE_NAMESPACE
}
#endif // USE_NAMESPACE
template <typename _CT, typename _T>
inline std::basic_ostream<_CT, _T> &operator<<(std::basic_ostream<_CT, _T> &os, color::Color cw)
{
#if SET_ANSI_COLOR_IF_AVAILABLE // UNABLE? TODO
os << std::string("\e[") + (cw.light ? "1;" : "") + std::to_string(cw.fore) + (cw.back != 47 ? ";" + std::to_string(cw.back) : "") + "m";
#elif (defined(__WINDOWS_) || defined(_WIN32))
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), (cw.fore - 30) | (cw.light << 3) | ((cw.back - 40) << 4));
#else // SET_ANSI_COLOR_IF_AVAILABLE || (defined(__WINDOWS_) || defined(_WIN32))
#error "Unable to use ansi color renderer or windows color renderer!"
#endif // SET_ANSI_COLOR_IF_AVAILABLE || (defined(__WINDOWS_) || defined(_WIN32))
return os;
}
#if USE_NAMESPACE
namespace color
{
#endif // USE_NAMESPACE
template <typename _CT, typename _T>
inline std::basic_ostream<_CT, _T> &endc(std::basic_ostream<_CT, _T> &os)
{
return os << reset << std::endl;
}
#if USE_NAMESPACE
}
#endif // USE_NAMESPACE
#endif // COLOR_LIB