1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
#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 yellowtxt
{
yellowtxt(const T &s) : value(s) {}
const T &value;
};
template <class T>
std::ostream& operator<<(std::ostream &out, const yellowtxt<T> &y)
{
return out << ANSI_YELLOW << y.value << ANSI_NORMAL;
}
template <class T>
struct normaltxt
{
normaltxt(const T &s) : value(s) {}
const T &value;
};
template <class T>
std::ostream& operator<<(std::ostream &out, const normaltxt<T> &y)
{
return out << ANSI_NORMAL << y.value;
}
class hintformat
{
public:
hintformat(const string &format) :fmt(format)
{
fmt.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
}
hintformat(const hintformat &hf)
: fmt(hf.fmt)
{}
template<class T>
hintformat& operator%(const T &value)
{
fmt % yellowtxt(value);
return *this;
}
std::string str() const
{
return fmt.str();
}
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;
}
}
|