def parse_usage(text): """ Parse a usage message by inferring its structure (and making some assumptions :-). :param text: The usage message to parse (a string). :returns: A tuple of two lists: 1. A list of strings with the paragraphs of the usage message's "introduction" (the paragraphs before the documentation of the supported command line options). 2. A list of strings with pairs of command line options and their descriptions: Item zero is a line listing a supported command line option, item one is the description of that command line option, item two is a line listing another supported command line option, etc. Usage messages in general are free format of course, however :func:`parse_usage()` assume a certain structure from usage messages in order to successfully parse them: - The usage message starts with a line ``Usage: ...`` that shows a symbolic representation of the way the program is to be invoked. - After some free form text a line ``Supported options:`` precedes the documentation of the supported command line options. - The command line options are documented as follows:: -v, --verbose Make more noise. So all of the variants of the command line option are shown together on a separate line, followed by one or more paragraphs describing the option. - There are several other minor assumptions, but to be honest I'm not sure if anyone other than me is ever going to use this functionality, so for now I won't list every intricate detail :-). If you're curious anyway, refer to the usage message of the `humanfriendly` package (defined in the :mod:`humanfriendly.cli` module) and compare it with the usage message you see when you run ``humanfriendly --help`` and the generated usage message embedded in the readme. Feel free to request more detailed documentation if you're interested in using the :mod:`humanfriendly.usage` module outside of the little ecosystem of Python packages that I have been building over the past years. """ # Split the raw usage message on lines that introduce a new command line option. chunks = [dedent(c) for c in re.split(OPTION_PATTERN, text) if c and not c.isspace()] # Split the introduction (the text before any options) into one or more paragraphs. introduction = [join_lines(p) for p in split_paragraphs(chunks.pop(0))] # Should someone need to easily debug the parsing performed here. logger.debug("Parsed introduction: %s", introduction) logger.debug("Parsed options: %s", chunks) return introduction, chunks
def parse_usage(text): """ Parse a usage message by inferring its structure (and making some assumptions :-). :param text: The usage message to parse (a string). :returns: A tuple of two lists: 1. A list of strings with the paragraphs of the usage message's "introduction" (the paragraphs before the documentation of the supported command line options). 2. A list of strings with pairs of command line options and their descriptions: Item zero is a line listing a supported command line option, item one is the description of that command line option, item two is a line listing another supported command line option, etc. Usage messages in general are free format of course, however :func:`parse_usage()` assume a certain structure from usage messages in order to successfully parse them: - The usage message starts with a line ``Usage: ...`` that shows a symbolic representation of the way the program is to be invoked. - After some free form text a line ``Supported options:`` (surrounded by empty lines) precedes the documentation of the supported command line options. - The command line options are documented as follows:: -v, --verbose Make more noise. So all of the variants of the command line option are shown together on a separate line, followed by one or more paragraphs describing the option. - There are several other minor assumptions, but to be honest I'm not sure if anyone other than me is ever going to use this functionality, so for now I won't list every intricate detail :-). If you're curious anyway, refer to the usage message of the `humanfriendly` package (defined in the :mod:`humanfriendly.cli` module) and compare it with the usage message you see when you run ``humanfriendly --help`` and the generated usage message embedded in the readme. Feel free to request more detailed documentation if you're interested in using the :mod:`humanfriendly.usage` module outside of the little ecosystem of Python packages that I have been building over the past years. """ introduction = [] documented_options = [] # Split the raw usage message into paragraphs. paragraphs = split_paragraphs(text) # Get the paragraphs that are part of the introduction. while paragraphs: # Check whether we've found the end of the introduction. end_of_intro = (paragraphs[0] == START_OF_OPTIONS_MARKER) # Append the current paragraph to the introduction. introduction.append(join_lines(paragraphs.pop(0))) # Stop after we've processed the complete introduction. if end_of_intro: break logger.debug("Parsed introduction: %s", introduction) # Parse the paragraphs that document command line options. while paragraphs: documented_options.append(dedent(paragraphs.pop(0))) description = [] while paragraphs: # Check if the next paragraph starts the documentation of another # command line option. if all(OPTION_PATTERN.match(t) for t in split(paragraphs[0])): break else: description.append(paragraphs.pop(0)) # Join the description's paragraphs back together so we can remove # common leading indentation. documented_options.append(dedent('\n\n'.join(description))) logger.debug("Parsed options: %s", documented_options) return introduction, documented_options