lix/src/libutil/fmt.hh
eldritch horrors cd654451c9 Merge pull request #9924 from 9999years/rename-yellowtxt
Rename `yellowtxt` -> `magentatxt`

(cherry picked from commit fb78a99e04206e7b1df84a362bb87d3300b41855)
Change-Id: I9ade553d9f499e6713aeff3463c9a653a880a051
2024-03-04 08:53:10 +01:00

146 lines
2.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
///@file
#include <boost/format.hpp>
#include <string>
#include "ansicolor.hh"
namespace nix {
/**
* Inherit some names from other namespaces for convenience.
*/
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...) {} };
/**
* 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;
}
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 magenta.
template <class T>
struct magentatxt
{
magentatxt(const T &s) : value(s) {}
const T & value;
};
template <class T>
std::ostream & operator<<(std::ostream & out, const magentatxt<T> & y)
{
return out << ANSI_WARNING << 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 std::string & format) : fmt(format)
{
fmt.exceptions(boost::io::all_error_bits ^
boost::io::too_many_args_bit ^
boost::io::too_few_args_bit);
}
hintformat(const hintformat & hf)
: fmt(hf.fmt)
{ }
hintformat(format && fmt)
: fmt(std::move(fmt))
{ }
template<class T>
hintformat & operator%(const T & value)
{
fmt % magentatxt(value);
return *this;
}
template<class T>
hintformat & operator%(const normaltxt<T> & value)
{
fmt % value.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;
}
inline hintformat hintfmt(const std::string & plain_string)
{
// we won't be receiving any args in this case, so just print the original string
return hintfmt("%s", normaltxt(plain_string));
}
}