A Minimal, Header only Modern c++ library for terminal goodies 💄✨

rang Build Status Build status codecov Download

Colors for your Terminal.

rang-demo

Windows Demo

rang-windows-demo

Example usage

#include "rang.hpp"

using namespace std;
using namespace rang;

int main()
{
    cout << "Plain old text"
         << style::bold << "Rang styled text!!"
         << style::reset << endl;
}

Dependencies

rang only depends on C++ standard library, unistd.h system header on unix and windows.h & io.h system headers on windows based systems. In other words, you don't need any 3rd party dependencies.

Installation

rang is a single header-only library. Put rang.hpp in the include folder directly into the project source tree or somewhere reachable from your project.

Or, if you use the conan package manager, follow these steps:

  1. Add a reference to rang to the requires section of your project's conanfile.txt file:

     [requires]
     rang/[email protected]/stable
    
  2. Run conan's install command:

     conan install
    

How to use

Rang uses iostream objects - cout/clog/cerr to apply attributes to output text. Since rang aims to support both windows and unix like systems, it takes care of the os specific details and tries to provide a uniform interface. Due to incompatiblities b/w different OS versions, not all kinds of attributes are supported on every system so rang will try to skip the ones which might produce garbage(instead of pushing random ANSI escape codes on your streams). Detection of tty is also handled internally so you don't need to check if application user might redirect output to a file.

Need support for non-ansi terminals? Check out Termdb which supports virtually all terminals and their capablities.

Apart from setting text attributes, you can also ask rang to override its default behaviour through these methods -

void rang::setControlMode(rang::control);

where rang::control takes

  • control::Auto - Automatically detects whether terminal supports color or not(Default)
  • control::Off - Turn off colors completely
  • control::Force - Force colors even if terminal doesn't supports them or output is redirected to non-terminal
void rang::setWinTermMode(rang::winTerm);

where rang::winTerm takes

  • winTerm::Auto - Checks for newer windows and picks Ansi otherwise falls back to Native(Default)
  • winTerm::Native - This method is supported in all versions of windows but supports less attributes
  • winTerm::Ansi - This method is supported in newer versions of windows and supports rich variety of attributes

Supported attributes with their compatiblity are listed below -

Text Styles:

Code Linux/Win/Others Old Win
rang::style::bold yes yes
rang::style::dim yes no
rang::style::italic yes no
rang::style::underline yes no
rang::style::blink no no
rang::style::rblink no no
rang::style::reversed yes yes
rang::style::conceal maybe yes
rang::style::crossed yes no

Text Color:

Code Linux/Win/Others Old Win
rang::fg::black yes yes
rang::fg::red yes yes
rang::fg::green yes yes
rang::fg::yellow yes yes
rang::fg::blue yes yes
rang::fg::magenta yes yes
rang::fg::cyan yes yes
rang::fg::gray yes yes

Background Color:

Code Linux/Win/Others Old Win
rang::bg::black yes yes
rang::bg::red yes yes
rang::bg::green yes yes
rang::bg::yellow yes yes
rang::bg::blue yes yes
rang::bg::magenta yes yes
rang::bg::cyan yes yes
rang::bg::gray yes yes

Bright Foreground Color:

Code Linux/Win/Others Old Win
rang::fgB::black yes yes
rang::fgB::red yes yes
rang::fgB::green yes yes
rang::fgB::yellow yes yes
rang::fgB::blue yes yes
rang::fgB::magenta yes yes
rang::fgB::cyan yes yes
rang::fgB::gray yes yes

Bright Background Color:

Code Linux/Win/Others Old Win
rang::bgB::black yes yes
rang::bgB::red yes yes
rang::bgB::green yes yes
rang::bgB::yellow yes yes
rang::bgB::blue yes yes
rang::bgB::magenta yes yes
rang::bgB::cyan yes yes
rang::bgB::gray yes yes

Reset Styles/Colors:

Code Linux/Win/Others Old Win
rang::style::reset yes yes
rang::fg::reset yes yes
rang::bg::reset yes yes

My terminal is not detected/gets garbage output!

Check your env variable TERM's value. Then open an issue here and make sure to mention TERM's value along with your terminal name.

Redirecting cout/cerr/clog rdbuf?

Rang doesn't interfere if you try to redirect cout/cerr/clog to somewhere else and leaves the decision to the library user. Make sure you've read this conversation and check out the example code here.

Comments
  • Feature: Unformatted Input

    Feature: Unformatted Input

    Note: This is work-in-progress code. There are things like printf statements and junk that are expected to be removed from the final commit. Also some things continue to be refactored between working commits.

  • Respect ANSICON environment variable on Windows

    Respect ANSICON environment variable on Windows

    If environment variable ANSICON is set on Windows, the console is capable of ANSI sequences, so preferably use them.

    What about this patch?

    --- a/include/rang.hpp +++ b/include/rang.hpp @@ -205,6 +205,7 @@ namespace rang_implementation { inline HANDLE getVersionDependentHandle() { if (IsWindowsVersionOrGreater(10, 0, 0)) return nullptr; + if (getenv("ANSICON")) return nullptr; return GetStdHandle(STD_OUTPUT_HANDLE); }

    Sorry for the formatting, it seems markup is mocking up ...

  • add support for windows<10 (issue #2)

    add support for windows<10 (issue #2)

    • Old behavior is preserved for windows >=10
    • Windows version is checked dynamically
    • Console handle is statically stored for windows <10

    A bit verbose perhaps, but should do the trick

  • MSVC not compiling when including

    MSVC not compiling when including "rang.hpp"

    I'm not sure what am I doing wrong but whenever I include "rang.hpp" outside of Main.cpp i get this compile error:

    error LNK2005: "void * __cdecl rang::rang_implementation::getVersionDependentHandle(void)" ([email protected][email protected]@@YAPAXXZ) already defined in [Wathever].obj

    Any idea what is happening ~~and how could I fix it~~?

  • Fixed work on Windows during resetting bg/fg color

    Fixed work on Windows during resetting bg/fg color

    1. Fixed work on Windows during resetting bg/fg color, fixes #66
    2. Added support of Windows 10 ANSI terminal sequences
    3. Code should be work on native windows terminals
  • add forceColor command which allows forcing color on non-tty devices

    add forceColor command which allows forcing color on non-tty devices

    Hey agauniyal, I tried my best at implementing the forceColor ostream modifier. I'm a first timer in PR's and would really appreciate if you could take a look and give me some criticism :smile:. I hope I didn't mess up too bad :sweat_smile:.

    Regarding the code, I don't really like to expose the getIword method, but I cannot think of any other way to give access to it.

    Hope this kind of helps and thanks in advance, benni012

  • Better CMake support

    Better CMake support

    This PR builds on the work of @zethon in #92 and a template I used for one of my projects

    • Basic package config file when installing the library
    • New CMakeLists.txt for the tests
    • CTest for test/test.cpp

    Hopefully, this makes integrating rang in other package managers (such as Hunter and Vcpkg) easier.

  • Remove use of std::atomics

    Remove use of std::atomics

    Originally we had fully threadsafe Linux only code but along the way I'm realizing most users need to synchronize text output by themselves(mutex over cout), hence removal of thread safe code.

  • Undocumented Behavior: Not Thread-Safe in C++11

    Undocumented Behavior: Not Thread-Safe in C++11

    The implementation of rang::rang_implementation::getIword() is not thread-safe in a strictly standards-compliant C++11 compiler. According to this thread-saftey for std::ios_base::xalloc was standardized in C++14. Please document the library as thread-unsafe for C++11 compilers or change the implementation to use a synchronization object when required.

  • avoid multiple pointer copies

    avoid multiple pointer copies

    Current approach of capturing initial pointer to cout/clog/cerr buffer requires multiple copies since each .cpp file that'll include it will have their own copy.

    But since the lib is using just 3 pointers within internal linkage, the overhead is almost negligible. But it can be resolved by providing static returns from function, see this stackoverflow question.

  • New release tag

    New release tag

    Is the code on master in a good state to be made into a new release? The last release is lacking the CMakeLists.txt file, so I'm forced to use master in my project when I pull this in. It'd be nice to have a release point to pull in instead.

  • A warning may be fixed

    A warning may be fixed

    When I used parameter -Wextra in g++, it gives a warning:

    [Warning] cast between incompatible function types from 'FARPROC' {aka 'long long int ()()'} to 'WINBOOL ()(HANDLE, FILE_INFO_BY_HANDLE_CLASS, LPVOID, DWORD)' {aka 'int ()(void, _FILE_INFO_BY_HANDLE_CLASS, void*, long unsigned int)'} [-Wcast-function-type]

    It's on line 175 in rang.hpp:

    inline bool isMsysPty(int fd) noexcept
        {
            // Dynamic load for binary compability with old Windows
            const auto ptrGetFileInformationByHandleEx
              = reinterpret_cast<decltype(&GetFileInformationByHandleEx)>(
                GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
                               "GetFileInformationByHandleEx"));
            if (!ptrGetFileInformationByHandleEx) {
                return false;
            }
    

    All the parameters I used under Windows 10 1903, g++ 8.1.0: g++ -std=c++2a -Wall -Wextra -Dlocal

  • [feature request] Please support true-color terminals

    [feature request] Please support true-color terminals

    For example, see how the awk script on this page prints a colorful line on text: https://gist.github.com/XVilka/8346728

    kde/gnome/xfce4 terminals now support true-color, and C++ interface can certainly support this functionality.

  • Created a RangBuffer class in response to (enhancement) issue #52

    Created a RangBuffer class in response to (enhancement) issue #52

    I created a RangBuffer class to store the display settings in an object. You might want to make a class 'buffer' inside rang namespace. It has setter functions to set the properties. This is how it works:

    RangBuffer rg;
    
    rg.setBgColor(rang::bg::cyan);
    rg.setFgBColor(rang::fgB::yellow);
    
    cout << rg << "hello world\n" << endl;
    rg.ignoreMySettings(cout);
    
    RangBuffer rg2;
    rg2.setBgBColor(rang::bgB::blue);
    cout << rg2 << "hello world\n";
    cout << rg << "This is my first contribution";
    

    There is a unique function RangBuffer::ignoreMysettings(std::ostream& os). It resets the ostream. So for example in the above code, the second line is displayed with a bright blue background and white foreground. Commenting that line will display the second line with a bright blue background and yellow colour (set by rg1).

    Now you might be wandering what's the difference between ignoreMySettings and reset()?

    • Reset resets the all the bitset (elementSet) to 0 in addition to resetting the terminal. So, after calling the clear function, it is as good as a new object.
    • IgnoreMySettings resets the terminal but does not reset the bitset. It means the next time the object is used to display using ostream.

    Plus, the design choice is such that say you have a common setting that the text you display is red, but at some point, you want red and the text to be bold, you can do this:

    RangBuffer rg;
    rg.setFgBColor(rang::fgB::red);
    
    cout << rang::style::bold << rg << "Hello world";
    rg.reset(cout);
    

    And it does all this without breaking code.

    I compiled my example on g++(version 8.2.1) and clang++(version 7.0) both on my Fedora 29. And it works as expected

  • storing color in variable

    storing color in variable

    Hi ! this is not an issue. I get inspired by your library. I need to store style and fg color in a variable for a postponed usage. Here is the idea:

    rang::color mycolor = std::pair(rang::red, rang::italic);
    std::cout << mycolor << "hello" << std::endl;
    

    So why not adding in your lib something like:

    struct color
      {
        color(rang::style style,
              rang::fg fg,
              rang::bg bg = rang::bg::reset)
          : m_style(style), m_fg(fg), m_bg(bg)
        {
        }
    
        rang::style m_style;
        rang::fg m_fg;
        rang::bg m_bg;
      };
    
    inline std::ostream& setColor(std::ostream &os, rang::color const c)
      {
        return os << "\033["
          << static_cast<int>(c.m_fg) << ';'
          << static_cast<int>(c.m_bg) << ';'
          << static_cast<int>(c.m_style) << "m";
      }
    

    A simple test code could be:

    #define ERROR_COLOR  rang::color(rang::style::bold, rang::fg::red)
    rang::color c = ERROR_COLOR;
    std::cout << c << "hello" << std::endl;
    

    I dunno what could be the best: std::pair (ugly and long syntax but can be used with constexpr) or struct (drawback: make copy). personally I would prefer something like red | italic (but can achieve easily). Other solution ?

    (Maybe your lib already can do this, in this case ignore my comment)

minimal but extensible header only implementation of photon mapping in C++
minimal but extensible header only implementation of photon mapping in C++

photon_mapping minimal but extensible header only implementation of photon mapping in C++. Features Direct illumination with explicit light sampling I

Oct 4, 2022
Tuibox - A single-header terminal UI (TUI) library, capable of creating mouse-driven, interactive applications on the command line.
Tuibox - A single-header terminal UI (TUI) library, capable of creating mouse-driven, interactive applications on the command line.

tuibox tuibox ("toybox") is a single-header terminal UI library, capable of creating mouse-driven, interactive applications on the command line. It is

Nov 9, 2022
The purpose of this project is to create a modern C++17 header-only interface to the FreeRTOS kernel API

FreeRTOS-Cpp The purpose of this project is to create a modern C++17 header-only interface to the FreeRTOS kernel API. Goals of this project include:

Nov 12, 2022
A very minimal & simple text editor written in C with only Standard C Library.
A very minimal & simple text editor written in C with only Standard C Library.

Texterm Text Editor A very minimal & simple text editor written in C with only Standard Library. Syntax highlighting supported for C JavaScript Python

Sep 22, 2022
Minimal, modern embedded V8 for Python.

Welcome to knight_v8 ?? Minimal, modern embedded V8 for Python. ?? Homepage Install pip install knight_v8 or: git clone https://github.com/Esbiya/knig

Feb 17, 2022
2D physics header-only library for videogames developed in C using raylib library.
2D physics header-only library for videogames developed in C using raylib library.

Physac Physac is a small 2D physics engine written in pure C. The engine uses a fixed time-step thread loop to simluate physics. A physics step contai

Nov 23, 2022
Library with useful output stream tools like: color and style manipulators, progress bars and terminal graphics.
Library with useful output stream tools like: color and style manipulators, progress bars and terminal graphics.

Library with useful output stream tools like: color and style manipulators, progress bars and terminal graphics Table of contents Introduction Documen

Nov 23, 2022
Lightweight Windows/Linux terminal control library for C/C++

TerControl Table of Contents About TerControl Features Installation Contributing License Contact Thanks TerControl is a lightweight opinion based term

Sep 3, 2022
A header-only library for C++(0x) that allows automagic pretty-printing of any container.

cxx-prettyprint =============== A pretty printing library for C++ containers. Synopsis: Simply by including this header-only library in your sourc

Nov 14, 2022
Cross-platform C++11 header-only library for memory mapped file IO

mio An easy to use header-only cross-platform C++11 memory mapping library with an MIT license. mio has been created with the goal to be easily includ

Nov 12, 2022
A C++ header-only library for creating, displaying, iterating and manipulating dates

The ASAP date/time library for beautiful C++ code ASAP is a small, header-only date-time library for C++11 and beyond. It is heavily inspired by my gr

Oct 26, 2022
AssociatedEnum: header-only library for C++ for enumerations with associated values

asenum AssociatedEnum is a header-only library for C++ for enumerations with associated values asenum is C++ implementation of very neat enums from Sw

Oct 30, 2022
A header only library that provides parser combinators to C++

This is an experimental C++ library for rapidly building parsers. It is inspired by parser combinators in haskell such as attoparsec and, like those libraries, allows for the construction of fully fledged parsers in a few lines of code.

Jul 24, 2022
Small and dirty header-only library that supports user input with some more advanced features than in the standard lib.

dirty-term Small and dirty header-only library that supports user input with some more advanced features than in the standard lib. This small, lightwe

Apr 24, 2022
Small Extremely Powerful Header Only C++ Lexical Analyzer/String Parser Library
Small Extremely Powerful Header Only C++ Lexical Analyzer/String Parser Library

lexpp Small Extremely Powerful Header Only C++ Lexical Analyzer/String Parser Library Lexpp is made with simplicity and size in mind. The entire libra

Jun 21, 2022
Header-only library providing unicode aware string support for C++

CsString Introduction CsString is a standalone library which provides unicode aware string support. The CsBasicString class is a templated class which

Aug 20, 2022
Header-only library to instrument scopes in C++

ScopeTimer Header Only Library How to use it? Easy cheesy: If you need milliseconds, just specify it and the compiler will do the rest of the work: #i

Nov 29, 2021
ServiceLocator - Service Locator Pattern Header-Only Library

Service Locator Very fast, header-only C++ Service Locator Pattern library What is the Service Locator Pattern The Service Locator Pattern is a design

Feb 21, 2022