mirror of
https://github.com/p-ranav/indicators.git
synced 2025-12-16 04:18:51 +08:00
Renamed project to indica
This commit is contained in:
6
include/indica/color.hpp
Normal file
6
include/indica/color.hpp
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include <indica/termcolor.hpp>
|
||||
|
||||
namespace indica {
|
||||
enum class Color { GREY, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE };
|
||||
}
|
||||
164
include/indica/progress_bar.hpp
Normal file
164
include/indica/progress_bar.hpp
Normal file
@@ -0,0 +1,164 @@
|
||||
#pragma once
|
||||
#include <atomic>
|
||||
#include <indica/color.hpp>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
namespace indica {
|
||||
|
||||
class ProgressBar {
|
||||
public:
|
||||
void set_foreground_color(Color color) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_foreground_color = color;
|
||||
}
|
||||
|
||||
void set_bar_width(size_t bar_width) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_bar_width = bar_width;
|
||||
}
|
||||
|
||||
void start_bar_with(const std::string &start) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_start = start;
|
||||
}
|
||||
|
||||
void fill_bar_progress_with(const std::string &fill) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_fill = fill;
|
||||
}
|
||||
|
||||
void lead_bar_progress_with(const std::string &lead) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_lead = lead;
|
||||
}
|
||||
|
||||
void fill_bar_remainder_with(const std::string &remainder) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_remainder = remainder;
|
||||
}
|
||||
|
||||
void end_bar_with(const std::string &end) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_end = end;
|
||||
}
|
||||
|
||||
void set_prefix_text(const std::string &text) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_prefix_text = text;
|
||||
}
|
||||
|
||||
void set_postfix_text(const std::string &text) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_postfix_text = text;
|
||||
if (_postfix_text.length() > _max_postfix_text_length)
|
||||
_max_postfix_text_length = _postfix_text.length();
|
||||
}
|
||||
|
||||
void show_percentage() { _show_percentage = true; }
|
||||
|
||||
void hide_percentage() { _show_percentage = false; }
|
||||
|
||||
void set_progress(float value) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_progress = value;
|
||||
}
|
||||
_print_progress();
|
||||
}
|
||||
|
||||
void tick() {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_progress += 1;
|
||||
}
|
||||
_print_progress();
|
||||
}
|
||||
|
||||
size_t current() {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
return std::min(static_cast<size_t>(_progress), size_t(100));
|
||||
}
|
||||
|
||||
bool is_completed() const { return _completed; }
|
||||
|
||||
void mark_as_completed() {
|
||||
_completed = true;
|
||||
_print_progress();
|
||||
}
|
||||
|
||||
private:
|
||||
float _progress{0.0};
|
||||
size_t _bar_width{100};
|
||||
std::string _prefix_text{""};
|
||||
std::string _start{"["};
|
||||
std::string _fill{"="};
|
||||
std::string _lead{">"};
|
||||
std::string _remainder{" "};
|
||||
std::string _end{"]"};
|
||||
std::string _postfix_text{""};
|
||||
std::atomic<size_t> _max_postfix_text_length{0};
|
||||
std::atomic<bool> _completed{false};
|
||||
std::atomic<bool> _show_percentage{true};
|
||||
std::mutex _mutex;
|
||||
Color _foreground_color;
|
||||
|
||||
void _print_progress() {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
std::cout << termcolor::bold;
|
||||
switch (_foreground_color) {
|
||||
case Color::GREY:
|
||||
std::cout << termcolor::grey;
|
||||
break;
|
||||
case Color::RED:
|
||||
std::cout << termcolor::red;
|
||||
break;
|
||||
case Color::GREEN:
|
||||
std::cout << termcolor::green;
|
||||
break;
|
||||
case Color::YELLOW:
|
||||
std::cout << termcolor::yellow;
|
||||
break;
|
||||
case Color::BLUE:
|
||||
std::cout << termcolor::blue;
|
||||
break;
|
||||
case Color::MAGENTA:
|
||||
std::cout << termcolor::magenta;
|
||||
break;
|
||||
case Color::CYAN:
|
||||
std::cout << termcolor::cyan;
|
||||
break;
|
||||
case Color::WHITE:
|
||||
std::cout << termcolor::white;
|
||||
break;
|
||||
}
|
||||
std::cout << _prefix_text;
|
||||
std::cout << _start;
|
||||
float pos = _progress * static_cast<float>(_bar_width) / 100.0;
|
||||
for (size_t i = 0; i < _bar_width; ++i) {
|
||||
if (i < pos)
|
||||
std::cout << _fill;
|
||||
else if (i == pos)
|
||||
std::cout << _lead;
|
||||
else
|
||||
std::cout << _remainder;
|
||||
}
|
||||
std::cout << _end;
|
||||
if (_show_percentage) {
|
||||
std::cout << " " << std::min(static_cast<size_t>(_progress), size_t(100)) << "%";
|
||||
}
|
||||
if (_max_postfix_text_length == 0)
|
||||
_max_postfix_text_length = 10;
|
||||
std::cout << " " << _postfix_text << std::string(_max_postfix_text_length, ' ') << "\r";
|
||||
std::cout.flush();
|
||||
if (_progress > 100.0) {
|
||||
_completed = true;
|
||||
}
|
||||
if (_completed)
|
||||
std::cout << termcolor::reset << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
133
include/indica/progress_spinner.hpp
Normal file
133
include/indica/progress_spinner.hpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#pragma once
|
||||
#include <atomic>
|
||||
#include <indica/color.hpp>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
namespace indica {
|
||||
|
||||
class ProgressSpinner {
|
||||
public:
|
||||
void set_foreground_color(Color color) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_foreground_color = color;
|
||||
}
|
||||
|
||||
void set_prefix_text(const std::string &text) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_prefix_text = text;
|
||||
}
|
||||
|
||||
void set_postfix_text(const std::string &text) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_postfix_text = text;
|
||||
if (_postfix_text.length() > _max_postfix_text_length)
|
||||
_max_postfix_text_length = _postfix_text.length();
|
||||
}
|
||||
|
||||
void show_percentage() { _show_percentage = true; }
|
||||
|
||||
void hide_percentage() { _show_percentage = false; }
|
||||
|
||||
void show_spinner() { _show_spinner = true; }
|
||||
|
||||
void hide_spinner() { _show_spinner = false; }
|
||||
|
||||
void set_progress(float value) {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_progress = value;
|
||||
}
|
||||
_print_progress();
|
||||
}
|
||||
|
||||
void tick() {
|
||||
{
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_progress += 1;
|
||||
}
|
||||
_print_progress();
|
||||
}
|
||||
|
||||
size_t current() {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
return std::min(static_cast<size_t>(_progress), size_t(100));
|
||||
}
|
||||
|
||||
bool is_completed() const { return _completed; }
|
||||
|
||||
void mark_as_completed() {
|
||||
_completed = true;
|
||||
_print_progress();
|
||||
}
|
||||
|
||||
void set_spinner_states(const std::vector<std::string>& states) {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
_states = states;
|
||||
}
|
||||
|
||||
private:
|
||||
float _progress{0.0};
|
||||
std::string _prefix_text{""};
|
||||
size_t _index{0};
|
||||
std::vector<std::string> _states{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"};
|
||||
std::string _postfix_text{""};
|
||||
std::atomic<size_t> _max_postfix_text_length{0};
|
||||
std::atomic<bool> _completed{false};
|
||||
std::atomic<bool> _show_percentage{true};
|
||||
std::atomic<bool> _show_spinner{true};
|
||||
std::mutex _mutex;
|
||||
Color _foreground_color;
|
||||
|
||||
void _print_progress() {
|
||||
std::unique_lock<std::mutex> lock{_mutex};
|
||||
std::cout << termcolor::bold;
|
||||
switch (_foreground_color) {
|
||||
case Color::GREY:
|
||||
std::cout << termcolor::grey;
|
||||
break;
|
||||
case Color::RED:
|
||||
std::cout << termcolor::red;
|
||||
break;
|
||||
case Color::GREEN:
|
||||
std::cout << termcolor::green;
|
||||
break;
|
||||
case Color::YELLOW:
|
||||
std::cout << termcolor::yellow;
|
||||
break;
|
||||
case Color::BLUE:
|
||||
std::cout << termcolor::blue;
|
||||
break;
|
||||
case Color::MAGENTA:
|
||||
std::cout << termcolor::magenta;
|
||||
break;
|
||||
case Color::CYAN:
|
||||
std::cout << termcolor::cyan;
|
||||
break;
|
||||
case Color::WHITE:
|
||||
std::cout << termcolor::white;
|
||||
break;
|
||||
}
|
||||
std::cout << _prefix_text;
|
||||
if (_show_spinner)
|
||||
std::cout << _states[_index % _states.size()];
|
||||
if (_show_percentage) {
|
||||
std::cout << " " << std::min(static_cast<size_t>(_progress), size_t(100)) << "%";
|
||||
}
|
||||
if (_max_postfix_text_length == 0)
|
||||
_max_postfix_text_length = 10;
|
||||
std::cout << " " << _postfix_text << std::string(_max_postfix_text_length, ' ') << "\r";
|
||||
std::cout.flush();
|
||||
_index += 1;
|
||||
if (_progress > 100.0) {
|
||||
_completed = true;
|
||||
}
|
||||
if (_completed)
|
||||
std::cout << termcolor::reset << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
447
include/indica/termcolor.hpp
Normal file
447
include/indica/termcolor.hpp
Normal file
@@ -0,0 +1,447 @@
|
||||
//!
|
||||
//! termcolor
|
||||
//! ~~~~~~~~~
|
||||
//!
|
||||
//! termcolor is a header-only c++ library for printing colored messages
|
||||
//! to the terminal. Written just for fun with a help of the Force.
|
||||
//!
|
||||
//! :copyright: (c) 2013 by Ihor Kalnytskyi
|
||||
//! :license: BSD, see LICENSE for details
|
||||
//!
|
||||
|
||||
#ifndef TERMCOLOR_HPP_
|
||||
#define 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 TERMCOLOR_OS_WINDOWS
|
||||
#elif defined(__APPLE__)
|
||||
#define TERMCOLOR_OS_MACOS
|
||||
#elif defined(__unix__) || defined(__unix)
|
||||
#define TERMCOLOR_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(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
#include <unistd.h>
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
namespace termcolor {
|
||||
// Forward declaration of the `_internal` namespace.
|
||||
// All comments are below.
|
||||
namespace _internal {
|
||||
// An index to be used to access a private storage of I/O streams. See
|
||||
// colorize / nocolorize I/O manipulators for details.
|
||||
static int colorize_index = std::ios_base::xalloc();
|
||||
|
||||
inline FILE *get_standard_stream(const std::ostream &stream);
|
||||
inline bool is_colorized(std::ostream &stream);
|
||||
inline bool is_atty(const std::ostream &stream);
|
||||
|
||||
#if defined(TERMCOLOR_OS_WINDOWS)
|
||||
inline void win_change_attributes(std::ostream &stream, int foreground, int background = -1);
|
||||
#endif
|
||||
} // namespace _internal
|
||||
|
||||
inline std::ostream &colorize(std::ostream &stream) {
|
||||
stream.iword(_internal::colorize_index) = 1L;
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &nocolorize(std::ostream &stream) {
|
||||
stream.iword(_internal::colorize_index) = 0L;
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &reset(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[00m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, -1, -1);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &bold(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[1m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &dark(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[2m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &italic(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[3m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &underline(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[4m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &blink(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[5m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &reverse(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[7m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &concealed(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[8m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &crossed(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[9m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &grey(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[30m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream,
|
||||
0 // grey (black)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &red(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[31m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, FOREGROUND_RED);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &green(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[32m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, FOREGROUND_GREEN);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &yellow(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[33m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, FOREGROUND_GREEN | FOREGROUND_RED);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &blue(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[34m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, FOREGROUND_BLUE);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &magenta(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[35m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_RED);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &cyan(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[36m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_GREEN);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &white(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[37m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &on_grey(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[40m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, -1,
|
||||
0 // grey (black)
|
||||
);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &on_red(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[41m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, -1, BACKGROUND_RED);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &on_green(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[42m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, -1, BACKGROUND_GREEN);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &on_yellow(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[43m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, -1, BACKGROUND_GREEN | BACKGROUND_RED);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &on_blue(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[44m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, -1, BACKGROUND_BLUE);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &on_magenta(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[45m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, -1, BACKGROUND_BLUE | BACKGROUND_RED);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &on_cyan(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[46m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, -1, BACKGROUND_GREEN | BACKGROUND_BLUE);
|
||||
#endif
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
inline std::ostream &on_white(std::ostream &stream) {
|
||||
if (_internal::is_colorized(stream)) {
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
stream << "\033[47m";
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
_internal::win_change_attributes(stream, -1,
|
||||
BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED);
|
||||
#endif
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
//! Since C++ hasn't a way to hide something in the header from
|
||||
//! the outer access, I have to introduce this namespace which
|
||||
//! is used for internal purpose and should't be access from
|
||||
//! the user code.
|
||||
namespace _internal {
|
||||
//! Since C++ hasn't a true way to extract stream handler
|
||||
//! from the a given `std::ostream` object, I have to write
|
||||
//! this kind of hack.
|
||||
inline FILE *get_standard_stream(const std::ostream &stream) {
|
||||
if (&stream == &std::cout)
|
||||
return stdout;
|
||||
else if ((&stream == &std::cerr) || (&stream == &std::clog))
|
||||
return stderr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Say whether a given stream should be colorized or not. It's always
|
||||
// true for ATTY streams and may be true for streams marked with
|
||||
// colorize flag.
|
||||
inline bool is_colorized(std::ostream &stream) {
|
||||
return is_atty(stream) || static_cast<bool>(stream.iword(colorize_index));
|
||||
}
|
||||
|
||||
//! Test whether a given `std::ostream` object refers to
|
||||
//! a terminal.
|
||||
inline bool is_atty(const std::ostream &stream) {
|
||||
FILE *std_stream = get_standard_stream(stream);
|
||||
|
||||
// Unfortunately, fileno() ends with segmentation fault
|
||||
// if invalid file descriptor is passed. So we need to
|
||||
// handle this case gracefully and assume it's not a tty
|
||||
// if standard stream is not detected, and 0 is returned.
|
||||
if (!std_stream)
|
||||
return false;
|
||||
|
||||
#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
|
||||
return ::isatty(fileno(std_stream));
|
||||
#elif defined(TERMCOLOR_OS_WINDOWS)
|
||||
return ::_isatty(_fileno(std_stream));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(TERMCOLOR_OS_WINDOWS)
|
||||
//! Change Windows Terminal colors attribute. If some
|
||||
//! parameter is `-1` then attribute won't changed.
|
||||
inline void win_change_attributes(std::ostream &stream, int foreground, int background) {
|
||||
// yeah, i know.. it's ugly, it's windows.
|
||||
static WORD defaultAttributes = 0;
|
||||
|
||||
// Windows doesn't have ANSI escape sequences and so we use special
|
||||
// API to change Terminal output color. That means we can't
|
||||
// manipulate colors by means of "std::stringstream" and hence
|
||||
// should do nothing in this case.
|
||||
if (!_internal::is_atty(stream))
|
||||
return;
|
||||
|
||||
// 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 // TERMCOLOR_OS_WINDOWS
|
||||
|
||||
} // namespace _internal
|
||||
|
||||
} // namespace termcolor
|
||||
|
||||
#undef TERMCOLOR_OS_WINDOWS
|
||||
#undef TERMCOLOR_OS_MACOS
|
||||
#undef TERMCOLOR_OS_LINUX
|
||||
|
||||
#endif // TERMCOLOR_HPP_
|
||||
Reference in New Issue
Block a user