You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Just dump the current state... Well, and also quote args with spaces... and other scary chars...
Umm... Except map doesn't preserve order, so we're fucked with the named ones!... :-o (And no, ordered_map doesn't mean the order of insertion either!... :-/ )
Ummmm... And even if some rudimentary quoting is kinda easy, there's still the open-ended problem of command-lines being consumed by shells, so such a generator must actually speak the (quoting-globbing-escaping) language of a certain particular target shell that it prepares the command-line to!... A hard NO to that!
Mmm, but actually... ;) OK, well, just that some generic features which are mostly OK for most shells, or are a good baseline for further custom app-level processing, would still be nice. (A quoting example is done below, and some escaping callback lambda could also be added, too.)
-> Also, wtime does something similar, and it's super handy. See its impl. -- with escaping for Win32::CreateProcess -- below, in another comment!
Also, BTW, the escaping function can be a callback!
...at the cost of adding <functional> to the comp. burden! :-/
And then listvals() (already there in the tests) could be added, too, reusing the same mechanics. The tests use a stream as an output:
auto listvals(auto const& container, const char* tail = "\n", const char* sep = ", ")
{
for (auto v = container.begin(); v != container.end(); ++v)
cout << (v == container.begin() ? "":sep)
<< *v
<< (v+1 == container.end() ? tail:"");
}
but it could just as well write to a string (and an improved one could even be nice and precalc. its length first -- and an even nicer one that also does auto-quoting, or an even nicer one that does that with multi-char quotes... :) ):
#include <string>
#include <string_view>
#include <cstring>
#include <cassert>
#define FOUND(expr) ((expr) != std::string::npos)
#define CONTAINS(str, chars) FOUND((str).find_first_of(chars))
string listvals(auto const& container, const char prewrap[] = "", const char postwrap[] = "", const char sep[] = ", ",
const char* quote = "\"", // not const char[], to hint that it accepts nullptr!
const char* scary_chars = " \t\n")
// The pre/post wrapping are optional parts that only get written if not empty,
// to support cases where callers would otherwise have to add an annoying
// `if (container.empty())` or two themselves.
{
string result;
if (!container.empty()) {
size_t QLEN = quote ? strlen(quote) : 0;
// Precalc. size... (Note: we're processing cmd args. We got time.)
size_t size = strlen(prewrap) + (container.size() - 1) * strlen(sep) + strlen(postwrap);
for (auto& v : container)
size += v.length()
+ (quote && *quote && CONTAINS(v, scary_chars) ? // add quotes...
(QLEN>1 ? QLEN:2) : 0); // special case for 1 (-> pair)!
result.reserve(size);
// Write...
result += prewrap;
for (auto v = container.begin(); v != container.end(); ++v) {
if (quote && *quote && CONTAINS(*v, scary_chars))
{ result += string_view(quote, quote + (QLEN/2 ? QLEN/2 : 1)); // special case for 1 quote!
result += *v;
result += string_view(quote + QLEN/2); }
else { result += *v; }
result += (v+1 == container.end() ? postwrap : sep);
}
//cout << "\n\n["<<result<<"]: " << "result.length() =? size: " << dec << result.length() << " vs. " << size << "\n\n";
assert(result.length() == size);
}
return result;
}
#undef FOUND
#undef CONTAINS
...then the args "serializer" could be as simple as (well, but still needs to write to a string, as the other!):
xparq
changed the title
Perhaps another nice utility to also generate cmdlines, not just consume
Perhaps another nice utility to also generate (not just consume) cmdlines
Nov 5, 2023
Just dump the current state... Well, and also quote args with spaces... and other scary chars...
map
doesn't preserve order, so we're fucked with the named ones!... :-o (And no,ordered_map
doesn't mean the order of insertion either!... :-/ )(A quoting example is done below, and some escaping callback lambda could also be added, too.)
-> Also, wtime does something similar, and it's super handy. See its impl. -- with escaping for
Win32::CreateProcess
-- below, in another comment!<functional>
to the comp. burden! :-/And then
listvals()
(already there in the tests) could be added, too, reusing the same mechanics. The tests use a stream as an output:but it could just as well write to a string (and an improved one could even be nice and precalc. its length first -- and an even nicer one that also does auto-quoting, or an even nicer one that does that with multi-char quotes... :) ):
...then the args "serializer" could be as simple as (well, but still needs to write to a string, as the other!):
Could be extra useful if the named/positional accessors would drop their (pretty orthodox)
const
(Drop const from named() and positional() (or have it both ways?) #55)! Then you could manipulate the arg set, and then "render" it to a new command line!The text was updated successfully, but these errors were encountered: