20#include <unordered_map>
34 AliasInfo(
const std::string &val,
const std::string &sep=std::string())
41using AliasInfoMap = std::unordered_map<std::string,AliasOverloads>;
46 std::string_view s,
bool allowRecursion=
false);
49static std::string
expandAlias(std::string_view aliasName,std::string_view aliasValue);
60 std::string aliasName;
61 std::string aliasValue;
63 std::string separator;
65 static std::string_view separators =
"!#$%&,.?|;:'+=~`/";
66 auto isValidSeparator = [](
char c) ->
bool {
return separators.find(c)!=std::string::npos; };
68 static const reg::Ex re(R
"(^(\a[\w-]*)({[^}]*})?\s*=)");
73 ASSERT(i!=std::string::npos);
75 aliasName = m[1].
str();
76 aliasValue = alias.substr(i);
82 size_t e = b + m[2].
length();
84 while (k<e-1 && isdigit(alias[k])) k++;
85 numParams = atoi(std::string{alias.substr(b+1,k-b-1)}.c_str());
91 while (s<e && isValidSeparator(alias[s])) s++;
94 err(
"Invalid alias '{}': invalid separator character '{:c}' (code {:d}), allowed characters: {}. Check your config file.\n",alias,alias[s],alias[s],separators);
99 separator=alias.substr(k,e-k-1);
105 aliasName,numParams,separator,aliasValue);
110 err(
"Invalid alias '{}': missing number of parameters. Check your config file.\n",alias);
122 err(
"Invalid alias '{}': invalid 'name=' or 'name{{...}}=' part. Check you config file.\n",alias);
136 auto it2 = it->second.find(numParams);
137 if (it2==it->second.end())
139 it->second.emplace(numParams,
AliasInfo(aliasValue,separator));
143 it2->second =
AliasInfo(aliasValue,separator);
166 for (
const auto &al : aliases)
172 for (
auto &[numParams,aliasInfo] : overloads)
174 aliasInfo.value =
expandAlias(name+
":"+std::to_string(numParams),aliasInfo.value);
179 for (
auto &[numParams,aliasInfo] : overloads)
209 while (i < s.size() &&
isId(s[i])) ++i;
210 if (i < s.size() && s[i] ==
'{')
222 std::string_view aliasValue,std::string_view argList,
223 std::string_view sep)
229 size_t l=argList.length();
231 for (
size_t i=0;i<l;i++)
236 (i==0 || argList[i-1]!=
'\\') &&
237 argList.substr(i,sep.length())==sep)
239 args.push_back(argList.substr(p,i-p));
243 else if (c==
'@' || c==
'\\')
249 if (l>p) args.push_back(argList.substr(p));
253 std::vector<Marker> markerList;
254 l = aliasValue.length();
256 bool insideMarkerId =
false;
257 size_t markerStart = 0;
258 auto isDigit = [](
char c) {
return c>=
'0' && c<=
'9'; };
259 for (
size_t i=0;i<=l;i++)
261 char c = i<l ? aliasValue[i] :
'\0';
262 if (insideMarkerId && !isDigit(c))
264 insideMarkerId =
false;
265 size_t markerLen = i-markerStart;
266 markerList.emplace_back(markerStart-1,
267 static_cast<size_t>(std::stoi(std::string{aliasValue.substr(markerStart,markerLen)})),
270 if (c==
'\\' && (pc==
'@' || pc==
'\\'))
277 if (isDigit(c) && pc==
'\\')
289 for (
const Marker &m : markerList)
291 result+=aliasValue.substr(p,m.pos-p);
293 if (m.number>0 && m.number<=args.size())
301 result+=aliasValue.substr(p);
316 if (s.empty() || sep.empty())
return s;
318 result.reserve(s.length()+10);
319 size_t i, p=0, l=sep.length();
320 while ((i=s.find(sep,p))!=std::string::npos)
322 result += s.substr(p,i-p);
323 if (i>0 && s[i-1]!=
'\\')
327 result += s.substr(i,l);
330 result += s.substr(p);
338 static const reg::Ex re(R
"([\\@](\a[\w-]*))");
344 size_t i = match.position();
345 size_t l = match.length();
346 if (i>p) result+=s.substr(p,i-p);
349 bool hasArgs = !args.empty();
350 size_t argsLen = args.length();
351 std::string cmd = match[1].str();
352 int selectedNumArgs = -1;
358 size_t minusPos = cmd.find(
'-');
359 if (minusPos!=std::string::npos)
364 cmd = cmd.substr(0,minusPos);
379 for (
const auto &[numParams,aliasInfo] : it->second)
382 if (numParams==numArgs && numArgs>selectedNumArgs)
384 selectedNumArgs = numArgs;
387 if (selectedNumArgs==-1)
389 auto it2 = it->second.find(1);
390 if (it2 != it->second.end())
407 std::string qualifiedName = cmd+
":"+std::to_string(selectedNumArgs);
408 if ((allowRecursion || aliasesProcessed.find(qualifiedName)==aliasesProcessed.end()) &&
410 it->second.find(selectedNumArgs)!=it->second.end())
412 const auto &aliasInfo = it->second.find(selectedNumArgs)->second;
414 if (!allowRecursion) aliasesProcessed.insert(qualifiedName);
415 std::string val = aliasInfo.value;
424 if (!allowRecursion) aliasesProcessed.erase(qualifiedName);
426 if (hasArgs) p += argsLen+2;
431 result += match.str();
435 result += s.substr(p);
444 size_t l = args.length();
445 for (
size_t i=0;i<l;i++)
450 (i==0 || args[i-1]!=
'\\') &&
451 args.substr(i,sep.length())==sep)
455 else if (c==
'@' || c==
'\\')
469 if (!args.empty() && args[0]==
'{')
471 for (
size_t i=0;i<args.length();i++)
488 return std::string{args.substr(1,i-1)};
492 return std::string{};
505static std::string
expandAlias(std::string_view aliasName,std::string_view aliasValue)
510 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 void addValidAliasToMap(std::string_view alias)
static std::string expandAliasRec(StringUnorderedSet &aliasesProcessed, std::string_view s, bool allowRecursion=false)
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 isId(char c)
Returns true if c is a valid character for an identifier.
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.