diff --git a/README.md b/README.md index 1ded07a1..9f2c7b99 100644 --- a/README.md +++ b/README.md @@ -1626,10 +1626,53 @@ std::cerr << toml::format_error("[error] value should be positive", hints, /*colorize = */ true) << std::endl; ``` -Note: It colorize `[error]` in red. That means that it detects `[error]` prefix +Note: It colorizes `[error]` in red. That means that it detects `[error]` prefix at the front of the error message. If there is no `[error]` prefix, `format_error` adds it to the error message. +Compared to the `TOML11_COLORIZE_ERROR_MESSAGE` macro that enables colorization +statically, toml11 provides `toml::color::enable` & `toml::color::disable` +functions to dynamically change the color mode. This feature overwrites +`TOML11_COLORIZE_ERROR_MESSAGE` and the `colorize` argument of +`toml::format_error` when you call `enable`. + +Note: If either `TOML11_COLORIZE_ERROR_MESSAGE` is defined or the `colorize` +argument is used, it takes precedence, meaning that `disable` won't work. +Accordingly, we highly recommend using only one of them. + +```cpp +toml::color::enable(); // enable colorization +toml::color::disable(); // disable colorization +``` + +If you use user-defined error message, you can manage the setting as follows: + +```cpp +toml::color::enable(); +std::cerr << toml::format_error("[error] value should be positive", + data.at("num"), "positive number required", + hints) << std::endl; // colorized + +toml::color::disable(); +std::cerr << toml::format_error("[error] value should be positive", + data.at("num"), "positive number required", + hints) << std::endl; // NOT colorized +``` + +Or you may use toml11 in your application like: + +```cpp +std::vector args(argv + 1, argv + argc); +auto result = std::find(args.begin(), args.end(), "--color"); +if (result != args.end()) { + toml::color::enable(); +} else { + toml::color::disable(); +} + +// use toml11 ... +``` + ## Opting out of the default `[error]` prefix toml11 prints error messages with the `[error]` prefix by default. diff --git a/toml/color.hpp b/toml/color.hpp index 4cb572cb..4b9ba398 100644 --- a/toml/color.hpp +++ b/toml/color.hpp @@ -17,11 +17,36 @@ namespace color_ansi { namespace detail { + inline int colorize_index() { static const int index = std::ios_base::xalloc(); return index; } + +// Control color mode globally +class color_mode { +public: + inline void enable() { + should_color_ = true; + } + inline void disable() { + should_color_ = false; + } + + inline bool should_color() const { + return should_color_; + } + + static color_mode& status() { + static color_mode status_; + return status_; + } + +private: + bool should_color_ = false; +}; + } // detail inline std::ostream& colorize(std::ostream& os) @@ -55,6 +80,18 @@ inline std::ostream& cyan (std::ostream& os) {if(os.iword(detail::colorize_index()) == 1) {os << "\033[36m";} return os;} inline std::ostream& white (std::ostream& os) {if(os.iword(detail::colorize_index()) == 1) {os << "\033[37m";} return os;} + +inline void enable() { + return detail::color_mode::status().enable(); +} +inline void disable() { + return detail::color_mode::status().disable(); +} + +inline bool should_color() { + return detail::color_mode::status().should_color(); +} + } // color_ansi // ANSI escape sequence is the only and default colorization method currently diff --git a/toml/source_location.hpp b/toml/source_location.hpp index c97d6f6c..135024fe 100644 --- a/toml/source_location.hpp +++ b/toml/source_location.hpp @@ -125,7 +125,7 @@ inline std::string format_underline(const std::string& message, std::ostringstream retval; - if(colorize) + if(color::should_color() || colorize) { retval << color::colorize; // turn on ANSI color }