On Sunday, 19 June 2016 at 23:01:26 UTC, Adam D. Ruppe wrote:
On Sunday, 19 June 2016 at 15:36:08 UTC, Hugo wrote:
I thought the proper way to call GetCommandLineW was precisely
through CommandLineToArgvW, now I am lost.
Typically, yes, but you are saying you don't like what
CommandLineToArgvW does (it is responsible for handling quotes
and backslash escapes), so I'm saying you can do it some other
way.
GetCommandLineW will give you a raw string of what the user
typed. From there, you can treat it all as one argument or
split it up however you like.
One potentially simple option would be to preprocess it by
doing a .replace(`\"`, `\\"`) then pass to CommandLineToArgvW
to hack in the extra slash... or you could do a simple little
splitter yourself, something along the lines of:
---
bool inQuote;
size_t startIdx;
string[] args;
foreach(idx, ch; your_command_line) {
if(ch == '"')
inQuote = !inQuote;
else if(ch == ' ') {
if(!inQuote) {
args ~= to!string(your_command_line[startIdx .. idx];
startIdx = idx + 1;
}
}
}
if(startIdx != your_command_line.length)
args ~= to!string(your_command_line[startIdx .. $];
---
or something along those lines, I didn't actually test that.
(btw the to!string is optional, you could just leave them as
wstrings)
But the idea is to just split on space unless you are inside
quotes, doing nothing special on backslashes. That'd be what
you want (I think).
Thanks for the ideas, actually I was trying to do a function
similar to your splitter (but still having some problems with it):
void cleanArgs(in string cmdline, ref string[] args) {
uint argc = 0;
bool inQuotedMode = false;
bool lastCharIsBlank = false;
foreach(char c; cmdline) {
if(c == '"') inQuotedMode = !inQuotedMode;
if(inQuotedMode || (!inQuotedMode && c!=' ')) args[argc] ~= c;
if(!inQuotedMode && c==' ' && !lastCharIsBlank) {
argc++;
lastCharIsBlank = true;
}
}
}