I'm trying to parse an argument string into an array of arguments. I have it mostly working, but it definitely seems like there'd be an easier way to go about doing this.
Rules:
- Quoted strings (
"some string"
) should be treated as a single argument, but the quotes should be removed from the resulting string - Any whitespace should separate arguments, except when we're already at the argCount (allowing the final argument to be unquoted, with all non-leading/trailing whitespace included)
- Quotes should be ignored in the final argument, being left in the string as-is, unless the quotes in question are surrounding the entire final argument.
Examples:
this is an arg string
with argCount 2 should result in['this', 'is an arg string']
"this is" an arg string
with argCount 2 should result in['this is', 'an arg string']
"this is" "an arg" string too
with argCount 3 should result in['this is', 'an arg', 'string too']
this\nis an arg\n string!
with argCount 3 should result in['this', 'is', 'an arg\n string!']
this\nis an arg string!
with argCount 2 should result in['this', 'is an arg string!']
this\nis an arg string\nwith multiple lines in the final arg.\n inner whitespace still here
with argCount 2 should result in['this', 'is an arg string\nwith multiple lines in the final arg.\n inner whitespace still here']
this is an arg " string with "quotes in the final" argument.
with argCount 2 should result in['this', 'is an arg " string with "quotes in the final" argument.']
"this is" "an arg string with nested "quotes" in the final arg. neat."
with argCount 2 should result in['this is', 'an arg string with nested "quotes" in the final arg. neat.']
My current code:
function parseArgs(argString, argCount) {
if(argCount) {
if(argCount < 2) throw new RangeError('argCount must be at least 2.');
const args = [];
const newlinesReplaced = argString.trim().replace(/\n/g, '{!~NL~!}');
const argv = stringArgv(newlinesReplaced);
if(argv.length > 0) {
for(let i = 0; i < argCount - 1; i++) args.push(argv.shift());
if(argv.length > 0) args.push(argv.join(' ').replace(/{!~NL~!}/g, '\n').replace(/\n{3,}/g, '\n\n'));
}
return args;
} else {
return stringArgv(argString);
}
}
I'm using the string-argv library, which is what stringArgv
is calling.
The four last examples do not work properly with my code, as the dummy newline replacement tokens cause the arguments to be smashed together during the stringArgv call - and quotes are taking complete priority.
Update:
I clarified the quotes rule, and added a rule about quotes also being left untouched in the final argument. Added two additional examples to go along with the new rule.