Opt-in types for quoting of option lists

This avoid quoting ints in int-lists for example, as they do not
risk containing whitespaces.

Fixes #2223
This commit is contained in:
Maxime Coste 2018-07-22 15:51:32 +10:00
parent 019150ba52
commit 7b9f162e7d
3 changed files with 26 additions and 4 deletions

View File

@ -42,6 +42,11 @@ option_add_from_strings(T& opt, ConstArrayView<String> strs)
return option_add(opt, strs[0]); return option_add(opt, strs[0]);
} }
template<typename T>
constexpr bool option_needs_quoting(Meta::Type<T>)
{
return false;
}
template<typename P, typename T> template<typename P, typename T>
struct PrefixedList struct PrefixedList

View File

@ -18,6 +18,20 @@
namespace Kakoune namespace Kakoune
{ {
template<typename T, typename... Rest>
constexpr bool option_needs_quoting(Meta::Type<T> type, Meta::Type<Rest>... rest)
{
return option_needs_quoting(type) or option_needs_quoting(rest...);
}
template<typename... Ts>
String quote_ifn(String str)
{
if (option_needs_quoting(Meta::Type<Ts>{}...))
return quote(std::move(str));
return str;
}
template<typename T> template<typename T>
constexpr decltype(T::option_type_name) option_type_name(Meta::Type<T>) constexpr decltype(T::option_type_name) option_type_name(Meta::Type<T>)
{ {
@ -66,6 +80,7 @@ inline Codepoint option_from_string(Meta::Type<Codepoint>, StringView str)
return str[0_char]; return str[0_char];
} }
constexpr StringView option_type_name(Meta::Type<Codepoint>) { return "codepoint"; } constexpr StringView option_type_name(Meta::Type<Codepoint>) { return "codepoint"; }
constexpr bool option_needs_quoting(Meta::Type<Codepoint>) { return true; }
template<typename T, MemoryDomain domain> template<typename T, MemoryDomain domain>
Vector<String> option_to_strings(const Vector<T, domain>& opt) Vector<String> option_to_strings(const Vector<T, domain>& opt)
@ -76,7 +91,7 @@ Vector<String> option_to_strings(const Vector<T, domain>& opt)
template<typename T, MemoryDomain domain> template<typename T, MemoryDomain domain>
String option_to_string(const Vector<T, domain>& opt) String option_to_string(const Vector<T, domain>& opt)
{ {
return join(opt | transform([](const T& t) { return quote(option_to_string(t)); }), ' ', false); return join(opt | transform([](const T& t) { return quote_ifn<T>(option_to_string(t)); }), ' ', false);
} }
template<typename T, MemoryDomain domain> template<typename T, MemoryDomain domain>
@ -123,9 +138,10 @@ template<typename Key, typename Value, MemoryDomain domain>
String option_to_string(const HashMap<Key, Value, domain>& opt) String option_to_string(const HashMap<Key, Value, domain>& opt)
{ {
return join(opt | transform([](auto&& item) { return join(opt | transform([](auto&& item) {
return quote(format("{}={}", return quote_ifn<Key, Value>(
escape(option_to_string(item.key), '=', '\\'), format("{}={}",
escape(option_to_string(item.value), '=', '\\'))); escape(option_to_string(item.key), '=', '\\'),
escape(option_to_string(item.value), '=', '\\')));
}), ' ', false); }), ' ', false);
} }

View File

@ -68,6 +68,7 @@ Optional<int> str_to_int_ifp(StringView str);
inline String option_to_string(StringView opt) { return opt.str(); } inline String option_to_string(StringView opt) { return opt.str(); }
inline String option_from_string(Meta::Type<String>, StringView str) { return str.str(); } inline String option_from_string(Meta::Type<String>, StringView str) { return str.str(); }
inline bool option_add(String& opt, StringView val) { opt += val; return not val.empty(); } inline bool option_add(String& opt, StringView val) { opt += val; return not val.empty(); }
constexpr bool option_needs_quoting(Meta::Type<String>) { return true; }
template<size_t N> template<size_t N>
struct InplaceString struct InplaceString