Add a format function for printf like formatting

This commit is contained in:
Maxime Coste 2015-03-30 23:05:24 +01:00
parent 8761fc34f4
commit 13a5af70ae
3 changed files with 66 additions and 0 deletions

View File

@ -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;
}
}

View File

@ -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

View File

@ -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()