diff --git a/include/spdlog/details/log_msg.h b/include/spdlog/details/log_msg.h index 834ca4df..372f2bf9 100644 --- a/include/spdlog/details/log_msg.h +++ b/include/spdlog/details/log_msg.h @@ -22,8 +22,8 @@ struct SPDLOG_API log_msg size_t thread_id{0}; // wrapping the formatted text with color (updated by pattern_formatter). - mutable size_t color_range_start{0}; - mutable size_t color_range_end{0}; + mutable std::vector color_range_start; + mutable std::vector color_range_end; source_loc source; string_view_t payload; diff --git a/include/spdlog/pattern_formatter-inl.h b/include/spdlog/pattern_formatter-inl.h index e68b91be..c2801364 100644 --- a/include/spdlog/pattern_formatter-inl.h +++ b/include/spdlog/pattern_formatter-inl.h @@ -734,7 +734,7 @@ public: void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { - msg.color_range_start = dest.size(); + msg.color_range_start.push_back(dest.size()); } }; @@ -747,7 +747,7 @@ public: void format(const details::log_msg &msg, const std::tm &, memory_buf_t &dest) override { - msg.color_range_end = dest.size(); + msg.color_range_end.push_back(dest.size()); } }; @@ -963,10 +963,10 @@ public: dest.push_back('['); // wrap the level name with color - msg.color_range_start = dest.size(); + msg.color_range_start.push_back(dest.size()); // fmt_helper::append_string_view(level::to_c_str(msg.level), dest); fmt_helper::append_string_view(level::to_string_view(msg.level), dest); - msg.color_range_end = dest.size(); + msg.color_range_end.push_back(dest.size()); dest.push_back(']'); dest.push_back(' '); diff --git a/include/spdlog/sinks/ansicolor_sink-inl.h b/include/spdlog/sinks/ansicolor_sink-inl.h index 3d5071d9..e58dd8ff 100644 --- a/include/spdlog/sinks/ansicolor_sink-inl.h +++ b/include/spdlog/sinks/ansicolor_sink-inl.h @@ -43,20 +43,31 @@ SPDLOG_INLINE void ansicolor_sink::log(const details::log_msg &msg // Wrap the originally formatted message in color codes. // If color is not supported in the terminal, log as is instead. std::lock_guard lock(mutex_); - msg.color_range_start = 0; - msg.color_range_end = 0; + msg.color_range_start.clear(); + msg.color_range_end.clear(); memory_buf_t formatted; formatter_->format(msg, formatted); - if (should_do_colors_ && msg.color_range_end > msg.color_range_start) + if (should_do_colors_ && !msg.color_range_start.empty() && msg.color_range_start.size() == msg.color_range_end.size()) { // before color range - print_range_(formatted, 0, msg.color_range_start); - // in color range - print_ccode_(colors_[msg.level]); - print_range_(formatted, msg.color_range_start, msg.color_range_end); - print_ccode_(reset); - // after color range - print_range_(formatted, msg.color_range_end, formatted.size()); + print_range_(formatted, 0, msg.color_range_start[0]); + + for(size_t i=0; i void SPDLOG_INLINE wincolor_sink::log(const details::log_msg &msg) { std::lock_guard lock(mutex_); - msg.color_range_start = 0; - msg.color_range_end = 0; + msg.color_range_start.clear(); + msg.color_range_end.clear(); memory_buf_t formatted; formatter_->format(msg, formatted); if (!in_console_) @@ -61,17 +61,29 @@ void SPDLOG_INLINE wincolor_sink::log(const details::log_msg &msg) write_to_file_(formatted); return; } - if (should_do_colors_ && msg.color_range_end > msg.color_range_start) + if (should_do_colors_ && !msg.color_range_start.empty() && msg.color_range_start.size() == msg.color_range_end.size()) { // before color range - print_range_(formatted, 0, msg.color_range_start); - - // in color range - auto orig_attribs = set_foreground_color_(colors_[msg.level]); - print_range_(formatted, msg.color_range_start, msg.color_range_end); - // reset to orig colors - ::SetConsoleTextAttribute(out_handle_, orig_attribs); - print_range_(formatted, msg.color_range_end, formatted.size()); + print_range_(formatted, 0, msg.color_range_start[0]); + + for(size_t i=0; iformat(msg, formatted); - REQUIRE(msg.color_range_start == 0); - REQUIRE(msg.color_range_end == 5); + REQUIRE(msg.color_range_start.size() == 1); + REQUIRE(msg.color_range_end.size() == 1); + REQUIRE(msg.color_range_start[0] == 0); + REQUIRE(msg.color_range_end[0] == 5); REQUIRE(log_to_str("hello", "%^%v%$", spdlog::pattern_time_type::local, "\n") == "hello\n"); } @@ -81,8 +83,10 @@ TEST_CASE("color range test2", "[pattern_formatter]") spdlog::details::log_msg msg(logger_name, spdlog::level::info, ""); memory_buf_t formatted; formatter->format(msg, formatted); - REQUIRE(msg.color_range_start == 0); - REQUIRE(msg.color_range_end == 0); + REQUIRE(msg.color_range_start.size() == 1); + REQUIRE(msg.color_range_end.size() == 1); + REQUIRE(msg.color_range_start[0] == 0); + REQUIRE(msg.color_range_end[0] == 0); REQUIRE(log_to_str("", "%^%$", spdlog::pattern_time_type::local, "\n") == "\n"); } @@ -93,8 +97,10 @@ TEST_CASE("color range test3", "[pattern_formatter]") spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored"); memory_buf_t formatted; formatter->format(msg, formatted); - REQUIRE(msg.color_range_start == 0); - REQUIRE(msg.color_range_end == 3); + REQUIRE(msg.color_range_start.size() == 1); + REQUIRE(msg.color_range_end.size() == 1); + REQUIRE(msg.color_range_start[0] == 0); + REQUIRE(msg.color_range_end[0] == 3); } TEST_CASE("color range test4", "[pattern_formatter]") @@ -105,8 +111,10 @@ TEST_CASE("color range test4", "[pattern_formatter]") memory_buf_t formatted; formatter->format(msg, formatted); - REQUIRE(msg.color_range_start == 2); - REQUIRE(msg.color_range_end == 5); + REQUIRE(msg.color_range_start.size() == 1); + REQUIRE(msg.color_range_end.size() == 1); + REQUIRE(msg.color_range_start[0] == 2); + REQUIRE(msg.color_range_end[0] == 5); REQUIRE(log_to_str("ignored", "XX%^YYY%$", spdlog::pattern_time_type::local, "\n") == "XXYYY\n"); } @@ -117,8 +125,9 @@ TEST_CASE("color range test5", "[pattern_formatter]") spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored"); memory_buf_t formatted; formatter->format(msg, formatted); - REQUIRE(msg.color_range_start == 2); - REQUIRE(msg.color_range_end == 0); + REQUIRE(msg.color_range_start.size() == 1); + REQUIRE(msg.color_range_end.empty()); + REQUIRE(msg.color_range_start[0] == 2); } TEST_CASE("color range test6", "[pattern_formatter]") @@ -128,8 +137,39 @@ TEST_CASE("color range test6", "[pattern_formatter]") spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored"); memory_buf_t formatted; formatter->format(msg, formatted); - REQUIRE(msg.color_range_start == 0); - REQUIRE(msg.color_range_end == 2); + REQUIRE(msg.color_range_start.empty()); + REQUIRE(msg.color_range_end.size() == 1); + REQUIRE(msg.color_range_end[0] == 2); +} + +TEST_CASE("color multi-range test1", "[pattern_formatter]") +{ + auto formatter = std::make_shared("%^%$%^%$"); + std::string logger_name = "test"; + spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored"); + memory_buf_t formatted; + formatter->format(msg, formatted); + REQUIRE(msg.color_range_start.size() == 2); + REQUIRE(msg.color_range_end.size() == 2); + REQUIRE(msg.color_range_start[0] == 0); + REQUIRE(msg.color_range_start[1] == 0); + REQUIRE(msg.color_range_end[0] == 0); + REQUIRE(msg.color_range_end[1] == 0); +} + +TEST_CASE("color multi-range test2", "[pattern_formatter]") +{ + auto formatter = std::make_shared("%^***%$***%^***%$"); + std::string logger_name = "test"; + spdlog::details::log_msg msg(logger_name, spdlog::level::info, "ignored"); + memory_buf_t formatted; + formatter->format(msg, formatted); + REQUIRE(msg.color_range_start.size() == 2); + REQUIRE(msg.color_range_end.size() == 2); + REQUIRE(msg.color_range_start[0] == 0); + REQUIRE(msg.color_range_start[1] == 6); + REQUIRE(msg.color_range_end[0] == 3); + REQUIRE(msg.color_range_end[1] == 9); } // diff --git a/tests/test_stdout_api.cpp b/tests/test_stdout_api.cpp index 3392439d..449bb4d5 100644 --- a/tests/test_stdout_api.cpp +++ b/tests/test_stdout_api.cpp @@ -79,6 +79,17 @@ TEST_CASE("stderr_color_mt", "[stderr]") spdlog::drop_all(); } +TEST_CASE("stderr_multi_color_range", "[stderr]") +{ + auto l = spdlog::stderr_color_mt("test"); + l->set_pattern("Test Mutliple Color Ranges -- %^First Color Range%$ %v %^Second Color Range%$ uncolored %^%l%$"); + l->info("uncolored text"); + l->warn("uncolored text"); + l->error("uncolored text"); + l->critical("uncolored text"); + spdlog::drop_all(); +} + #ifdef SPDLOG_WCHAR_TO_UTF8_SUPPORT TEST_CASE("wchar_api", "[stdout]")