16#include <unordered_map>
33 AliasInfo(
const std::string &val,
const std::string &sep=std::string())
40using AliasInfoMap = std::unordered_map<std::string,AliasOverloads>;
45 std::string_view s,
bool allowRecursion=
FALSE);
48static std::string
expandAlias(std::string_view aliasName,std::string_view aliasValue);
59 std::string aliasName;
60 std::string aliasValue;
62 std::string separator;
64 static std::string_view separators =
"!#$%&,.?|;:'+=~`/";
65 auto isValidSeparator = [](
char c) ->
bool {
return separators.find(c)!=std::string::npos; };
67 static const reg::Ex re1(R
"(^\a[\w-]*\s*=)");
68 static const reg::Ex re2(R
"(^\a[\w-]*{[^}]*}\s*=)");
71 size_t i=alias.find(
'=');
72 assert(i!=std::string::npos);
74 aliasValue = alias.substr(i+1);
76 size_t l = name.length();
77 size_t j = name.find(
'{');
78 if (j!=std::string::npos)
84 while (k<l-1 && isdigit(name[k])) k++;
85 numParams = atoi(name.substr(j+1,k-j-1).c_str());
91 while (m<l && isValidSeparator(name[m])) m++;
94 err(
"Invalid alias '%s': invalid separator character '%c' (code %d), allowed characters: %s. Check your config file.\n",
qPrint(alias),name[m],name[m],
qPrint(std::string{separators}));
99 separator=name.substr(k,l-k-1);
104 aliasName = name.substr(0,j);
111 err(
"Invalid alias '%s': missing number of parameters. Check your config file.\n",
qPrint(std::string{alias}));
117 err(
"Invalid alias '%s': missing closing bracket. Check your config file.\n",
qPrint(std::string{alias}));
130 err(
"Invalid alias '%s': invalid 'name=' or 'name{...}=' part. Check you config file.\n",
qPrint(std::string{alias}));
144 auto it2 = it->second.find(numParams);
145 if (it2==it->second.end())
147 it->second.emplace(numParams,
AliasInfo(aliasValue,separator));
151 it2->second =
AliasInfo(aliasValue,separator);
174 for (
const auto &al : aliasList)
180 for (
auto &[numParams,aliasInfo] : overloads)
182 aliasInfo.value =
expandAlias(name+
":"+std::to_string(numParams),aliasInfo.value);
187 for (
auto &[numParams,aliasInfo] : overloads)
220 while (i<s.length() && (c=s[i]) &&
isId(c)) i++;
231 std::string_view aliasValue,std::string_view argList,
232 std::string_view sep)
238 size_t l=argList.length();
240 for (
size_t i=0;i<l;i++)
245 (i==0 || argList[i-1]!=
'\\') &&
246 argList.substr(i,sep.length())==sep)
248 args.push_back(argList.substr(p,i-p));
252 else if (c==
'@' || c==
'\\')
258 if (l>p) args.push_back(argList.substr(p));
262 std::vector<Marker> markerList;
263 l = aliasValue.length();
265 bool insideMarkerId =
false;
266 size_t markerStart = 0;
267 auto isDigit = [](
char c) {
return c>=
'0' && c<=
'9'; };
268 for (
size_t i=0;i<=l;i++)
270 char c = i<l ? aliasValue[i] :
'\0';
271 if (insideMarkerId && !isDigit(c))
273 insideMarkerId =
false;
274 size_t markerLen = i-markerStart;
275 markerList.emplace_back(markerStart-1,
276 static_cast<size_t>(std::stoi(std::string{aliasValue.substr(markerStart,markerLen)})),
279 if (c==
'\\' && (pc==
'@' || pc==
'\\'))
286 if (isDigit(c) && pc==
'\\')
298 for (
const Marker &m : markerList)
300 result+=aliasValue.substr(p,m.pos-p);
302 if (m.number>0 && m.number<=args.size())
310 result+=aliasValue.substr(p);
325 if (s.empty() || sep.empty())
return s;
327 result.reserve(s.length()+10);
328 size_t i, p=0, l=sep.length();
329 while ((i=s.find(sep,p))!=std::string::npos)
331 result += s.substr(p,i-p);
332 if (i>0 && s[i-1]!=
'\\')
336 result += s.substr(i,l);
339 result += s.substr(p);
347 static const reg::Ex re(R
"([\\@](\a[\w-]*))");
353 size_t i = match.position();
354 size_t l = match.length();
355 if (i>p) result+=s.substr(p,i-p);
358 bool hasArgs = !args.empty();
359 size_t argsLen = args.length();
360 std::string cmd = match[1].str();
361 int selectedNumArgs = -1;
367 size_t minusPos = cmd.find(
'-');
368 if (minusPos!=std::string::npos)
373 cmd = cmd.substr(0,minusPos);
388 for (
const auto &[numParams,aliasInfo] : it->second)
391 if (numParams==numArgs && numArgs>selectedNumArgs)
393 selectedNumArgs = numArgs;
396 if (selectedNumArgs==-1)
398 auto it2 = it->second.find(1);
399 if (it2 != it->second.end())
416 std::string qualifiedName = cmd+
":"+std::to_string(selectedNumArgs);
417 if ((allowRecursion || aliasesProcessed.find(qualifiedName)==aliasesProcessed.end()) &&
419 it->second.find(selectedNumArgs)!=it->second.end())
421 const auto &aliasInfo = it->second.find(selectedNumArgs)->second;
423 if (!allowRecursion) aliasesProcessed.insert(qualifiedName);
424 std::string val = aliasInfo.value;
433 if (!allowRecursion) aliasesProcessed.erase(qualifiedName);
435 if (hasArgs) p += argsLen+2;
440 result += match.str();
444 result += s.substr(p);
453 size_t l = args.length();
454 for (
size_t i=0;i<l;i++)
459 (i==0 || args[i-1]!=
'\\') &&
460 args.substr(i,sep.length())==sep)
464 else if (c==
'@' || c==
'\\')
478 if (!args.empty() && args[0]==
'{')
480 for (
size_t i=0;i<args.length();i++)
497 return std::string{args.substr(1,i-1)};
501 return std::string{};
514static std::string
expandAlias(std::string_view aliasName,std::string_view aliasValue)
519 aliasesProcessed.insert(std::string{aliasName});
bool isAliasCmd(std::string_view aliasCmd)
static std::string replaceAliasArguments(StringUnorderedSet &aliasesProcessed, std::string_view aliasValue, std::string_view argList, std::string_view sep)
Replaces the markers in an alias definition aliasValue with the corresponding values found in the com...
static size_t findEndOfCommand(std::string_view s)
For a string s that starts with a command name, returns the character offset within that string repre...
static std::string expandAlias(std::string_view aliasName, std::string_view aliasValue)
std::string resolveAliasCmd(std::string_view aliasCmd)
std::unordered_map< int, AliasInfo > AliasOverloads
static AliasInfoMap g_aliasInfoMap
static std::string escapeSeparators(const std::string &s, const std::string &sep)
std::unordered_map< std::string, AliasOverloads > AliasInfoMap
static std::string expandAliasRec(StringUnorderedSet &aliasesProcessed, std::string_view s, bool allowRecursion=FALSE)
static void addValidAliasToMap(std::string_view alias)
static std::string extractAliasArgs(std::string_view args)
static int countAliasArguments(std::string_view args, std::string_view sep)
static std::string escapeAlias(std::string_view value)
static void print(DebugMask mask, int prio, const char *fmt,...)
Class representing a regular expression.
Object representing the matching results.
#define Config_getList(name)
std::unordered_set< std::string > StringUnorderedSet
std::vector< std::string_view > StringViewVector
std::vector< std::string > StringVector
bool search(std::string_view str, Match &match, const Ex &re, size_t pos)
Search in a given string str starting at position pos for a match against regular expression re.
const char * qPrint(const char *s)
Some helper functions for std::string.
std::string substituteStringView(std::string_view s, std::string_view toReplace, std::string_view replaceWith)
Returns a new string where occurrences of substring toReplace in string s are replaced by string repl...
void substituteInplace(std::string &s, std::string_view toReplace, std::string_view replaceWith)
Replaces occurrences of substring toReplace in string s with string replaceWith.
std::string_view stripWhiteSpace(std::string_view s)
Given a string view s, returns a new, narrower view on that string, skipping over any leading or trai...
AliasInfo(const std::string &val, const std::string &sep=std::string())
Marker(size_t p, size_t n, size_t s)
A bunch of utility functions.