29template <typename T, typename = typename std::enable_if<std::is_enum<T>::value>::type>
30std::ostream &
operator<<(std::ostream &in,
const T &item) {
32 return in << static_cast<typename std::underlying_type<T>::type>(item);
38using enums::operator<<;
46inline std::vector<std::string>
split(
const std::string &s,
char delim) {
47 std::vector<std::string> elems;
55 while(std::getline(ss, item, delim)) {
56 elems.push_back(item);
63template <
typename T> std::string
join(
const T &v, std::string delim =
",") {
65 auto beg = std::begin(v);
66 auto end = std::end(v);
78 typename =
typename std::enable_if<!std::is_constructible<std::string, Callable>::value>::type>
79std::string
join(
const T &v, Callable func, std::string delim =
",") {
81 auto beg = std::begin(v);
82 auto end = std::end(v);
85 auto nloc = s.tellp();
96template <
typename T> std::string
rjoin(
const T &v, std::string delim =
",") {
98 for(std::size_t start = 0; start < v.size(); start++) {
101 s << v[v.size() - start - 1];
109inline std::string &
ltrim(std::string &str) {
110 auto it = std::find_if(str.begin(), str.end(), [](
char ch) { return !std::isspace<char>(ch, std::locale()); });
111 str.erase(str.begin(), it);
116inline std::string &
ltrim(std::string &str,
const std::string &filter) {
117 auto it = std::find_if(str.begin(), str.end(), [&filter](
char ch) { return filter.find(ch) == std::string::npos; });
118 str.erase(str.begin(), it);
123inline std::string &
rtrim(std::string &str) {
124 auto it = std::find_if(str.rbegin(), str.rend(), [](
char ch) { return !std::isspace<char>(ch, std::locale()); });
125 str.erase(it.base(), str.end());
130inline std::string &
rtrim(std::string &str,
const std::string &filter) {
132 std::find_if(str.rbegin(), str.rend(), [&filter](
char ch) { return filter.find(ch) == std::string::npos; });
133 str.erase(it.base(), str.end());
141inline std::string &
trim(std::string &str,
const std::string filter) {
return ltrim(
rtrim(str, filter), filter); }
151 if(str.length() > 1 && (str.front() ==
'"' || str.front() ==
'\'')) {
152 if(str.front() == str.back()) {
154 str.erase(str.begin(), str.begin() + 1);
164inline std::string
fix_newlines(
const std::string &leader, std::string input) {
165 std::string::size_type n = 0;
166 while(n != std::string::npos && n < input.size()) {
167 n = input.find(
'\n', n);
168 if(n != std::string::npos) {
169 input = input.substr(0, n + 1) + leader + input.substr(n + 1);
177inline std::string
trim_copy(
const std::string &str,
const std::string &filter) {
179 return trim(s, filter);
182inline std::ostream &
format_help(std::ostream &out, std::string name,
const std::string &description, std::size_t wid) {
184 out << std::setw(static_cast<int>(wid)) << std::left << name;
185 if(!description.empty()) {
186 if(name.length() >= wid)
187 out <<
"\n" << std::setw(
static_cast<int>(wid)) <<
"";
188 for(
const char c : description) {
191 out << std::setw(static_cast<int>(wid)) <<
"";
200inline std::ostream &
format_aliases(std::ostream &out,
const std::vector<std::string> &aliases, std::size_t wid) {
201 if(!aliases.empty()) {
202 out << std::setw(static_cast<int>(wid)) <<
" aliases: ";
204 for(
const auto &alias : aliases) {
219template <
typename T>
bool valid_first_char(T c) {
return ((c !=
'-') && (c !=
'!') && (c !=
' ') && c !=
'\n'); }
226 return ((c !=
'=') && (c !=
':') && (c !=
'{') && (c !=
' ') && c !=
'\n');
235 for(
auto c = str.begin() + 1; c != e; ++c)
243 static const std::string badChars(std::string(
"\n") +
'\0');
244 return (str.find_first_of(badChars) == std::string::npos);
249 static const std::string sep(
"%%");
250 return (str.empty() || str == sep);
255 return std::all_of(str.begin(), str.end(), [](
char c) { return std::isalpha(c, std::locale()); });
260 std::transform(std::begin(str), std::end(str), std::begin(str), [](
const std::string::value_type &x) {
261 return std::tolower(x, std::locale());
268 str.erase(std::remove(std::begin(str), std::end(str),
'_'), std::end(str));
275 std::size_t start_pos = 0;
277 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
278 str.replace(start_pos, from.length(), to);
279 start_pos += to.length();
287 return (flags.find_first_of(
"{!") != std::string::npos);
291 auto loc = flags.find_first_of(
'{', 2);
292 while(loc != std::string::npos) {
293 auto finish = flags.find_first_of(
"},", loc + 1);
294 if((finish != std::string::npos) && (flags[finish] ==
'}')) {
295 flags.erase(flags.begin() +
static_cast<std::ptrdiff_t
>(loc),
296 flags.begin() +
static_cast<std::ptrdiff_t
>(finish) + 1);
298 loc = flags.find_first_of(
'{', loc + 1);
300 flags.erase(std::remove(flags.begin(), flags.end(),
'!'), flags.end());
305 const std::vector<std::string> names,
308 auto it = std::end(names);
312 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
317 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
324 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
328 it = std::find(std::begin(names), std::end(names), name);
331 return (it != std::end(names)) ? (it - std::begin(names)) : (-1);
336template <
typename Callable>
inline std::string
find_and_modify(std::string str, std::string trigger, Callable modify) {
337 std::size_t start_pos = 0;
338 while((start_pos = str.find(trigger, start_pos)) != std::string::npos) {
339 start_pos = modify(str, start_pos);
346inline std::vector<std::string> split_up(std::string str,
char delimiter =
'\0') {
348 const std::string delims(
"\'\"`");
350 return (delimiter ==
'\0') ? (std::isspace<char>(ch, std::locale()) != 0) : (ch == delimiter);
357 while(!str.empty()) {
358 if(delims.find_first_of(str[0]) != std::string::npos) {
360 auto end = str.find_first_of(
keyChar, 1);
361 while((end != std::string::npos) && (str[end - 1] ==
'\\')) {
362 end = str.find_first_of(
keyChar, end + 1);
365 if(end != std::string::npos) {
366 output.push_back(str.substr(1, end - 1));
367 if(end + 2 < str.size()) {
368 str = str.substr(end + 2);
374 output.push_back(str.substr(1));
378 auto it = std::find_if(std::begin(str), std::end(str),
find_ws);
379 if(it != std::end(str)) {
380 std::string value = std::string(str.begin(), it);
382 str = std::string(it + 1, str.end());
403 auto next = str[offset + 1];
404 if((next ==
'\"') || (next ==
'\'') || (next ==
'`')) {
405 auto astart = str.find_last_of(
"-/ \"\'`", offset - 1);
406 if(astart != std::string::npos) {
407 if(str[astart] == ((str[offset] ==
'=') ?
'-' :
'/'))
416 if((str.front() !=
'"' && str.front() !=
'\'') || str.front() != str.back()) {
417 char quote = str.find(
'"') < str.find(
'\'') ?
'\'' :
'"';
418 if(str.find(
' ') != std::string::npos) {
419 str.insert(0, 1, quote);
420 str.append(1, quote);
std::string & remove_quotes(std::string &str)
remove quotes at the front and back of a string either '"' or '\''
Definition StringTools.hpp:150
std::vector< std::string > output
Definition StringTools.hpp:354
std::string & rtrim(std::string &str)
Trim whitespace from right of string.
Definition StringTools.hpp:123
std::ptrdiff_t find_member(std::string name, const std::vector< std::string > names, bool ignore_case=false, bool ignore_underscore=false)
Check if a string is a member of a list of strings and optionally ignore case or ignore underscores.
Definition StringTools.hpp:304
bool valid_first_char(T c)
Definition StringTools.hpp:219
bool valid_name_string(const std::string &str)
Verify an option/subcommand name.
Definition StringTools.hpp:230
std::ostream & format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid)
Print a two part "help" string.
Definition StringTools.hpp:182
std::string remove_underscore(std::string str)
remove underscores from a string
Definition StringTools.hpp:267
bool is_separator(const std::string &str)
check if a string is a container segment separator (empty or "%%")
Definition StringTools.hpp:248
std::string find_and_modify(std::string str, std::string trigger, Callable modify)
Definition StringTools.hpp:336
std::string trim_copy(const std::string &str)
Make a copy of the string and then trim it.
Definition StringTools.hpp:144
std::string & trim(std::string &str)
Trim whitespace from string.
Definition StringTools.hpp:138
auto find_ws
Definition StringTools.hpp:349
std::string fix_newlines(const std::string &leader, std::string input)
Definition StringTools.hpp:164
void remove_default_flag_values(std::string &flags)
Definition StringTools.hpp:290
std::ostream & format_aliases(std::ostream &out, const std::vector< std::string > &aliases, std::size_t wid)
Print subcommand aliases.
Definition StringTools.hpp:200
bool valid_later_char(T c)
Verify following characters of an option.
Definition StringTools.hpp:222
constexpr int expected_max_vector_size
Definition StringTools.hpp:43
std::string & ltrim(std::string &str)
Trim whitespace from left of string.
Definition StringTools.hpp:109
std::string join(const T &v, std::string delim=",")
Simple function to join a string.
Definition StringTools.hpp:63
std::string find_and_replace(std::string str, std::string from, std::string to)
Find and replace a substring with another substring.
Definition StringTools.hpp:273
std::vector< std::string > split(const std::string &s, char delim)
Split a string by a delim.
Definition StringTools.hpp:46
bool valid_alias_name_string(const std::string &str)
Verify an app name.
Definition StringTools.hpp:242
bool isalpha(const std::string &str)
Verify that str consists of letters only.
Definition StringTools.hpp:254
bool embeddedQuote
Definition StringTools.hpp:355
std::string to_lower(std::string str)
Return a lower case version of a string.
Definition StringTools.hpp:259
bool has_default_flag_values(const std::string &flags)
check if the flag definitions has possible false flags
Definition StringTools.hpp:286
char keyChar
Definition StringTools.hpp:356
std::string rjoin(const T &v, std::string delim=",")
Join a string in reverse order.
Definition StringTools.hpp:96
std::ostream & operator<<(std::ostream &in, const T &item)
output streaming for enumerations
Definition StringTools.hpp:30
std::string ignore_case(std::string item)
Helper function to allow ignore_case to be passed to IsMember or Transform.
Definition Validators.hpp:909
std::string ignore_underscore(std::string item)
Helper function to allow ignore_underscore to be passed to IsMember or Transform.
Definition Validators.hpp:912
std::string & add_quotes_if_needed(std::string &str)
Add quotes if the string contains spaces.
Definition StringTools.hpp:415
std::size_t escape_detect(std::string &str, std::size_t offset)
Definition StringTools.hpp:402