Browse Source

More porting

master
J. King 2 years ago
parent
commit
b3602a8e98
  1. 68
      lib/Docopt.php

68
lib/Docopt.php

@ -38,32 +38,33 @@ class Docopt {
* --options, <positional-argument>, commands, which could be * --options, <positional-argument>, commands, which could be
* [optional], (required), (mutually | exclusive) or repeated... * [optional], (required), (mutually | exclusive) or repeated...
* *
* Example * Example:
* -------
* *
* > use MensBeam\Docopt\Docopt; * ```
* > $doc = <<<DOCSTRING * use MensBeam\Docopt\Docopt;
* <<< Usage: * $doc = <<<DOCSTRING
* <<< my_program tcp <host> <port> [--timeout=<seconds>] * Usage:
* <<< my_program serial <port> [--baud=<n>] [--timeout=<seconds>] * my_program tcp <host> <port> [--timeout=<seconds>]
* <<< my_program (-h | --help | --version) * my_program serial <port> [--baud=<n>] [--timeout=<seconds>]
* <<< * my_program (-h | --help | --version)
* <<< Options: *
* <<< -h, --help Show this screen and exit. * Options:
* <<< --baud=<n> Baudrate [default: 9600] * -h, --help Show this screen and exit.
* <<< DOCSTRING; * --baud=<n> Baudrate [default: 9600]
* > $argv = ['tcp', '127.0.0.1', '80', '--timeout', '30']; * DOCSTRING;
* > echo json_encode(Docopt::docopt($doc, $argv), \JSON_PRETTY_PRINT); * $argv = ['tcp', '127.0.0.1', '80', '--timeout', '30'];
* { * echo json_encode(Docopt::docopt($doc, $argv), \JSON_PRETTY_PRINT);
* "--baud": "9600", * //{
* "--help": false, * // "--baud": "9600",
* "--timeout": "30", * // "--help": false,
* "--version": false, * // "--timeout": "30",
* "<host>": "127.0.0.1", * // "--version": false,
* "<port>": "80", * // "<host>": "127.0.0.1",
* "serial": false, * // "<port>": "80",
* "tcp": true * // "serial": false,
* } * // "tcp": true
* //}
* ```
* *
* @param string $docstring Description of your command-line interface * @param string $docstring Description of your command-line interface
* @param string[]|string|null $argv Argument list to be parsed. $_SERVER['argv'] is used if null is provided * @param string[]|string|null $argv Argument list to be parsed. $_SERVER['argv'] is used if null is provided
@ -81,6 +82,7 @@ class Docopt {
bool $more_magic = false bool $more_magic = false
): ParsedOptions { ): ParsedOptions {
# argv = sys.argv[1:] if argv is None else argv # argv = sys.argv[1:] if argv is None else argv
$argv = $argv ?? array_slice($_SERVER['argv'] ?? [], 1);
# maybe_frame = inspect.currentframe() # maybe_frame = inspect.currentframe()
# if maybe_frame: # if maybe_frame:
# parent_frame = doc_parent_frame = magic_parent_frame = maybe_frame.f_back # parent_frame = doc_parent_frame = magic_parent_frame = maybe_frame.f_back
@ -91,6 +93,8 @@ class Docopt {
# more_magic = True # more_magic = True
# else: # else:
# magic_parent_frame = magic_parent_frame.f_back # magic_parent_frame = magic_parent_frame.f_back
// DEVIATION: All these lines are to do with automatic invocation of the "magic" variant of docopt()
// We cannot do this in PHP
# if not docstring: # go look for one, if none exists, raise Exception # if not docstring: # go look for one, if none exists, raise Exception
# while not docstring and doc_parent_frame: # while not docstring and doc_parent_frame:
# docstring = doc_parent_frame.f_locals.get("__doc__") # docstring = doc_parent_frame.f_locals.get("__doc__")
@ -98,6 +102,7 @@ class Docopt {
# doc_parent_frame = doc_parent_frame.f_back # doc_parent_frame = doc_parent_frame.f_back
# if not docstring: # if not docstring:
# raise DocoptLanguageError("Either __doc__ must be defined in the scope of a parent or passed as the first argument.") # raise DocoptLanguageError("Either __doc__ must be defined in the scope of a parent or passed as the first argument.")
// DEVIATION: All these lines look for a docstring in the parent context. We simply require one as input
# output_value_assigned = False # output_value_assigned = False
# if more_magic and parent_frame: # if more_magic and parent_frame:
# import dis # import dis
@ -110,14 +115,27 @@ class Docopt {
# MAYBE_STORE = next(instrs) # MAYBE_STORE = next(instrs)
# if MAYBE_STORE and (MAYBE_STORE.opname.startswith("STORE") or MAYBE_STORE.opname.startswith("RETURN")): # if MAYBE_STORE and (MAYBE_STORE.opname.startswith("STORE") or MAYBE_STORE.opname.startswith("RETURN")):
# output_value_assigned = True # output_value_assigned = True
// DEVIATION: This is all for magic which is not possible in PHP
# usage_sections = parse_section("usage:", docstring) # usage_sections = parse_section("usage:", docstring)
# if len(usage_sections) == 0: # if len(usage_sections) == 0:
# raise DocoptLanguageError('"usage:" section (case-insensitive) not found. Perhaps missing indentation?') # raise DocoptLanguageError('"usage:" section (case-insensitive) not found. Perhaps missing indentation?')
# if len(usage_sections) > 1: # if len(usage_sections) > 1:
# raise DocoptLanguageError('More than one "usage:" (case-insensitive).') # raise DocoptLanguageError('More than one "usage:" (case-insensitive).')
$usage_sections = Util::parse_section("usage:", $docstring);
if (sizeof($usage_sections) === 0) {
throw new DocoptLanguageError('"usage:" section (case-insensitive) not found. Perhaps missing indentation?');
}
if (sizeof($usage_sections) > 1) {
throw new DocoptLanguageError('More than one "usage:" (case-insensitive).');
}
# options_pattern = re.compile(r"\n\s*?options:", re.IGNORECASE) # options_pattern = re.compile(r"\n\s*?options:", re.IGNORECASE)
# if options_pattern.search(usage_sections[0]): # if options_pattern.search(usage_sections[0]):
# raise DocoptExit("Warning: options (case-insensitive) was found in usage." "Use a blank line between each section..") # raise DocoptExit("Warning: options (case-insensitive) was found in usage." "Use a blank line between each section..")
$options_pattern = '/\n\s*?options:/si';
if (preg_match($options_pattern, $usage_sections[0])) {
throw new DocoptExit("Warning: options (case-insensitive) was found in usage."."Use a blank line between each section..");
}
# DocoptExit.usage = usage_sections[0] # DocoptExit.usage = usage_sections[0]
# options = parse_defaults(docstring) # options = parse_defaults(docstring)
# pattern = parse_pattern(formal_usage(DocoptExit.usage), options) # pattern = parse_pattern(formal_usage(DocoptExit.usage), options)

Loading…
Cancel
Save