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;
    }
  }
}

Reply via email to