File indexing completed on 2025-01-18 09:54:43
0001
0002
0003
0004
0005
0006
0007 #pragma once
0008
0009
0010 #include <CLI/StringTools.hpp>
0011
0012
0013 #include <string>
0014 #include <vector>
0015
0016
0017 namespace CLI {
0018
0019
0020 namespace detail {
0021 CLI11_INLINE std::vector<std::string> split(const std::string &s, char delim) {
0022 std::vector<std::string> elems;
0023
0024 if(s.empty()) {
0025 elems.emplace_back();
0026 } else {
0027 std::stringstream ss;
0028 ss.str(s);
0029 std::string item;
0030 while(std::getline(ss, item, delim)) {
0031 elems.push_back(item);
0032 }
0033 }
0034 return elems;
0035 }
0036
0037 CLI11_INLINE std::string <rim(std::string &str) {
0038 auto it = std::find_if(str.begin(), str.end(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });
0039 str.erase(str.begin(), it);
0040 return str;
0041 }
0042
0043 CLI11_INLINE std::string <rim(std::string &str, const std::string &filter) {
0044 auto it = std::find_if(str.begin(), str.end(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });
0045 str.erase(str.begin(), it);
0046 return str;
0047 }
0048
0049 CLI11_INLINE std::string &rtrim(std::string &str) {
0050 auto it = std::find_if(str.rbegin(), str.rend(), [](char ch) { return !std::isspace<char>(ch, std::locale()); });
0051 str.erase(it.base(), str.end());
0052 return str;
0053 }
0054
0055 CLI11_INLINE std::string &rtrim(std::string &str, const std::string &filter) {
0056 auto it =
0057 std::find_if(str.rbegin(), str.rend(), [&filter](char ch) { return filter.find(ch) == std::string::npos; });
0058 str.erase(it.base(), str.end());
0059 return str;
0060 }
0061
0062 CLI11_INLINE std::string &remove_quotes(std::string &str) {
0063 if(str.length() > 1 && (str.front() == '"' || str.front() == '\'')) {
0064 if(str.front() == str.back()) {
0065 str.pop_back();
0066 str.erase(str.begin(), str.begin() + 1);
0067 }
0068 }
0069 return str;
0070 }
0071
0072 CLI11_INLINE std::string fix_newlines(const std::string &leader, std::string input) {
0073 std::string::size_type n = 0;
0074 while(n != std::string::npos && n < input.size()) {
0075 n = input.find('\n', n);
0076 if(n != std::string::npos) {
0077 input = input.substr(0, n + 1) + leader + input.substr(n + 1);
0078 n += leader.size();
0079 }
0080 }
0081 return input;
0082 }
0083
0084 CLI11_INLINE std::ostream &
0085 format_help(std::ostream &out, std::string name, const std::string &description, std::size_t wid) {
0086 name = " " + name;
0087 out << std::setw(static_cast<int>(wid)) << std::left << name;
0088 if(!description.empty()) {
0089 if(name.length() >= wid)
0090 out << "\n" << std::setw(static_cast<int>(wid)) << "";
0091 for(const char c : description) {
0092 out.put(c);
0093 if(c == '\n') {
0094 out << std::setw(static_cast<int>(wid)) << "";
0095 }
0096 }
0097 }
0098 out << "\n";
0099 return out;
0100 }
0101
0102 CLI11_INLINE std::ostream &format_aliases(std::ostream &out, const std::vector<std::string> &aliases, std::size_t wid) {
0103 if(!aliases.empty()) {
0104 out << std::setw(static_cast<int>(wid)) << " aliases: ";
0105 bool front = true;
0106 for(const auto &alias : aliases) {
0107 if(!front) {
0108 out << ", ";
0109 } else {
0110 front = false;
0111 }
0112 out << detail::fix_newlines(" ", alias);
0113 }
0114 out << "\n";
0115 }
0116 return out;
0117 }
0118
0119 CLI11_INLINE bool valid_name_string(const std::string &str) {
0120 if(str.empty() || !valid_first_char(str[0])) {
0121 return false;
0122 }
0123 auto e = str.end();
0124 for(auto c = str.begin() + 1; c != e; ++c)
0125 if(!valid_later_char(*c))
0126 return false;
0127 return true;
0128 }
0129
0130 CLI11_INLINE std::string find_and_replace(std::string str, std::string from, std::string to) {
0131
0132 std::size_t start_pos = 0;
0133
0134 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
0135 str.replace(start_pos, from.length(), to);
0136 start_pos += to.length();
0137 }
0138
0139 return str;
0140 }
0141
0142 CLI11_INLINE void remove_default_flag_values(std::string &flags) {
0143 auto loc = flags.find_first_of('{', 2);
0144 while(loc != std::string::npos) {
0145 auto finish = flags.find_first_of("},", loc + 1);
0146 if((finish != std::string::npos) && (flags[finish] == '}')) {
0147 flags.erase(flags.begin() + static_cast<std::ptrdiff_t>(loc),
0148 flags.begin() + static_cast<std::ptrdiff_t>(finish) + 1);
0149 }
0150 loc = flags.find_first_of('{', loc + 1);
0151 }
0152 flags.erase(std::remove(flags.begin(), flags.end(), '!'), flags.end());
0153 }
0154
0155 CLI11_INLINE std::ptrdiff_t
0156 find_member(std::string name, const std::vector<std::string> names, bool ignore_case, bool ignore_underscore) {
0157 auto it = std::end(names);
0158 if(ignore_case) {
0159 if(ignore_underscore) {
0160 name = detail::to_lower(detail::remove_underscore(name));
0161 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
0162 return detail::to_lower(detail::remove_underscore(local_name)) == name;
0163 });
0164 } else {
0165 name = detail::to_lower(name);
0166 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
0167 return detail::to_lower(local_name) == name;
0168 });
0169 }
0170
0171 } else if(ignore_underscore) {
0172 name = detail::remove_underscore(name);
0173 it = std::find_if(std::begin(names), std::end(names), [&name](std::string local_name) {
0174 return detail::remove_underscore(local_name) == name;
0175 });
0176 } else {
0177 it = std::find(std::begin(names), std::end(names), name);
0178 }
0179
0180 return (it != std::end(names)) ? (it - std::begin(names)) : (-1);
0181 }
0182
0183 CLI11_INLINE std::vector<std::string> split_up(std::string str, char delimiter) {
0184
0185 const std::string delims("\'\"`");
0186 auto find_ws = [delimiter](char ch) {
0187 return (delimiter == '\0') ? std::isspace<char>(ch, std::locale()) : (ch == delimiter);
0188 };
0189 trim(str);
0190
0191 std::vector<std::string> output;
0192 bool embeddedQuote = false;
0193 char keyChar = ' ';
0194 while(!str.empty()) {
0195 if(delims.find_first_of(str[0]) != std::string::npos) {
0196 keyChar = str[0];
0197 auto end = str.find_first_of(keyChar, 1);
0198 while((end != std::string::npos) && (str[end - 1] == '\\')) {
0199 end = str.find_first_of(keyChar, end + 1);
0200 embeddedQuote = true;
0201 }
0202 if(end != std::string::npos) {
0203 output.push_back(str.substr(1, end - 1));
0204 if(end + 2 < str.size()) {
0205 str = str.substr(end + 2);
0206 } else {
0207 str.clear();
0208 }
0209
0210 } else {
0211 output.push_back(str.substr(1));
0212 str = "";
0213 }
0214 } else {
0215 auto it = std::find_if(std::begin(str), std::end(str), find_ws);
0216 if(it != std::end(str)) {
0217 std::string value = std::string(str.begin(), it);
0218 output.push_back(value);
0219 str = std::string(it + 1, str.end());
0220 } else {
0221 output.push_back(str);
0222 str = "";
0223 }
0224 }
0225
0226 if(embeddedQuote) {
0227 output.back() = find_and_replace(output.back(), std::string("\\") + keyChar, std::string(1, keyChar));
0228 embeddedQuote = false;
0229 }
0230 trim(str);
0231 }
0232 return output;
0233 }
0234
0235 CLI11_INLINE std::size_t escape_detect(std::string &str, std::size_t offset) {
0236 auto next = str[offset + 1];
0237 if((next == '\"') || (next == '\'') || (next == '`')) {
0238 auto astart = str.find_last_of("-/ \"\'`", offset - 1);
0239 if(astart != std::string::npos) {
0240 if(str[astart] == ((str[offset] == '=') ? '-' : '/'))
0241 str[offset] = ' ';
0242 }
0243 }
0244 return offset + 1;
0245 }
0246
0247 CLI11_INLINE std::string &add_quotes_if_needed(std::string &str) {
0248 if((str.front() != '"' && str.front() != '\'') || str.front() != str.back()) {
0249 char quote = str.find('"') < str.find('\'') ? '\'' : '"';
0250 if(str.find(' ') != std::string::npos) {
0251 str.insert(0, 1, quote);
0252 str.append(1, quote);
0253 }
0254 }
0255 return str;
0256 }
0257
0258 }
0259
0260 }