From 87c066a35b7cc70bb7d438a543c8b49b577e61f4 Mon Sep 17 00:00:00 2001 From: Shawn Zhong Date: Tue, 24 Jan 2023 14:30:00 -0600 Subject: [PATCH] Implement `println` (#3267) --- include/fmt/core.h | 30 ++++++++++++++++++++++++++++++ include/fmt/ostream.h | 13 +++++++++++++ include/fmt/xchar.h | 9 +++++++++ test/format-test.cc | 3 +++ test/ostream-test.cc | 14 +++++++++++--- test/xchar-test.cc | 19 +++++++++++++++---- 6 files changed, 81 insertions(+), 7 deletions(-) diff --git a/include/fmt/core.h b/include/fmt/core.h index f7656da0..8942ad3e 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -3009,6 +3009,36 @@ FMT_INLINE void print(std::FILE* f, format_string fmt, T&&... args) { : detail::vprint_mojibake(f, fmt, vargs); } +/** + \rst + Formats ``args`` according to specifications in ``fmt`` and writes the + output to the file ``f`` followed by a newline. + + **Example**:: + + fmt::println(stderr, "Don't {}!", "panic"); + \endrst + */ +template +FMT_INLINE void println(std::FILE* f, format_string fmt, T&&... args) { + return fmt::print(f, "{}\n", fmt::format(fmt, std::forward(args)...)); +} + +/** + \rst + Formats ``args`` according to specifications in ``fmt`` and writes the output + to ``stdout`` followed by a newline. + + **Example**:: + + fmt::println("Elapsed time: {0:.2f} seconds", 1.23); + \endrst + */ +template +FMT_INLINE void println(format_string fmt, T&&... args) { + return fmt::println(stdout, fmt, std::forward(args)...); +} + FMT_MODULE_EXPORT_END FMT_GCC_PRAGMA("GCC pop_options") FMT_END_NAMESPACE diff --git a/include/fmt/ostream.h b/include/fmt/ostream.h index 86ec47e1..d3bb432c 100644 --- a/include/fmt/ostream.h +++ b/include/fmt/ostream.h @@ -232,6 +232,19 @@ void print(std::wostream& os, vprint(os, fmt, fmt::make_format_args>(args...)); } +FMT_MODULE_EXPORT template +void println(std::ostream& os, format_string fmt, T&&... args) { + print(os, "{}\n", fmt::format(fmt, std::forward(args)...)); +} + +FMT_MODULE_EXPORT +template +void println(std::wostream& os, + basic_format_string...> fmt, + Args&&... args) { + print(os, L"{}\n", fmt::format(fmt, std::forward(args)...)); +} + FMT_END_NAMESPACE #endif // FMT_OSTREAM_H_ diff --git a/include/fmt/xchar.h b/include/fmt/xchar.h index 5b0cf4d4..5a57c519 100644 --- a/include/fmt/xchar.h +++ b/include/fmt/xchar.h @@ -238,6 +238,15 @@ template void print(wformat_string fmt, T&&... args) { return vprint(wstring_view(fmt), fmt::make_wformat_args(args...)); } +template +void println(std::FILE* f, wformat_string fmt, T&&... args) { + return print(f, L"{}\n", fmt::format(fmt, std::forward(args)...)); +} + +template void println(wformat_string fmt, T&&... args) { + return print(L"{}\n", fmt::format(fmt, std::forward(args)...)); +} + /** Converts *value* to ``std::wstring`` using the default format for type *T*. */ diff --git a/test/format-test.cc b/test/format-test.cc index c1d97766..eaf84c52 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1778,6 +1778,9 @@ TEST(format_test, print) { EXPECT_WRITE(stdout, fmt::print("Don't {}!", "panic"), "Don't panic!"); EXPECT_WRITE(stderr, fmt::print(stderr, "Don't {}!", "panic"), "Don't panic!"); + EXPECT_WRITE(stdout, fmt::println("Don't {}!", "panic"), "Don't panic!\n"); + EXPECT_WRITE(stderr, fmt::println(stderr, "Don't {}!", "panic"), + "Don't panic!\n"); } TEST(format_test, variadic) { diff --git a/test/ostream-test.cc b/test/ostream-test.cc index 4ba1279f..b9a6b352 100644 --- a/test/ostream-test.cc +++ b/test/ostream-test.cc @@ -106,9 +106,17 @@ TEST(ostream_test, empty_custom_output) { } TEST(ostream_test, print) { - std::ostringstream os; - fmt::print(os, "Don't {}!", "panic"); - EXPECT_EQ("Don't panic!", os.str()); + { + std::ostringstream os; + fmt::print(os, "Don't {}!", "panic"); + EXPECT_EQ("Don't panic!", os.str()); + } + + { + std::ostringstream os; + fmt::println(os, "Don't {}!", "panic"); + EXPECT_EQ("Don't panic!\n", os.str()); + } } TEST(ostream_test, write_to_ostream) { diff --git a/test/xchar-test.cc b/test/xchar-test.cc index 34af6e4f..1deab2d0 100644 --- a/test/xchar-test.cc +++ b/test/xchar-test.cc @@ -210,7 +210,10 @@ TEST(xchar_test, named_arg_udl) { TEST(xchar_test, print) { // Check that the wide print overload compiles. - if (fmt::detail::const_check(false)) fmt::print(L"test"); + if (fmt::detail::const_check(false)) { + fmt::print(L"test"); + fmt::println(L"test"); + } } TEST(xchar_test, join) { @@ -382,9 +385,17 @@ TEST(xchar_test, color) { TEST(xchar_test, ostream) { #if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 409 - std::wostringstream wos; - fmt::print(wos, L"Don't {}!", L"panic"); - EXPECT_EQ(wos.str(), L"Don't panic!"); + { + std::wostringstream wos; + fmt::print(wos, L"Don't {}!", L"panic"); + EXPECT_EQ(wos.str(), L"Don't panic!"); + } + + { + std::wostringstream wos; + fmt::println(wos, L"Don't {}!", L"panic"); + EXPECT_EQ(wos.str(), L"Don't panic!\n"); + } #endif }