Add a format function for printf like formatting
This commit is contained in:
parent
8761fc34f4
commit
13a5af70ae
|
@ -205,4 +205,46 @@ Vector<StringView> wrap_lines(StringView text, CharCount max_width)
|
|||
return lines;
|
||||
}
|
||||
|
||||
String format(StringView fmt, ArrayView<const StringView> params)
|
||||
{
|
||||
ByteCount size = fmt.length();
|
||||
for (auto& s : params) size += s.length();
|
||||
String res;
|
||||
res.reserve(size);
|
||||
|
||||
int implicitIndex = 0;
|
||||
for (auto it = fmt.begin(), end = fmt.end(); it != end;)
|
||||
{
|
||||
auto opening = std::find(it, end, '{');
|
||||
res += StringView{it, opening};
|
||||
if (opening == end)
|
||||
break;
|
||||
|
||||
if (opening != it && res.back() == '\\')
|
||||
{
|
||||
res.back() = '{';
|
||||
it = opening + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto closing = std::find(it, end, '}');
|
||||
if (closing == end)
|
||||
throw runtime_error("Format string error, unclosed '{'");
|
||||
int index;
|
||||
if (closing == opening + 1)
|
||||
index = implicitIndex;
|
||||
else
|
||||
index = str_to_int({opening+1, closing});
|
||||
|
||||
if (index >= params.size())
|
||||
throw runtime_error("Format string parameter index too big");
|
||||
|
||||
res += params[index];
|
||||
implicitIndex = index+1;
|
||||
it = closing+1;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "utf8.hh"
|
||||
#include "hash.hh"
|
||||
#include "vector.hh"
|
||||
#include "array_view.hh"
|
||||
|
||||
#include <string>
|
||||
#include <climits>
|
||||
|
@ -276,6 +277,27 @@ String expand_tabs(StringView line, CharCount tabstop, CharCount col = 0);
|
|||
|
||||
Vector<StringView> wrap_lines(StringView text, CharCount max_width);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename T> using IsString = std::is_convertible<T, StringView>;
|
||||
|
||||
template<typename T, class = typename std::enable_if<!IsString<T>::value>::type>
|
||||
String format_param(const T& val) { return to_string(val); }
|
||||
|
||||
template<typename T, class = typename std::enable_if<IsString<T>::value>::type>
|
||||
StringView format_param(const T& val) { return val; }
|
||||
|
||||
}
|
||||
|
||||
String format(StringView fmt, ArrayView<const StringView> params);
|
||||
|
||||
template<typename... Types>
|
||||
String format(StringView fmt, Types... params)
|
||||
{
|
||||
return format(fmt, ArrayView<const StringView>{{detail::format_param(params)...}});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // string_hh_INCLUDED
|
||||
|
|
|
@ -137,6 +137,8 @@ void test_string()
|
|||
kak_assert(subsequence_match("tchou kanaky", "knk"));
|
||||
kak_assert(subsequence_match("tchou kanaky", "tchou kanaky"));
|
||||
kak_assert(not subsequence_match("tchou kanaky", "tchou kanaky"));
|
||||
|
||||
kak_assert(format("Youhou {1} {} {0} \\{}", 10, "hehe", 5) == "Youhou hehe 5 10 {}");
|
||||
}
|
||||
|
||||
void test_keys()
|
||||
|
|
Loading…
Reference in New Issue
Block a user