diff options
author | Rebecca Turner <rbt@sent.as> | 2024-03-26 15:39:54 -0700 |
---|---|---|
committer | Rebecca Turner <rbt@sent.as> | 2024-03-26 15:40:05 -0700 |
commit | 8e63eca912a01659cef81b9d6d1cc7cb11edfff5 (patch) | |
tree | de159e9a3c17068d55ab06920d3c587d4e2094c7 /src/libutil | |
parent | da22dbc33397c9c6c5d115ce753d5cf11585291e (diff) |
Remove `HintFmt::operator%`
Change-Id: Ibcf1a7848b4b18ec9b0807628ff229079ae7a0fe
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/fmt.hh | 177 | ||||
-rw-r--r-- | src/libutil/logging.hh | 4 |
2 files changed, 87 insertions, 94 deletions
diff --git a/src/libutil/fmt.hh b/src/libutil/fmt.hh index 84a3e3e11..c68591b72 100644 --- a/src/libutil/fmt.hh +++ b/src/libutil/fmt.hh @@ -5,43 +5,94 @@ #include <string> #include "ansicolor.hh" - namespace nix { -namespace { /** - * A helper for writing `boost::format` expressions. - * - * These are equivalent: + * Values wrapped in this struct are printed in magenta. * - * ``` - * formatHelper(formatter, a_0, ..., a_n) - * formatter % a_0 % ... % a_n - * ``` + * By default, arguments to `HintFmt` are printed in magenta. To avoid this, + * either wrap the argument in `Uncolored` or add a specialization of + * `HintFmt::operator%`. + */ +template<class T> +struct Magenta +{ + Magenta(const T & s) : value(s) {} + const T & value; +}; + +template<class T> +std::ostream & operator<<(std::ostream & out, const Magenta<T> & y) +{ + return out << ANSI_MAGENTA << y.value << ANSI_NORMAL; +} + +/** + * Values wrapped in this class are printed without coloring. * - * With a single argument, `formatHelper(s)` is a no-op. + * By default, arguments to `HintFmt` are printed in magenta (see `Magenta`). */ -template<class F> -inline void formatHelper(F & f) -{ } +template<class T> +struct Uncolored +{ + Uncolored(const T & s) : value(s) {} + const T & value; +}; -template<class F, typename T, typename... Args> -inline void formatHelper(F & f, const T & x, const Args & ... args) +template<class T> +std::ostream & operator<<(std::ostream & out, const Uncolored<T> & y) { - // Interpolate one argument and then recurse. - formatHelper(f % x, args...); + return out << ANSI_NORMAL << y.value; } +namespace fmt_internal { + /** * Set the correct exceptions for `fmt`. */ -void setExceptions(boost::format & fmt) +inline void setExceptions(boost::format & fmt) { fmt.exceptions( - boost::io::all_error_bits ^ - boost::io::too_many_args_bit ^ - boost::io::too_few_args_bit); + boost::io::all_error_bits ^ boost::io::too_many_args_bit ^ boost::io::too_few_args_bit + ); } + +/** + * Helper class for `HintFmt` that supports the evil `operator%`. + * + * See: https://git.lix.systems/lix-project/lix/issues/178 + */ +struct HintFmt +{ + boost::format fmt; + + template<typename... Args> + HintFmt(boost::format && fmt, const Args &... args) : fmt(std::move(fmt)) + { + setExceptions(fmt); + (*this % ... % args); + } + + template<class T> + HintFmt & operator%(const T & value) + { + fmt % Magenta(value); + return *this; + } + + template<class T> + HintFmt & operator%(const Uncolored<T> & value) + { + fmt % value.value; + return *this; + } + + boost::format into_format() + { + return std::move(fmt); + } +}; + } /** @@ -77,53 +128,15 @@ inline std::string fmt(const char * s) } template<typename... Args> -inline std::string fmt(const std::string & fs, const Args & ... args) +inline std::string fmt(const std::string & fs, const Args &... args) { boost::format f(fs); - setExceptions(f); - formatHelper(f, args...); + fmt_internal::setExceptions(f); + (f % ... % args); return f.str(); } /** - * Values wrapped in this struct are printed in magenta. - * - * By default, arguments to `HintFmt` are printed in magenta. To avoid this, - * either wrap the argument in `Uncolored` or add a specialization of - * `HintFmt::operator%`. - */ -template <class T> -struct Magenta -{ - Magenta(const T &s) : value(s) {} - const T & value; -}; - -template <class T> -std::ostream & operator<<(std::ostream & out, const Magenta<T> & y) -{ - return out << ANSI_WARNING << y.value << ANSI_NORMAL; -} - -/** - * Values wrapped in this class are printed without coloring. - * - * By default, arguments to `HintFmt` are printed in magenta (see `Magenta`). - */ -template <class T> -struct Uncolored -{ - Uncolored(const T & s) : value(s) {} - const T & value; -}; - -template <class T> -std::ostream & operator<<(std::ostream & out, const Uncolored<T> & y) -{ - return out << ANSI_NORMAL << y.value; -} - -/** * A wrapper around `boost::format` which colors interpolated arguments in * magenta by default. */ @@ -137,46 +150,28 @@ public: * Format the given string literally, without interpolating format * placeholders. */ - HintFmt(const std::string & literal) - : HintFmt("%s", Uncolored(literal)) - { } - - static HintFmt fromFormatString(const std::string & format) { - return HintFmt(boost::format(format)); - } + HintFmt(const std::string & literal) : HintFmt("%s", Uncolored(literal)) {} /** * Interpolate the given arguments into the format string. */ template<typename... Args> - HintFmt(const std::string & format, const Args & ... args) + HintFmt(const std::string & format, const Args &... args) : HintFmt(boost::format(format), args...) - { } - - HintFmt(const HintFmt & hf) - : fmt(hf.fmt) - { } - - template<typename... Args> - HintFmt(boost::format && fmt, const Args & ... args) - : fmt(std::move(fmt)) { - setExceptions(fmt); - formatHelper(*this, args...); } - template<class T> - HintFmt & operator%(const T & value) - { - fmt % Magenta(value); - return *this; - } + HintFmt(const HintFmt & hf) : fmt(hf.fmt) {} - template<class T> - HintFmt & operator%(const Uncolored<T> & value) + template<typename... Args> + HintFmt(boost::format && fmt, const Args &... args) + : fmt(fmt_internal::HintFmt(std::move(fmt), args...).into_format()) { - fmt % value.value; - return *this; + if (this->fmt.remaining_args() != 0) { + throw boost::io::too_few_args( + this->fmt.bound_args() + this->fmt.fed_args(), this->fmt.expected_args() + ); + } } std::string str() const diff --git a/src/libutil/logging.hh b/src/libutil/logging.hh index 7a6341d70..298d66060 100644 --- a/src/libutil/logging.hh +++ b/src/libutil/logging.hh @@ -242,9 +242,7 @@ extern Verbosity verbosity; template<typename... Args> inline void warn(const std::string & fs, const Args & ... args) { - boost::format f(fs); - formatHelper(f, args...); - logger->warn(f.str()); + logger->warn(HintFmt(fs, args...).str()); } #define warnOnce(haveWarned, args...) \ |