Description
Not sure if I'm "doing it wrong", but I am having the same issue as reported in other languages, where Docopt does not treat quote delimited strings as one parameter.
As demonstrated here
Also reported in:
docopt/docopt#207
docopt/try.docopt.org#3
docopt/docopt.R#4
Until this is fixed I suggest putting a warning or removing examples like git commit
where it's typical for a command like git commit -m "To have multiple words inside a quote"
.
In the mean time I have created a workaround that isn't perfect but has so far worked okay for me. I pre-process and post-process the input/output.
The pre-process function replaces any quoted strings with a variable so that git commit -m "To have multiple words inside a quote"
becomes git commit -m $_v12345abcdef
.
function pre_processor(string $string) {
$variables = [];
$new_string = preg_replace_callback('/["\'](.*?(?<!\\\\))["\']/m', function($match) use (&$variables) {
// Results in a var name like 'v12345abcdef'
$varName = 'v' . hash('fnv164', $match[0]);
$variables[$varName] = $match[1];
// Results in a placeholder like $_v12345abcdef
return '$_' . $varName;
},$string);
return ['string' => $new_string, 'variables' => $variables];
}
The $new_string
is the passed to Docopt handler in place of the normal CLI input args. The result of which is then sent to a post processing function to fill the variables back in
function post_processor(array $args, array $variables) {
foreach ($args as &$arg){
// find any thing that matches like $_v12345abcdef and replace it with the actual value
$arg = preg_replace_callback('/\$_(v[a-f0-9]{16})\b/', function($match) use ($variables) {
return str_replace($match[0], isset($variables[$match[1]]) ? $variables[$match[1]] : $match[0], $match[0]);
}, $arg);
}
return $args;
}
For example, you might have something that looks like this:
function handle($string) {
list('string' => $processed_string, 'variables' => $variables) = pre_processor($string);
$result = $DOCOPT->handle($doc, $processed_string);
$real_args = post_processor($result->args, $variables);
return $real_args;
}
I haven't looked through the Docopt.php code, but this might be something that could be done as part of the existing handle() function.