Color Console
A lightweight header-only C++ library to bring colors to your Windows console with a very-easy-to-use API that frees you from the burden of setting and resetting screen colors every time you make a call.
Contents
Installation
Put color.hpp
in the folder where you include headers.
For Windows. C++11 support required. C++14 or above recommended.
Getting Started
#include "../include/color.hpp"
#include <iostream>
int main()
{
std::cout << dye::aqua("Hello, World!") << std::endl;
return 0;
}
You are seeing Hello, World!
in aqua.
Try saying Hello, World yourself.
Why Use It?
-
No need to reset : most solutions on the market work like manipulators, which constantly require you to reset the screen color after you set it. While this traditional approach is also offered in this library in the
hue
namespacecout << "When in doubt, wear " << hue::red << "red" << hue::reset << "." << endl;
it can be boring to do so. Why not just
dye
the objectcout << "When in doubt, wear " << dye::red("red") << "." << endl;
-
Object-oriented : you may
dye
an object and save it for later (re)useauto green = dye::green("green"); cout << "I saw "<< green << " trees, " << green << " bushes." << endl;
-
dye
anything :int
double
char
std::string
...cout << "Take the " << dye::blue("Blue") << " Line and then " << "catch Bus " << dye::yellow(42 + 7 % 8) << "."<< endl;
In fact, you can
dye
any object for whichoperator<<
is properly defined. Suppose we havestruct DoubleVector; ostream & operator<<(ostream &, const DoubleVector &);
we are free to
dye
cout << dye::purple(DoubleVector{3.14, 2.72}) << endl;
-
+
dyed objects, even colors differ :cout << dye::light_red('A') + dye::light_blue('B') + dye::light_green('C') << endl;
-
Extra support for strings : be it
std::string
or C-style strings, dyed or undyed, you can mix them up without caring about their types.const char ca[] = "ca"; string str = "str"; cout << "[ " + dye::aqua(ca) + " | " + dye::aqua(str) + " ]" << endl;
-
Convenient and extensible API : say
colorize
an object according to the parameter, or quicklyinvert
the colordouble a = 88.88; cout << dye::colorize(a, a >= 0 ? "red" : "green").invert() << endl;
Try the above cases yourself.
A Real Example
With Color Console, we implement an auto marker which highlights keywords given in a watch list and colorizes numbers as well. The key function is
using namespace std;
auto mark(const string & str, string color)
{
istringstream iss(str);
auto marked = dye::vanilla("");
for (string line; getline(iss, line); marked += "\n") {
istringstream lineiss(line);
for (string text; lineiss >> text; marked += " ") {
string pre, word, post;
// split a text into 3 parts: word in middle, and punctuations around it
separate(text, pre, word, post);
marked += pre;
if (is_keyword(word))
marked += dye::colorize(word, color).invert();
else if (is_number(word))
marked += dye::colorize(word, color);
else
marked += word;
marked += post;
}
}
return marked;
}
To mark the introductory paragraph of a tech news
cout << mark(tech_news, "light_red") << endl;
You will see
As another example in which we mark both keywords and numbers
cout << mark(stock_news, "yellow") << endl;
We are having
For the details, see the full implementation.
How to Use
Color Console offers two sets of solutions which are put separately in two namespaces
- objected-oriented
dye
(⭐ highly recommended ) - console-oriented, manipulator-like, traditional
hue
There are 16 single colors and thus 256 combinations (text + background) supported by Windows console.
Know the color tags and dye
your console (or change its hue
) immediately!
Color Tags
-
Single / Text
- Basic
black
blue
green
aqua
red
purple
yellow
white
grey
- Light
light_blue
light_green
light_aqua
light_red
light_purple
light_yellow
- Bright
bright_white
- Basic
-
Background
on_[single]
e.g.on_light_aqua
-
Compound
[single]_on_[single]
e.g.light_red_on_bright_white
-
Special
vanilla
do nothing i.e. stay in current console color
dye
Namespace
An object-oriented solution.
-
dye::color_tag(object)
generates a dyed object ready for colorized outputauto a = dye::on_yellow(42); cout << a << endl;
-
You may use
+
or+=
to make a chain of dyed objects. Colors may differ, so long as the types of the original objects stay the same.using vec = DoubleVector; auto b = dye::red(vec{1, 2, 3}); b = b + dye::blue(vec{4, 5, 6}); b += dye::green(vec{7, 8, 9}); cout << b << endl;
-
Rules for strings are even more flexible. You may
+
or+=
any compatible strings, even those undyed ones.cout << dye::on_white(string("strings")) + " are " + dye::on_white("more") + string(" flexible") << endl;
-
dye::colorize(object, color_tag)
dyesobject
withcolor_tag
cout << dye::colorize("grape", "purple") << endl;
-
dye::invert(dyed)
generates a new object in inverted color.dyed.invert()
does that in place.cout << dye::invert(dye::red("red")) << endl; auto contrast = dye::vanilla("contrast"); cout << contrast.invert() << endl;
Try the above cases yourself.
hue
Namespace
A console-oriented, manipulator-like, traditional solution.
-
cout << hue::color_tag
to set the text color tocolor_tag
-
cout << hue::reset
to reset the console color (to white text and black background)#include "../include/color.hpp" #include <iostream> int main() { std::cout << hue::light_red << hue::on_bright_white << "Hello, World" << hue::reset << std::endl; return 0; }
Try saying Hello, World in the traditional manner.
Note: Do remember to
reset
, otherwise you're causing troubles to late-users of the console.
Technical Note
- move semantics are widely used. Fast
+
operations are supported between dyed objects, especially for temporaries. Since more rvalues than lvalues are expected in use, we adopt a pass-by-value-and-move pattern. dye::red
and the like are in fact template factory functions that spit out dyed objects. Function template argument deduction is made use of to free users from having to specify the types explicitly (e.g.dye::red<std::string>("hello")
).- users shouldn't worry about the types of the dyed objects. If they want to, there are two layers of template classes: a
dye::item<T>
to hold a single object, and a containerdye::colorful<item<T>>
to holditem
(s).item
is intermediate and kept internally. Users are always usingcolorful
, of one or manyitem
(s). - a compile-time type-conversion technique (called
bar<T>
) is employed so that even function template argument deduction concludes it sees aconst char *
the dyed object generated would be based onstd::string
.