diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b7aab5a..face43b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,7 +87,16 @@ `RTTI` ([#604](https://github.com/odygrd/quill/issues/604)) - Fixed an incorrectly triggered assertion in debug builds when `BackendOptions::log_timestamp_ordering_grace_period` is set to 0 ([#605](https://github.com/odygrd/quill/issues/605)) -- Fixed a compile-time error in `CsvWriter` that occurred when passing a custom `FrontendOptions` type as a template parameter. ([#609](https://github.com/odygrd/quill/issues/609)) +- Fixed a compile-time error in `CsvWriter` that occurred when passing a custom `FrontendOptions` type as a template + parameter. ([#609](https://github.com/odygrd/quill/issues/609)) +- Added `ConsoleColours::ColourMode` to `ConsoleSink`, allowing colors to be explicitly forced or conditionally enabled + based on the environment. Previously, colors were only conditionally + enabled. ([#611](https://github.com/odygrd/quill/issues/611)). + + For example: + ```cpp + quill::Frontend::create_or_get_sink( + "sink_id_1", quill::ConsoleColours::ColourMode::Automatic); ## v7.3.0 diff --git a/examples/console_logging.cpp b/examples/console_logging.cpp index 202aadbc..136a608e 100644 --- a/examples/console_logging.cpp +++ b/examples/console_logging.cpp @@ -24,7 +24,9 @@ int main() quill::Backend::start(backend_options); // Frontend - auto console_sink = quill::Frontend::create_or_get_sink("sink_id_1"); + auto console_sink = quill::Frontend::create_or_get_sink( + "sink_id_1", quill::ConsoleColours::ColourMode::Automatic); + quill::Logger* logger = quill::Frontend::create_or_get_logger("root", std::move(console_sink)); // Change the LogLevel to print everything diff --git a/include/quill/sinks/ConsoleSink.h b/include/quill/sinks/ConsoleSink.h index ceab81c4..25896a4f 100644 --- a/include/quill/sinks/ConsoleSink.h +++ b/include/quill/sinks/ConsoleSink.h @@ -54,7 +54,19 @@ class ConsoleColours using WORD = unsigned short; public: - ConsoleColours() { _colours.fill(white); } + enum class ColourMode + { + Always, + Automatic, + Never + }; + + ConsoleColours() + { + // by default _using_colours is false + _colours.fill(white); + } + ~ConsoleColours() = default; /** @@ -145,7 +157,21 @@ class ConsoleColours return is_atty && is_console; } - void _set_can_use_colours(FILE* file) noexcept { _can_use_colours = _is_in_terminal(file); } + void _set_can_use_colours(FILE* file, ColourMode colour_mode) noexcept + { + if (colour_mode == ColourMode::Always) + { + _can_use_colours = true; + } + else if (colour_mode == ColourMode::Automatic) + { + _can_use_colours = _is_in_terminal(file); + } + else + { + _can_use_colours = false; + } + } private: std::array _colours = {0}; /**< Colours per log level */ @@ -159,7 +185,18 @@ class ConsoleColours class ConsoleColours { public: - ConsoleColours() { _colours.fill(white); } + enum class ColourMode + { + Always, + Automatic, + Never + }; + + ConsoleColours() + { + // by default _using_colours is false + _colours.fill(white); + } ~ConsoleColours() = default; @@ -293,9 +330,21 @@ class ConsoleColours return ::isatty(fileno(file)) != 0; } - void _set_can_use_colours(FILE* file) noexcept + /***/ + void _set_can_use_colours(FILE* file, ColourMode colour_mode) noexcept { - _can_use_colours = _is_in_terminal(file) && _is_colour_terminal(); + if (colour_mode == ColourMode::Always) + { + _can_use_colours = true; + } + else if (colour_mode == ColourMode::Automatic) + { + _can_use_colours = _is_in_terminal(file) && _is_colour_terminal(); + } + else + { + _can_use_colours = false; + } } private: @@ -313,14 +362,19 @@ class ConsoleSink : public StreamSink * @brief Constructor * @param console_colours console colours instance * @param stream stream name can only be "stdout" or "stderr" + * @param colour_mode Determines when console colours are enabled. + * - Always: Colours are always enabled. + * - Automatic: Colours are enabled automatically based on the environment (e.g., terminal support). + * - Never: Colours are never enabled. */ - explicit ConsoleSink(ConsoleColours const& console_colours, std::string const& stream = "stdout") + explicit ConsoleSink(ConsoleColours const& console_colours, std::string const& stream = "stdout", + ConsoleColours::ColourMode colour_mode = ConsoleColours::ColourMode::Automatic) : StreamSink{stream, nullptr}, _console_colours(console_colours) { assert((stream == "stdout") || (stream == "stderr")); // In this ctor we take a full copy of console_colours and in our instance we modify it - _console_colours._set_can_use_colours(_file); + _console_colours._set_can_use_colours(_file, colour_mode); } /** @@ -335,7 +389,28 @@ class ConsoleSink : public StreamSink if (enable_colours) { - _console_colours._set_can_use_colours(_file); + _console_colours._set_can_use_colours(_file, ConsoleColours::ColourMode::Automatic); + _console_colours.set_default_colours(); + } + } + + /** + * @brief Constructor + * @param colour_mode Determines when console colours are enabled. + * - Always: Colours are always enabled. + * - Automatic: Colours are enabled automatically based on the environment (e.g., terminal support). + * - Never: Colours are never enabled. + * @param stream stream name can only be "stdout" or "stderr" + */ + explicit ConsoleSink(ConsoleColours::ColourMode colour_mode, std::string const& stream = "stdout") + : StreamSink{stream, nullptr} + { + assert((stream == "stdout") || (stream == "stderr")); + + _console_colours._set_can_use_colours(_file, colour_mode); + + if (colour_mode != ConsoleColours::ColourMode::Never) + { _console_colours.set_default_colours(); } }