def test_parse_section(): assert parse_section('usage:', 'foo bar fizz buzz') == [] assert parse_section('usage:', 'usage: prog') == ['usage: prog'] assert parse_section('usage:', 'usage: -x\n -y') == ['usage: -x\n -y'] assert parse_section('usage:', usage) == [ 'usage: this', 'usage:hai', 'usage: this that', 'usage: foo\n bar', 'PROGRAM USAGE:\n foo\n bar', 'usage:\n\ttoo\n\ttar', 'Usage: eggs spam', 'usage: pit stop', ]
def test_parse_section(): assert parse_section("usage:", "foo bar fizz buzz") == [] assert parse_section("usage:", "usage: prog") == ["usage: prog"] assert parse_section("usage:", "usage: -x\n -y") == ["usage: -x\n -y"] assert parse_section("usage:", usage) == [ "usage: this", "usage:hai", "usage: this that", "usage: foo\n bar", "PROGRAM USAGE:\n foo\n bar", "usage:\n\ttoo\n\ttar", "Usage: eggs spam", "usage: pit stop", ]
def create_console(self, script): usage_sections = parse_section('usage:', script.__doc__) if len(usage_sections) == 0: raise DocoptLanguageError('"usage:" (case-insensitive) not found.') if len(usage_sections) > 1: raise DocoptLanguageError('More than one "usage:" (case-insensitive).') DocoptExit.usage = usage_sections[0] pattern = parse_pattern(formal_usage(DocoptExit.usage), parse_defaults(script.__doc__)) paths = [] paths.append({ "flags": [opt for opt in parse_defaults(script.__doc__) if not opt.argcount and opt.name not in ["--help", "--version"]], "extras": [opt for opt in parse_defaults(script.__doc__) if not opt.argcount and opt.name in ["--help", "--version"]], "options": [opt for opt in parse_defaults(script.__doc__) if opt.argcount and not opt.value], "default_options": [opt for opt in parse_defaults(script.__doc__) if opt.value], "arguments": [arg.name for arg in pattern.flat(Argument)], }) return { "name": script.__name__, "file": script.__file__, "doc": script.__doc__, "paths": paths, }
def test_formal_usage(): doc = """ Usage: prog [-hv] ARG prog N M prog is a program.""" usage, = parse_section('usage:', doc) assert usage == "Usage: prog [-hv] ARG\n prog N M" assert formal_usage(usage) == "( [-hv] ARG ) | ( N M )"
def parseDocoptOptions(usage): defaults = [] for s in docopt.parse_section('options:', usage): # FIXME corner case "bla: options: --foo" _, _, s = s.partition(':') # get rid of "options:" split = re.split('\n[ \t]*(-\S+?)', '\n' + s)[1:] split = [s1 + s2 for s1, s2 in zip(split[::2], split[1::2])] # Modified from docopt { #options = [Option.parse(s) for s in split if s.startswith('-')] #defaults += options for line in split: if not line.startswith('-'): continue option = docopt.Option.parse(line) option.description = extractOptionDescription(line) # Monkeypatch. defaults.append(option) # } End of modified from docopt. return defaults
else: args['<docopt>'] = sys.stdin.read() if args['--template'] is None: args['--template'] = os.path.join( os.path.dirname(os.path.realpath(__file__)), "template.c") template_h_path = re.sub(r'\.c$', '.h', args['--template']) with open(args['--template'], 'r') as f: args['--template'] = f.read() if args['--header']: with open(template_h_path, 'r') as f: template_h = f.read() except IOError as e: sys.exit(e) doc = args['<docopt>'] usage = docopt.parse_section('usage:', doc) s = ['More than one ', '"usage:" (case-insensitive)', ' not found.'] usage = {0: s[1:], 1: usage[0] if usage else None}.get(len(usage), s[:2]) if isinstance(usage, list): raise docopt.DocoptLanguageError(''.join(usage)) all_options = docopt.parse_defaults(doc) pattern = docopt.parse_pattern(docopt.formal_usage(usage), all_options) leafs, commands, arguments, flags, options = parse_leafs( pattern, all_options) t_commands = ';\n '.join('int %s' % c_name(cmd.name) for cmd in commands) t_commands = (('\n /* commands */\n ' + t_commands + ';') if t_commands != '' else '') t_arguments = ';\n '.join('char *%s' % c_name(arg.name)
with open(args["<docopt>"], "r") as f: args["<docopt>"] = f.read() elif args["<docopt>"] is None and sys.stdin.isatty(): print(__doc__.strip("\n")) sys.exit("") else: args["<docopt>"] = sys.stdin.read() if args["--template"] is None: args["--template"] = os.path.join(os.path.dirname(os.path.realpath(__file__)), "template.c") with open(args["--template"], "r") as f: args["--template"] = f.read() except IOError as e: sys.exit(e) doc = args["<docopt>"] usage = docopt.parse_section("usage:", doc) s = ["More than one ", '"usage:" (case-insensitive)', " not found."] usage = {0: s[1:], 1: usage[0] if usage else None}.get(len(usage), s[:2]) if isinstance(usage, list): raise docopt.DocoptLanguageError("".join(usage)) all_options = docopt.parse_defaults(doc) pattern = docopt.parse_pattern(docopt.formal_usage(usage), all_options) leafs, commands, arguments, flags, options = parse_leafs(pattern, all_options) t_commands = ";\n ".join("int %s" % c_name(cmd.name) for cmd in commands) t_commands = ("\n /* commands */\n " + t_commands + ";") if t_commands != "" else "" t_arguments = ";\n ".join("char *%s" % c_name(arg.name) for arg in arguments) t_arguments = ("\n /* arguments */\n " + t_arguments + ";") if t_arguments != "" else "" t_flags = ";\n ".join("int %s" % c_name(flag.long or flag.short) for flag in flags) t_flags = ("\n /* options without arguments */\n " + t_flags + ";") if t_flags != "" else ""
args['--output-name']='docoptout' if args['--templatec'] is None: args['--templatec'] = os.path.join( os.path.dirname(os.path.realpath(__file__)), "template.c") with open(args['--templatec'], 'r') as f: args['--templatec'] = f.read() if args['--templateh'] is None: args['--templateh'] = os.path.join( os.path.dirname(os.path.realpath(__file__)), "template.h") with open(args['--templateh'], 'r') as f: args['--templateh'] = f.read() except IOError as e: sys.exit(e) doc = args['<docopt>'] usage = docopt.parse_section('usage:', doc) s = ['More than one ', '"usage:" (case-insensitive)', ' not found.'] usage = {0: s[1:], 1: usage[0] if usage else None}.get(len(usage), s[:2]) if isinstance(usage, list): raise docopt.DocoptLanguageError(''.join(usage)) options = docopt.parse_defaults(doc) pattern = docopt.parse_pattern(docopt.formal_usage(usage), options) leafs, commands, arguments, flags, options = parse_leafs(pattern) t_commands = ';\n '.join('int %s' % c_name(cmd.name) for cmd in commands) t_commands = (('\n /* commands */\n ' + t_commands + ';') if t_commands != '' else '') t_arguments = ';\n '.join('char *%s' % c_name(arg.name) for arg in arguments)
args['<docopt>'] = f.read() elif args['<docopt>'] is None and sys.stdin.isatty(): print(__doc__.strip("\n")) sys.exit("") else: args['<docopt>'] = sys.stdin.read() if args['--module'] is None: args['--module'] = os.path.join( os.path.dirname(os.path.realpath(__file__)), "template.c") #with open(args['--module'], 'r') as f: # args['--module'] = f.read() except IOError as e: sys.exit(e) doc = args['<docopt>'] usage = docopt.parse_section('usage:', doc) s = ['More than one ', '"usage:" (case-insensitive)', ' not found.'] usage = {0: s[1:], 1: usage[0] if usage else None}.get(len(usage), s[:2]) if isinstance(usage, list): raise docopt.DocoptLanguageError(''.join(usage)) all_options = docopt.parse_defaults(doc) pattern = docopt.parse_pattern(docopt.formal_usage(usage), all_options) leafs, commands, arguments, flags, options = parse_leafs(pattern, all_options) t_commands = ';\n '.join('int %s' % c_name(cmd.name) for cmd in commands) t_commands = (('\n /* commands */\n ' + t_commands + ';') if t_commands != '' else '') t_arguments = ';\n '.join('char *%s' % c_name(arg.name) for arg in arguments)
def main(): assert __doc__ is not None args = docopt.docopt(__doc__) try: if args['<docopt>'] is not None: with open(args['<docopt>'], 'r') as f: args['<docopt>'] = f.read() elif args['<docopt>'] is None and sys.stdin.isatty(): print(__doc__.strip("\n")) sys.exit("") else: args['<docopt>'] = sys.stdin.read() if args['--template'] is None: args['--template'] = template_c else: with open(args['--template'], 'rt') as f: args['--template'] = f.read() if args['--template-header'] is None: args['--template-header'] = template_h else: with open(args['--template-header'], 'rt') as f: args['--template-header'] = f.read() except IOError as e: sys.exit(e) doc = args['<docopt>'] usage = docopt.parse_section('usage:', doc) error_str_l = 'More than one ', '"usage:" (case-insensitive)', ' not found.' usage = {0: error_str_l[1:], 1: usage[0] if usage else None}.get(len(usage), error_str_l[:2]) if isinstance(usage, list): raise docopt.DocoptLanguageError(''.join(usage)) all_options = docopt.parse_defaults(doc) pattern = docopt.parse_pattern(docopt.formal_usage(usage), all_options) leafs, commands, arguments, flags, options = parse_leafs(pattern, all_options) _indent = ' ' * 4 t_commands = ';\n{indent}'.format(indent=_indent).join('size_t {!s}'.format(c_name(cmd.name)) for cmd in commands) t_commands = '\n{indent}/* commands */\n{indent}{t_commands};'.format(indent=_indent, t_commands=t_commands) \ if t_commands != '' else '' t_arguments = ';\n{indent}'.join('char *{!s}'.format(c_name(arg.name)) for arg in arguments) t_arguments = '\n{indent}/* arguments */\n{indent}{t_arguments};'.format(indent=_indent, t_arguments=t_arguments) \ if t_arguments != '' else '' t_flags = ';\n{indent}'.format(indent=_indent).join('size_t {!s}'.format(c_name(flag.long or flag.short)) for flag in flags) t_flags = '\n{indent}/* options without arguments */\n{indent}{t_flags};'.format(indent=_indent, t_flags=t_flags) \ if t_flags != '' else '' t_options = ';\n{indent}'.format(indent=_indent).join('char *{!s}'.format(c_name(opt.long or opt.short)) for opt in options) t_options = '\n{indent}/* options with arguments */\n{indent}{t_options};'.format(indent=_indent, t_options=t_options) \ if t_options != '' else '' t_defaults = ', '.join(to_c(leaf.value) for leaf in leafs) t_defaults = re.sub(r'"(.*?)"', r'(char *) "\1"', t_defaults) t_defaults = '\n{indent}'.format(indent=_indent * 2).join(textwrap.wrap(t_defaults, 72)) t_defaults = '\n{indent}{t_defaults},'.format(indent=_indent * 2, t_defaults=t_defaults) if t_defaults != '' else '' t_elems_cmds = ',\n{indent}'.format(indent=_indent * 2).join(c_command(cmd) for cmd in commands) t_elems_cmds = '\n{indent}{t_elems_cmds}'.format(indent=_indent * 2, t_elems_cmds=t_elems_cmds) if t_elems_cmds != '' else '' t_elems_args = ',\n{indent}'.format(indent=_indent * 2).join(c_argument(arg) for arg in arguments) t_elems_args = '\n{indent}{t_elems_args}'.format(indent=_indent * 2, t_elems_args=t_elems_args) if t_elems_args != '' else '' t_elems_opts = ',\n{indent}'.format(indent=_indent * 2).join(c_option(o) for o in (flags + options)) t_elems_opts = '\n{indent}{t_elems_opts}'.format(indent=_indent * 2, t_elems_opts=t_elems_opts) if t_elems_opts != '' else '' ''' t_elems_n_commands = str(len(commands)) t_elems_n_arguments = str(len(arguments)) t_elems_n_options = str(len(flags + options)) t_elems_n_cmds = str(len(commands)) t_elems_n = ', '.join(str(len(l)) for l in (commands, arguments, (flags + options))) print( 't_elems_n_commands:', t_elems_n_commands, ';\n', 't_elems_n_arguments:', t_elems_n_arguments, ';\n', 't_elems_n_options:', t_elems_n_options, ';\n', 't_elems_n_cmds:', t_elems_n_cmds, ';\n', 't_elems_n:', t_elems_n, ';' ) ''' t_if_command = ' else '.join(c_if_command(command) for command in commands) t_if_command = '\n{indent}{t_if_command}'.format(indent=_indent * 2, t_if_command=t_if_command) if t_if_command != '' else '' t_if_argument = ' else '.join(c_if_argument(arg) for arg in arguments) t_if_argument = '\n{indent}{t_if_argument}'.format( indent=_indent * 2, t_if_argument='\n{indent}'.format(indent=_indent * 2).join(t_if_argument.splitlines()) ) if t_if_argument != '' else '' t_if_flag = ''.join('\n{indent}'.format(indent=_indent * 2).join(c_if_flag(flag).splitlines()) for flag in flags) t_if_option = ''.join( '\n{indent}'.format(indent=_indent * 2).join(c_if_option(opt).splitlines()) for opt in options ) if not args['--output-name']: header_output_name = '<stdout>' else: base, ext = os.path.splitext(args['--output-name']) if ext not in frozenset(('.h', '.c')): base = args['--output-name'] args['--output-name'] = "{base}.c".format(base=base) header_output_name = "{base}.h".format(base=base) header_name = os.path.basename(header_output_name) doc = doc.splitlines() doc_n = len(doc) template_out = Template(args['--template']).safe_substitute( help_message='\n{indent}'.format(indent=_indent).join(to_initializer(doc).splitlines()), help_message_n=doc_n, usage_pattern='\n{indent}'.format(indent=_indent * 2).join(to_c(usage).splitlines()), if_flag=t_if_flag, if_option=t_if_option, if_command=t_if_command, if_argument=t_if_argument, defaults=t_defaults, elems_cmds=null_if_zero(t_elems_cmds), elems_args=null_if_zero(t_elems_args), elems_opts=null_if_zero(t_elems_opts), t_elems_n_commands=str(len(commands)), t_elems_n_arguments=str(len(arguments)), t_elems_n_options=str(len(flags + options)), header_name=header_name ) template_header_out = Template(args['--template-header']).safe_substitute( commands=t_commands, arguments=t_arguments, flags=t_flags, options=t_options, help_message_n=doc_n, # nargs=t_nargs ).replace('$header_no_ext', os.path.splitext(header_name)[0].upper()) if args['--output-name'] is None: print(template_out.strip(), '\n') else: try: with open(sys.stdout if args['--output-name'] in (None, "<stdout>") else args['--output-name'], 'w') as f: f.write(template_out.strip() + '\n') with open(sys.stdout if header_output_name == "<stdout>" else header_output_name, 'w') as f: f.write(template_header_out.strip() + '\n') except IOError as e: sys.exit(str(e))