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 re(R
"(^(\a[\w-]*)({[^}]*})?\s*=)");
72 assert(i!=std::string::npos);
74 aliasName = m[1].
str();
75 aliasValue = alias.substr(i);
81 size_t e = b + m[2].
length();
83 while (k<e-1 && isdigit(alias[k])) k++;
84 numParams = atoi(std::string{alias.substr(b+1,k-b-1)}.c_str());
90 while (s<e && isValidSeparator(alias[s])) s++;
93 err(
"Invalid alias '{}': invalid separator character '{:c}' (code {:d}), allowed characters: {}. Check your config file.\n",alias,alias[s],alias[s],separators);
98 separator=alias.substr(k,e-k-1);
104 aliasName,numParams,separator,aliasValue);
109 err(
"Invalid alias '{}': missing number of parameters. Check your config file.\n",alias);
121 err(
"Invalid alias '{}': invalid 'name=' or 'name{{...}}=' part. Check you config file.\n",alias);
135 auto it2 = it->second.find(numParams);
136 if (it2==it->second.end())
138 it->second.emplace(numParams,
AliasInfo(aliasValue,separator));
142 it2->second =
AliasInfo(aliasValue,separator);
165 for (
const auto &al : aliasList)
171 for (
auto &[numParams,aliasInfo] : overloads)
173 aliasInfo.value =
expandAlias(name+
":"+std::to_string(numParams),aliasInfo.value);
178 for (
auto &[numParams,aliasInfo] : overloads)
208 while (i < s.size() &&
isId(s[i])) ++i;
209 if (i < s.size() && s[i] ==
'{')
221 std::string_view aliasValue,std::string_view argList,
222 std::string_view sep)
228 size_t l=argList.length();
230 for (
size_t i=0;i<l;i++)
235 (i==0 || argList[i-1]!=
'\\') &&
236 argList.substr(i,sep.length())==sep)
238 args.push_back(argList.substr(p,i-p));
242 else if (c==
'@' || c==
'\\')
248 if (l>p) args.push_back(argList.substr(p));
252 std::vector<Marker> markerList;
253 l = aliasValue.length();
255 bool insideMarkerId =
false;
256 size_t markerStart = 0;
257 auto isDigit = [](
char c) {
return c>=
'0' && c<=
'9'; };
258 for (
size_t i=0;i<=l;i++)
260 char c = i<l ? aliasValue[i] :
'\0';
261 if (insideMarkerId && !isDigit(c))
263 insideMarkerId =
false;
264 size_t markerLen = i-markerStart;
265 markerList.emplace_back(markerStart-1,
266 static_cast<size_t>(std::stoi(std::string{aliasValue.substr(markerStart,markerLen)})),
269 if (c==
'\\' && (pc==
'@' || pc==
'\\'))
276 if (isDigit(c) && pc==
'\\')
288 for (
const Marker &m : markerList)
290 result+=aliasValue.substr(p,m.pos-p);
292 if (m.number>0 && m.number<=args.size())
300 result+=aliasValue.substr(p);
315 if (s.empty() || sep.empty())
return s;
317 result.reserve(s.length()+10);
318 size_t i, p=0, l=sep.length();
319 while ((i=s.find(sep,p))!=std::string::npos)
321 result += s.substr(p,i-p);
322 if (i>0 && s[i-1]!=
'\\')
326 result += s.substr(i,l);
329 result += s.substr(p);
337 static const reg::Ex re(R
"([\\@](\a[\w-]*))");
343 size_t i = match.position();
344 size_t l = match.length();
345 if (i>p) result+=s.substr(p,i-p);
348 bool hasArgs = !args.empty();
349 size_t argsLen = args.length();
350 std::string cmd = match[1].str();
351 int selectedNumArgs = -1;
357 size_t minusPos = cmd.find(
'-');
358 if (minusPos!=std::string::npos)
363 cmd = cmd.substr(0,minusPos);
378 for (
const auto &[numParams,aliasInfo] : it->second)
381 if (numParams==numArgs && numArgs>selectedNumArgs)
383 selectedNumArgs = numArgs;
386 if (selectedNumArgs==-1)
388 auto it2 = it->second.find(1);
389 if (it2 != it->second.end())
406 std::string qualifiedName = cmd+
":"+std::to_string(selectedNumArgs);
407 if ((allowRecursion || aliasesProcessed.find(qualifiedName)==aliasesProcessed.end()) &&
409 it->second.find(selectedNumArgs)!=it->second.end())
411 const auto &aliasInfo = it->second.find(selectedNumArgs)->second;
413 if (!allowRecursion) aliasesProcessed.insert(qualifiedName);
414 std::string val = aliasInfo.value;
423 if (!allowRecursion) aliasesProcessed.erase(qualifiedName);
425 if (hasArgs) p += argsLen+2;
430 result += match.str();
434 result += s.substr(p);
443 size_t l = args.length();
444 for (
size_t i=0;i<l;i++)
449 (i==0 || args[i-1]!=
'\\') &&
450 args.substr(i,sep.length())==sep)
454 else if (c==
'@' || c==
'\\')
468 if (!args.empty() && args[0]==
'{')
470 for (
size_t i=0;i<args.length();i++)
487 return std::string{args.substr(1,i-1)};
491 return std::string{};
504static std::string
expandAlias(std::string_view aliasName,std::string_view aliasValue)
509 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, fmt::format_string< Args... > fmt, Args &&... args)
Class representing a regular expression.
Object representing the matching results.
size_t size() const
Returns the number of sub matches available in this match.
size_t position() const
Returns the position of the match or std::string::npos if no position is set.
std::string str() const
Return a string representing the matching part.
size_t length() const
Returns the position of the match or std::string::npos if no length is set.
#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.
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.
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.