aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/fmt.hh
diff options
context:
space:
mode:
authorBen Burdette <bburdette@gmail.com>2020-04-21 13:25:41 -0600
committerBen Burdette <bburdette@gmail.com>2020-04-21 13:25:41 -0600
commitd3052197feababc312fd874e08ae48050d985eb3 (patch)
treed82b94bb3478f59e60b4df5dcd5dddc554697771 /src/libutil/fmt.hh
parent15e9564fd1e11b3797f0188a494aa66d4622dfb0 (diff)
add ErrorInfo to BaseError
Diffstat (limited to 'src/libutil/fmt.hh')
-rw-r--r--src/libutil/fmt.hh127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/libutil/fmt.hh b/src/libutil/fmt.hh
new file mode 100644
index 000000000..08edffee0
--- /dev/null
+++ b/src/libutil/fmt.hh
@@ -0,0 +1,127 @@
+#pragma once
+
+#include <boost/format.hpp>
+#include <string>
+#include "ansicolor.hh"
+
+
+namespace nix {
+
+
+/* Inherit some names from other namespaces for convenience. */
+using std::string;
+using boost::format;
+
+
+/* A variadic template that does nothing. Useful to call a function
+ for all variadic arguments but ignoring the result. */
+struct nop { template<typename... T> nop(T...) {} };
+
+
+struct FormatOrString
+{
+ string s;
+ FormatOrString(const string & s) : s(s) { };
+ template<class F>
+ FormatOrString(const F & f) : s(f.str()) { };
+ FormatOrString(const char * s) : s(s) { };
+};
+
+
+/* A helper for formatting strings. ‘fmt(format, a_0, ..., a_n)’ is
+ equivalent to ‘boost::format(format) % a_0 % ... %
+ ... a_n’. However, ‘fmt(s)’ is equivalent to ‘s’ (so no %-expansion
+ takes place). */
+
+template<class F>
+inline void formatHelper(F & f)
+{
+}
+
+template<class F, typename T, typename... Args>
+inline void formatHelper(F & f, const T & x, const Args & ... args)
+{
+ formatHelper(f % x, args...);
+}
+
+inline std::string fmt(const std::string & s)
+{
+ return s;
+}
+
+inline std::string fmt(const char * s)
+{
+ return s;
+}
+
+inline std::string fmt(const FormatOrString & fs)
+{
+ return fs.s;
+}
+
+template<typename... Args>
+inline std::string fmt(const std::string & fs, const Args & ... args)
+{
+ boost::format f(fs);
+ f.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
+ formatHelper(f, args...);
+ return f.str();
+}
+
+// -----------------------------------------------------------------------------
+// format function for hints in errors. same as fmt, except templated values
+// are always in yellow.
+
+template <class T>
+struct yellowify
+{
+ yellowify(T &s) : value(s) {}
+ T &value;
+};
+
+template <class T>
+std::ostream& operator<<(std::ostream &out, const yellowify<T> &y)
+{
+ return out << ANSI_YELLOW << y.value << ANSI_NORMAL;
+}
+
+class hintformat
+{
+public:
+ hintformat(const string &format) :fmt(format)
+ {
+ fmt.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
+ }
+ template<class T>
+ hintformat& operator%(const T &value)
+ {
+ fmt % yellowify(value);
+ return *this;
+ }
+ hintformat(const hintformat &hf)
+ : fmt(hf.fmt)
+ {}
+
+
+ std::string str() const
+ {
+ return fmt.str();
+ }
+
+ template <typename U>
+ friend class AddHint;
+private:
+ format fmt;
+};
+
+std::ostream& operator<<(std::ostream &os, const hintformat &hf);
+
+template<typename... Args>
+inline hintformat hintfmt(const std::string & fs, const Args & ... args)
+{
+ hintformat f(fs);
+ formatHelper(f, args...);
+ return f;
+}
+
+}