diff --git a/include/fmt/color.h b/include/fmt/color.h index 20399210..c5e30168 100644 --- a/include/fmt/color.h +++ b/include/fmt/color.h @@ -423,26 +423,53 @@ template <> inline void reset_color(FILE *stream) FMT_NOEXCEPT { fputs(internal::data::WRESET_COLOR, stream); } + +// The following specialiazation disables using std::FILE as a character type, +// which is needed because or else +// fmt::print(stderr, fmt::emphasis::bold, ""); +// would take stderr (a std::FILE *) as the format string. +template <> +struct is_string : std::false_type {}; +template <> +struct is_string : std::false_type {}; } // namespace internal template < typename S, typename Char = typename internal::char_t::type> -void vprint(const text_style &tf, const S &format, +void vprint(std::FILE *f, const text_style &ts, const S &format, basic_format_args::type> args) { - if (tf.has_emphasis()) { + if (ts.has_emphasis()) { internal::fputs( - internal::make_emphasis(tf.get_emphasis()), stdout); + internal::make_emphasis(ts.get_emphasis()), f); } - if (tf.has_foreground()) { + if (ts.has_foreground()) { internal::fputs( - internal::make_foreground_color(tf.get_foreground()), stdout); + internal::make_foreground_color(ts.get_foreground()), f); } - if (tf.has_background()) { + if (ts.has_background()) { internal::fputs( - internal::make_background_color(tf.get_background()), stdout); + internal::make_background_color(ts.get_background()), f); } - vprint(format, args); - internal::reset_color(stdout); + vprint(f, format, args); + internal::reset_color(f); +} + +/** + Formats a string and prints it to the specified file stream using ANSI + escape sequences to specify text formatting. + Example: + fmt::print(fmt::emphasis::bold | fg(fmt::color::red), + "Elapsed time: {0:.2f} seconds", 1.23); + */ +template +typename std::enable_if::value>::type print( + std::FILE *f, const text_style &ts, const String &format_str, + const Args &... args) { + internal::check_format_string(format_str); + typedef typename internal::char_t::type char_t; + typedef typename buffer_context::type context_t; + format_arg_store as{args...}; + vprint(f, ts, format_str, basic_format_args(as)); } /** @@ -453,13 +480,10 @@ void vprint(const text_style &tf, const S &format, "Elapsed time: {0:.2f} seconds", 1.23); */ template -typename std::enable_if::value>::type -print(const text_style &tf, const String &format_str, const Args & ... args) { - internal::check_format_string(format_str); - typedef typename internal::char_t::type char_t; - typedef typename buffer_context::type context_t; - format_arg_store as{args...}; - vprint(tf, format_str, basic_format_args(as)); +typename std::enable_if::value>::type print( + const text_style &ts, const String &format_str, + const Args &... args) { + return print(stdout, ts, format_str, args...); } #endif diff --git a/test/format-impl-test.cc b/test/format-impl-test.cc index c40fe3b5..9774c33a 100644 --- a/test/format-impl-test.cc +++ b/test/format-impl-test.cc @@ -228,4 +228,8 @@ TEST(ColorsTest, Colors) { stdout, fmt::print(fg(fmt::color::blue) | fmt::emphasis::bold, "blue/bold"), "\x1b[1m\x1b[38;2;000;000;255mblue/bold\x1b[0m"); + EXPECT_WRITE(stderr, fmt::print(stderr, fmt::emphasis::bold, "bold error"), + "\x1b[1mbold error\x1b[0m"); + EXPECT_WRITE(stderr, fmt::print(stderr, fg(fmt::color::blue), "blue log"), + "\x1b[38;2;000;000;255mblue log\x1b[0m"); }