2020-04-21 22:25:41 +03:00
|
|
|
|
#pragma once
|
2023-04-01 06:18:41 +03:00
|
|
|
|
///@file
|
2020-04-21 22:25:41 +03:00
|
|
|
|
|
|
|
|
|
#include <boost/format.hpp>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include "ansicolor.hh"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
|
|
|
|
|
|
2023-03-27 04:12:25 +03:00
|
|
|
|
/**
|
|
|
|
|
* Inherit some names from other namespaces for convenience.
|
|
|
|
|
*/
|
2020-04-21 22:25:41 +03:00
|
|
|
|
using boost::format;
|
|
|
|
|
|
|
|
|
|
|
2023-03-27 04:12:25 +03:00
|
|
|
|
/**
|
|
|
|
|
* A variadic template that does nothing. Useful to call a function
|
|
|
|
|
* for all variadic arguments but ignoring the result.
|
|
|
|
|
*/
|
2020-04-21 22:25:41 +03:00
|
|
|
|
struct nop { template<typename... T> nop(T...) {} };
|
|
|
|
|
|
|
|
|
|
|
2023-03-27 04:12:25 +03:00
|
|
|
|
/**
|
|
|
|
|
* 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).
|
|
|
|
|
*/
|
2020-04-21 22:25:41 +03:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-01 17:33:22 +02:00
|
|
|
|
inline std::string fmt(std::string_view s)
|
|
|
|
|
{
|
|
|
|
|
return std::string(s);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-21 22:25:41 +03:00
|
|
|
|
inline std::string fmt(const char * s)
|
|
|
|
|
{
|
|
|
|
|
return 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
|
2024-02-04 05:16:30 +02:00
|
|
|
|
// are always in magenta.
|
2020-04-21 22:25:41 +03:00
|
|
|
|
template <class T>
|
2024-02-04 05:16:30 +02:00
|
|
|
|
struct magentatxt
|
2020-04-21 22:25:41 +03:00
|
|
|
|
{
|
2024-02-04 05:16:30 +02:00
|
|
|
|
magentatxt(const T &s) : value(s) {}
|
2020-10-07 17:33:19 +03:00
|
|
|
|
const T & value;
|
2020-04-21 22:25:41 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <class T>
|
2024-02-04 05:16:30 +02:00
|
|
|
|
std::ostream & operator<<(std::ostream & out, const magentatxt<T> & y)
|
2020-04-21 22:25:41 +03:00
|
|
|
|
{
|
2021-09-14 11:38:10 +03:00
|
|
|
|
return out << ANSI_WARNING << y.value << ANSI_NORMAL;
|
2020-04-21 22:25:41 +03:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-05 01:19:20 +03:00
|
|
|
|
template <class T>
|
|
|
|
|
struct normaltxt
|
|
|
|
|
{
|
2020-10-07 17:33:19 +03:00
|
|
|
|
normaltxt(const T & s) : value(s) {}
|
|
|
|
|
const T & value;
|
2020-05-05 01:19:20 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <class T>
|
2020-10-07 17:33:19 +03:00
|
|
|
|
std::ostream & operator<<(std::ostream & out, const normaltxt<T> & y)
|
2020-05-05 01:19:20 +03:00
|
|
|
|
{
|
|
|
|
|
return out << ANSI_NORMAL << y.value;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-21 22:25:41 +03:00
|
|
|
|
class hintformat
|
|
|
|
|
{
|
|
|
|
|
public:
|
2022-02-25 17:00:00 +02:00
|
|
|
|
hintformat(const std::string & format) : fmt(format)
|
2020-04-21 22:25:41 +03:00
|
|
|
|
{
|
2020-10-07 17:33:19 +03:00
|
|
|
|
fmt.exceptions(boost::io::all_error_bits ^
|
2020-06-20 00:29:19 +03:00
|
|
|
|
boost::io::too_many_args_bit ^
|
|
|
|
|
boost::io::too_few_args_bit);
|
2020-04-21 22:25:41 +03:00
|
|
|
|
}
|
2020-04-24 21:44:23 +03:00
|
|
|
|
|
2020-10-07 17:33:19 +03:00
|
|
|
|
hintformat(const hintformat & hf)
|
|
|
|
|
: fmt(hf.fmt)
|
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
hintformat(format && fmt)
|
|
|
|
|
: fmt(std::move(fmt))
|
|
|
|
|
{ }
|
2020-04-24 21:44:23 +03:00
|
|
|
|
|
2020-04-21 22:25:41 +03:00
|
|
|
|
template<class T>
|
2020-10-07 17:33:19 +03:00
|
|
|
|
hintformat & operator%(const T & value)
|
2020-04-21 22:25:41 +03:00
|
|
|
|
{
|
2024-02-04 05:16:30 +02:00
|
|
|
|
fmt % magentatxt(value);
|
2020-04-21 22:25:41 +03:00
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-22 20:32:20 +03:00
|
|
|
|
template<class T>
|
2020-10-07 17:33:19 +03:00
|
|
|
|
hintformat & operator%(const normaltxt<T> & value)
|
2020-06-22 20:32:20 +03:00
|
|
|
|
{
|
|
|
|
|
fmt % value.value;
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-21 22:25:41 +03:00
|
|
|
|
std::string str() const
|
|
|
|
|
{
|
|
|
|
|
return fmt.str();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
format fmt;
|
|
|
|
|
};
|
|
|
|
|
|
2020-10-07 17:33:19 +03:00
|
|
|
|
std::ostream & operator<<(std::ostream & os, const hintformat & hf);
|
2020-04-21 22:25:41 +03:00
|
|
|
|
|
|
|
|
|
template<typename... Args>
|
|
|
|
|
inline hintformat hintfmt(const std::string & fs, const Args & ... args)
|
|
|
|
|
{
|
|
|
|
|
hintformat f(fs);
|
|
|
|
|
formatHelper(f, args...);
|
|
|
|
|
return f;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-07 13:58:58 +02:00
|
|
|
|
inline hintformat hintfmt(const std::string & plain_string)
|
2020-06-20 00:29:19 +03:00
|
|
|
|
{
|
2020-06-22 19:00:37 +03:00
|
|
|
|
// we won't be receiving any args in this case, so just print the original string
|
2020-06-22 20:32:20 +03:00
|
|
|
|
return hintfmt("%s", normaltxt(plain_string));
|
2020-06-20 00:29:19 +03:00
|
|
|
|
}
|
2022-01-21 17:13:34 +02:00
|
|
|
|
|
2020-04-21 22:25:41 +03:00
|
|
|
|
}
|