// Copyright(c) 2015-present, Gabi Melman & spdlog contributors. // Distributed under the MIT License (http://opensource.org/licenses/MIT) #pragma once #ifndef SPDLOG_HEADER_ONLY #include "spdlog/sinks/ansicolor_sink.h" #endif #include "spdlog/details/pattern_formatter.h" #include "spdlog/details/os.h" namespace spdlog { namespace sinks { template SPDLOG_INLINE ansicolor_sink::ansicolor_sink(FILE *target_file, color_mode mode) : target_file_(target_file) , mutex_(ConsoleMutex::mutex()) , formatter_(details::make_unique()) { set_color_mode(mode); colors_[level::trace] = white; colors_[level::debug] = cyan; colors_[level::info] = green; colors_[level::warn] = yellow_bold; colors_[level::err] = red_bold; colors_[level::critical] = bold_on_red; colors_[level::off] = reset; } template SPDLOG_INLINE void ansicolor_sink::set_color(level::level_enum color_level, string_view_t color) { std::lock_guard lock(mutex_); colors_[color_level] = color; } template 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_); memory_buf_t formatted; formatter_->format(msg, formatted); if (should_do_colors_ && msg.color_range_end > msg.color_range_start) { // 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()); } else // no color { print_range_(formatted, 0, formatted.size()); } fflush(target_file_); } template SPDLOG_INLINE void ansicolor_sink::flush() { std::lock_guard lock(mutex_); fflush(target_file_); } template SPDLOG_INLINE void ansicolor_sink::set_pattern(const std::string &pattern) { std::lock_guard lock(mutex_); formatter_ = std::unique_ptr(new pattern_formatter(pattern)); } template SPDLOG_INLINE void ansicolor_sink::set_formatter(std::unique_ptr sink_formatter) { std::lock_guard lock(mutex_); formatter_ = std::move(sink_formatter); } template SPDLOG_INLINE bool ansicolor_sink::should_color() { return should_do_colors_; } template SPDLOG_INLINE void ansicolor_sink::set_color_mode(color_mode mode) { switch (mode) { case color_mode::always: should_do_colors_ = true; return; case color_mode::automatic: should_do_colors_ = details::os::in_terminal(target_file_) && details::os::is_color_terminal(); return; case color_mode::never: should_do_colors_ = false; return; } } template SPDLOG_INLINE void ansicolor_sink::print_ccode_(const string_view_t &color_code) { fwrite(color_code.data(), sizeof(string_view_t::char_type), color_code.size(), target_file_); } template SPDLOG_INLINE void ansicolor_sink::print_range_(const memory_buf_t &formatted, size_t start, size_t end) { fwrite(formatted.data() + start, sizeof(char), end - start, target_file_); } // ansicolor_stdout_sink template SPDLOG_INLINE ansicolor_stdout_sink::ansicolor_stdout_sink(color_mode mode) : ansicolor_sink(stdout, mode) {} // ansicolor_stderr_sink template SPDLOG_INLINE ansicolor_stderr_sink::ansicolor_stderr_sink(color_mode mode) : ansicolor_sink(stderr, mode) {} } // namespace sinks } // namespace spdlog