From 279db0190611aab8f34cda1f5c77c2757cab5ec5 Mon Sep 17 00:00:00 2001 From: Ken Matsui <26405363+ken-matsui@users.noreply.github.com> Date: Wed, 29 Jan 2025 21:13:02 -0500 Subject: [PATCH] refactor: replace some ostream use with fmt --- src/Cli.cc | 18 ++++++------- src/Cli.hpp | 4 +-- src/Cmd/Version.cc | 25 +++++++++--------- src/Command.cc | 57 +++++++++++++++++++++++++++++++++++++++++ src/Command.hpp | 61 ++++++++++---------------------------------- src/CurlVersion.cc | 30 ++++++++++++++-------- src/CurlVersion.hpp | 13 +++++++--- src/Git2/Version.cc | 29 +++++++++++++-------- src/Git2/Version.hpp | 13 +++++++--- src/TermColor.cc | 18 +++++-------- src/TermColor.hpp | 13 +++++----- 11 files changed, 165 insertions(+), 116 deletions(-) diff --git a/src/Cli.cc b/src/Cli.cc index b7db1b789..bc7bd6402 100644 --- a/src/Cli.cc +++ b/src/Cli.cc @@ -7,10 +7,10 @@ #include #include +#include #include #include #include -#include #include #include #include @@ -195,16 +195,16 @@ Subcmd::setGlobalOpts(const Opts& globalOpts) noexcept { return *this; } std::string -Subcmd::formatUsage(std::ostream& os) const noexcept { - std::string str = Bold(Green("Usage: ")).toStr(os); - str += Bold(Cyan(cmdName)).toStr(os); +Subcmd::formatUsage(FILE* file) const noexcept { + std::string str = Bold(Green("Usage: ")).toStr(file); + str += Bold(Cyan(cmdName)).toStr(file); str += ' '; - str += Bold(Cyan(name)).toStr(os); + str += Bold(Cyan(name)).toStr(file); str += ' '; - str += Cyan("[OPTIONS]").toStr(os); + str += Cyan("[OPTIONS]").toStr(file); if (!arg.name.empty()) { str += ' '; - str += Cyan(arg.getLeft()).toStr(os); + str += Cyan(arg.getLeft()).toStr(file); } return str; } @@ -229,7 +229,7 @@ Subcmd::noSuchArg(std::string_view arg) const { "{}" "{}\n\n" "For more information, try '{}'", - Bold(Yellow(arg)).toErrStr(), suggestion, formatUsage(std::cerr), + Bold(Yellow(arg)).toErrStr(), suggestion, formatUsage(stderr), Bold(Cyan("--help")).toErrStr() ); } @@ -273,7 +273,7 @@ Subcmd::formatHelp() const noexcept { std::string str = std::string(desc); str += "\n\n"; - str += formatUsage(std::cout); + str += formatUsage(stdout); str += "\n\n"; str += formatHeader("Options:"); if (globalOpts.has_value()) { diff --git a/src/Cli.hpp b/src/Cli.hpp index 623616f57..60e196cd4 100644 --- a/src/Cli.hpp +++ b/src/Cli.hpp @@ -2,9 +2,9 @@ #include "Rustify/Result.hpp" +#include #include #include -#include #include #include #include @@ -206,7 +206,7 @@ class Subcmd : public CliBase, public ShortAndHidden { } Subcmd& setGlobalOpts(const Opts& globalOpts) noexcept; - std::string formatUsage(std::ostream& os) const noexcept; + std::string formatUsage(FILE* file) const noexcept; std::string formatHelp() const noexcept; std::string format(std::size_t maxOffset) const noexcept; diff --git a/src/Cmd/Version.cc b/src/Cmd/Version.cc index 96a5fa17d..fa173072a 100644 --- a/src/Cmd/Version.cc +++ b/src/Cmd/Version.cc @@ -7,7 +7,7 @@ #include "../Rustify/Result.hpp" #include -#include +#include #include #ifndef CABIN_CABIN_PKG_VERSION @@ -147,18 +147,19 @@ versionMain(const CliArgsView args) noexcept { return VERSION_CMD.noSuchArg(arg); } - std::cout << "cabin " CABIN_CABIN_PKG_VERSION << commitInfo(); + fmt::print("cabin {}{}\n", CABIN_CABIN_PKG_VERSION, commitInfo()); if (isVerbose()) { - std::cout << "release: " CABIN_CABIN_PKG_VERSION - "\n" - "commit-hash: " COMMIT_HASH - "\n" - "commit-date: " COMMIT_DATE - "\n" - "compiler: " COMPILER_VERSION "\n" - << "compile-date: " << COMPILE_DATE << '\n' - << "libgit2: " << git2::Version() << '\n' - << "libcurl: " << curl::Version() << '\n'; + fmt::print( + "release: {}\n" + "commit-hash: {}\n" + "commit-date: {}\n" + "compiler: {}\n" + "compile-date: {}\n" + "libgit2: {}\n" + "libcurl: {}\n", + CABIN_CABIN_PKG_VERSION, COMMIT_HASH, COMMIT_DATE, COMPILER_VERSION, + COMPILE_DATE, git2::Version(), curl::Version() + ); } return Ok(); diff --git a/src/Command.cc b/src/Command.cc index c724cbbdb..fbb7f9397 100644 --- a/src/Command.cc +++ b/src/Command.cc @@ -17,6 +17,56 @@ namespace cabin { constexpr std::size_t BUFFER_SIZE = 128; +bool +ExitStatus::exitedNormally() const noexcept { + return WIFEXITED(rawStatus); +} +bool +ExitStatus::killedBySignal() const noexcept { + return WIFSIGNALED(rawStatus); +} +bool +ExitStatus::stoppedBySignal() const noexcept { + return WIFSTOPPED(rawStatus); +} +int +ExitStatus::exitCode() const noexcept { + return WEXITSTATUS(rawStatus); +} +int +ExitStatus::termSignal() const noexcept { + return WTERMSIG(rawStatus); +} +int +ExitStatus::stopSignal() const noexcept { + return WSTOPSIG(rawStatus); +} +bool +ExitStatus::coreDumped() const noexcept { + return WCOREDUMP(rawStatus); +} + +// Successful only if normally exited with code 0 +bool +ExitStatus::success() const noexcept { + return exitedNormally() && exitCode() == 0; +} + +std::string +ExitStatus::toString() const { + if (exitedNormally()) { + return fmt::format("exited with code {}", exitCode()); + } else if (killedBySignal()) { + return fmt::format( + "killed by signal {}{}", termSignal(), + coreDumped() ? " (core dumped)" : "" + ); + } else if (stoppedBySignal()) { + return fmt::format("stopped by signal {}", stopSignal()); + } + return "unknown status"; +} + Result Child::wait() const noexcept { int status{}; @@ -244,3 +294,10 @@ operator<<(std::ostream& os, const Command& cmd) { } } // namespace cabin + +auto +fmt::formatter::format( + const cabin::ExitStatus& v, format_context& ctx +) const -> format_context::iterator { + return formatter::format(v.toString(), ctx); +} diff --git a/src/Command.hpp b/src/Command.hpp index ec2a39bb2..1abe5bdb4 100644 --- a/src/Command.hpp +++ b/src/Command.hpp @@ -5,14 +5,9 @@ #include #include #include -#include -#include -#include #include #include #include -#include -#include #include #include @@ -25,51 +20,18 @@ class ExitStatus { ExitStatus() noexcept : rawStatus(EXIT_SUCCESS) {} explicit ExitStatus(int status) noexcept : rawStatus(status) {} - bool exitedNormally() const noexcept { - return WIFEXITED(rawStatus); - } - bool killedBySignal() const noexcept { - return WIFSIGNALED(rawStatus); - } - bool stoppedBySignal() const noexcept { - return WIFSTOPPED(rawStatus); - } - int exitCode() const noexcept { - return WEXITSTATUS(rawStatus); - } - int termSignal() const noexcept { - return WTERMSIG(rawStatus); - } - int stopSignal() const noexcept { - return WSTOPSIG(rawStatus); - } - bool coreDumped() const noexcept { - return WCOREDUMP(rawStatus); - } + bool exitedNormally() const noexcept; + bool killedBySignal() const noexcept; + bool stoppedBySignal() const noexcept; + int exitCode() const noexcept; + int termSignal() const noexcept; + int stopSignal() const noexcept; + bool coreDumped() const noexcept; // Successful only if normally exited with code 0 - bool success() const noexcept { - return exitedNormally() && exitCode() == 0; - } - - std::string toString() const { - if (exitedNormally()) { - return fmt::format("exited with code {}", exitCode()); - } else if (killedBySignal()) { - return fmt::format( - "killed by signal {}{}", termSignal(), - coreDumped() ? " (core dumped)" : "" - ); - } else if (stoppedBySignal()) { - return fmt::format("stopped by signal {}", stopSignal()); - } - return "unknown status"; - } + bool success() const noexcept; - friend std::ostream& operator<<(std::ostream& os, const ExitStatus& status) { - os << status.toString(); - return os; - } + std::string toString() const; }; struct CommandOutput { @@ -144,4 +106,7 @@ std::ostream& operator<<(std::ostream& os, const Command& cmd); } // namespace cabin template <> -struct fmt::formatter : ostream_formatter {}; +struct fmt::formatter : formatter { + auto format(const cabin::ExitStatus& v, format_context& ctx) const + -> format_context::iterator; +}; diff --git a/src/CurlVersion.cc b/src/CurlVersion.cc index c4613b3b2..4b3b452db 100644 --- a/src/CurlVersion.cc +++ b/src/CurlVersion.cc @@ -1,21 +1,31 @@ #include "CurlVersion.hpp" -#include +#include +#include namespace curl { -std::ostream& -operator<<(std::ostream& os, const Version& version) { - if (version.data) { - os << version.data->version << " (ssl: "; - if (version.data->ssl_version) { - os << version.data->ssl_version; +std::string +Version::toString() const { + std::string str; + if (data) { + str += data->version; + str += " (ssl: "; + if (data->ssl_version) { + str += data->ssl_version; } else { - os << "none"; + str += "none"; } - os << ")"; + str += ")"; } - return os; + return str; } }; // namespace curl + +auto +fmt::formatter::format( + const curl::Version& v, format_context& ctx +) const -> format_context::iterator { + return formatter::format(v.toString(), ctx); +} diff --git a/src/CurlVersion.hpp b/src/CurlVersion.hpp index 6b0e0ca44..d6dbce1c8 100644 --- a/src/CurlVersion.hpp +++ b/src/CurlVersion.hpp @@ -1,7 +1,8 @@ #pragma once #include -#include +#include +#include namespace curl { @@ -9,8 +10,14 @@ struct Version { curl_version_info_data* data; Version() : data(curl_version_info(CURLVERSION_NOW)) {} -}; -std::ostream& operator<<(std::ostream& os, const Version& version); + std::string toString() const; +}; }; // namespace curl + +template <> +struct fmt::formatter : formatter { + auto format(const curl::Version& v, format_context& ctx) const + -> format_context::iterator; +}; diff --git a/src/Git2/Version.cc b/src/Git2/Version.cc index c6303b56c..48fd051be 100644 --- a/src/Git2/Version.cc +++ b/src/Git2/Version.cc @@ -2,7 +2,9 @@ #include "Exception.hpp" +#include #include +#include namespace git2 { @@ -10,6 +12,16 @@ Version::Version() : features(git2Throw(git_libgit2_features())) { git2Throw(git_libgit2_version(&this->major, &this->minor, &this->rev)); } +std::string +Version::toString() const { + const auto flagStr = [](const bool flag) { return flag ? "on" : "off"; }; + return fmt::format( + "{}.{}.{} (threads: {}, https: {}, ssh: {}, nsec: {})", major, minor, rev, + flagStr(hasThread()), flagStr(hasHttps()), flagStr(hasSsh()), + flagStr(hasNsec()) + ); +} + bool Version::hasThread() const noexcept { return this->features & GIT_FEATURE_THREADS; @@ -30,14 +42,11 @@ Version::hasNsec() const noexcept { return this->features & GIT_FEATURE_NSEC; } -std::ostream& -operator<<(std::ostream& os, const Version& version) { - const auto flagStr = [](const bool flag) { return flag ? "on" : "off"; }; - return os << version.major << '.' << version.minor << '.' << version.rev - << " (threads: " << flagStr(version.hasThread()) << ", " - << "https: " << flagStr(version.hasHttps()) << ", " - << "ssh: " << flagStr(version.hasSsh()) << ", " - << "nsec: " << flagStr(version.hasNsec()) << ')'; -} - } // namespace git2 + +auto +fmt::formatter::format( + const git2::Version& v, format_context& ctx +) const -> format_context::iterator { + return formatter::format(v.toString(), ctx); +} diff --git a/src/Git2/Version.hpp b/src/Git2/Version.hpp index c0693400f..45837f9bf 100644 --- a/src/Git2/Version.hpp +++ b/src/Git2/Version.hpp @@ -1,6 +1,7 @@ #pragma once -#include +#include +#include namespace git2 { @@ -12,6 +13,8 @@ struct Version { Version(); + std::string toString() const; + /// Returns true if libgit2 was built thread-aware and can be safely used /// from multiple threads. bool hasThread() const noexcept; @@ -34,6 +37,10 @@ struct Version { bool hasNsec() const noexcept; }; -std::ostream& operator<<(std::ostream& os, const Version& version); - } // namespace git2 + +template <> +struct fmt::formatter : formatter { + auto format(const git2::Version& v, format_context& ctx) const + -> format_context::iterator; +}; diff --git a/src/TermColor.cc b/src/TermColor.cc index f23481e4b..6f9952c11 100644 --- a/src/TermColor.cc +++ b/src/TermColor.cc @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -77,22 +76,17 @@ getColorMode() noexcept { } static bool -isTerm(const std::ostream& os) noexcept { - if (&os == &std::cout) { - return isatty(fileno(stdout)); - } else if (&os == &std::cerr) { - return isatty(fileno(stderr)); - } - return false; +isTerm(FILE* file) { + return isatty(fileno(file)) != 0; } bool -shouldColor(const std::ostream& os) noexcept { +shouldColor(FILE* file) noexcept { switch (getColorMode()) { case ColorMode::Always: return true; case ColorMode::Auto: - return isTerm(os); + return isTerm(file); case ColorMode::Never: return false; } @@ -100,11 +94,11 @@ shouldColor(const std::ostream& os) noexcept { } bool shouldColorStdout() noexcept { - return shouldColor(std::cout); + return shouldColor(stdout); } bool shouldColorStderr() noexcept { - return shouldColor(std::cerr); + return shouldColor(stderr); } } // namespace cabin diff --git a/src/TermColor.hpp b/src/TermColor.hpp index 1eddaa109..1f16a4c78 100644 --- a/src/TermColor.hpp +++ b/src/TermColor.hpp @@ -1,10 +1,9 @@ #pragma once #include +#include #include -#include #include -#include #include #include #include @@ -14,7 +13,7 @@ namespace cabin { void setColorMode(std::string_view str) noexcept; -bool shouldColor(const std::ostream& os) noexcept; +bool shouldColor(FILE* file) noexcept; bool shouldColorStdout() noexcept; bool shouldColorStderr() noexcept; @@ -45,18 +44,18 @@ class ColorStr { ColorStr& operator=(ColorStr&&) noexcept = default; virtual ~ColorStr() noexcept = default; - std::string toStr(const std::ostream& os) const noexcept { - if (shouldColor(os)) { + std::string toStr(FILE* file) const noexcept { + if (shouldColor(file)) { return fmt::format("\033[{}m{}\033[0m", fmt::join(codes, ";"), str); } return str; } std::string toStr() const noexcept { - return toStr(std::cout); + return toStr(stdout); } std::string toErrStr() const noexcept { - return toStr(std::cerr); + return toStr(stderr); } };