From 2f9550860ae4e5138d7e8150a21c6d73401dce53 Mon Sep 17 00:00:00 2001 From: Tony Duckles Date: Sat, 28 Jan 2012 00:00:05 -0500 Subject: [PATCH] Improve optparse formatting --- svn2svn/__init__.py | 2 +- svn2svn/run/parse.py | 63 ++++++++++++++++++++++++++++++++++++++++++ svn2svn/run/svn2svn.py | 21 +++++--------- 3 files changed, 71 insertions(+), 15 deletions(-) create mode 100644 svn2svn/run/parse.py diff --git a/svn2svn/__init__.py b/svn2svn/__init__.py index 95872bd..2d3f101 100644 --- a/svn2svn/__init__.py +++ b/svn2svn/__init__.py @@ -2,7 +2,7 @@ __all__ = [] __author__ = 'Tony Duckles' __license__ = 'GNU General Public License (version 3 or later)' -__versioninfo__ = (1, 0, 0) +__versioninfo__ = (1, 1, 0) base_version = '.'.join(map(str, __versioninfo__)) full_version = base_version diff --git a/svn2svn/run/parse.py b/svn2svn/run/parse.py new file mode 100644 index 0000000..0dabdb7 --- /dev/null +++ b/svn2svn/run/parse.py @@ -0,0 +1,63 @@ +""" optparser helper functions """ + +import optparse +import textwrap + +class HelpFormatter(optparse.IndentedHelpFormatter): + """ + Modified version of certain optparse.IndentedHelpFormatter methods: + * Respect line-breaks in parser.desription and option.help_text + * Vertically-align long_opts + Inspired by: http://groups.google.com/group/comp.lang.python/browse_thread/thread/6df6e6b541a15bc2/09f28e26af0699b1?pli=1 + """ + def format_description(self, description): + if not description: return "" + desc_width = self.width - self.current_indent + indent = " "*self.current_indent + bits = description.split('\n') + formatted_bits = [ + textwrap.fill(bit, + desc_width, + initial_indent=indent, + subsequent_indent=indent) + for bit in bits] + result = "\n".join(formatted_bits) + "\n" + return result + + def format_option_strings(self, option): + """Return a comma-separated list of option strings & metavariables.""" + if option.takes_value(): + metavar = option.metavar or option.dest.upper() + short_opts = [("%s" % (sopt)) if option._long_opts else \ + (self._short_opt_fmt % (sopt, metavar)) + for sopt in option._short_opts] + long_opts = [self._long_opt_fmt % (lopt, metavar) + for lopt in option._long_opts] + else: + short_opts = option._short_opts + long_opts = option._long_opts + + return (" " if not short_opts else "")+(", ".join(short_opts + long_opts)) + + def format_option(self, option): + result = [] + opts = self.option_strings[option] + opt_width = self.help_position - self.current_indent - 2 + if len(opts) > opt_width: + opts = "%*s%s\n" % (self.current_indent, "", opts) + indent_first = self.help_position + else: # start help on same line as opts + opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts) + indent_first = 0 + result.append(opts) + if option.help: + help_text = self.expand_default(option) + help_lines = [] + for para in help_text.split("\n"): + help_lines.extend(textwrap.wrap(para, self.help_width)) + result.append("%*s%s\n" % (indent_first, "", help_lines[0])) + result.extend(["%*s%s\n" % (self.help_position, "", line) + for line in help_lines[1:]]) + elif opts[-1] != "\n": + result.append("\n") + return "".join(result) diff --git a/svn2svn/run/svn2svn.py b/svn2svn/run/svn2svn.py index c4e6077..13041c7 100644 --- a/svn2svn/run/svn2svn.py +++ b/svn2svn/run/svn2svn.py @@ -21,6 +21,7 @@ from .. import ui from .. import svnclient from ..shell import run_svn from ..errors import (ExternalCommandFailed, UnsupportedSVNAction, InternalError, VerificationError) +from parse import HelpFormatter import sys import os @@ -28,7 +29,7 @@ import time import traceback import shutil import operator -from optparse import OptionParser,OptionGroup +import optparse from datetime import datetime _valid_svn_actions = "MARD" # The list of known SVN action abbr's, from "svn log" @@ -590,15 +591,6 @@ def disp_svn_log_summary(log_entry): ui.status(log_entry['message']) ui.status("------------------------------------------------------------------------") -def display_parser_error(parser, message): - """ - Display an options error, and terminate. - """ - print "error:", message - print - parser.print_help() - sys.exit(1) - def real_main(options, args): source_url = args.pop(0).rstrip("/") target_url = args.pop(0).rstrip("/") @@ -756,8 +748,8 @@ def real_main(options, args): def main(): # Defined as entry point. Must be callable without arguments. - usage = """Usage: %prog [OPTIONS] source_url target_url - + usage = "Usage: %prog [OPTIONS] source_url target_url" + description = """\ Replicate (replay) history from one SVN repository to another. Maintain logical ancestry wherever possible, so that 'svn log' on the replayed repo will correctly follow file/folder renames. @@ -784,7 +776,8 @@ def main(): the last replayed revision to file:///svn/target/trunk (based on the svn2svn:* revprops) will be replayed to _wc_target, maintaining all logical ancestry where possible.""" - parser = OptionParser(usage, version="%prog "+str(full_version)) + parser = optparse.OptionParser(usage, description=description, + formatter=HelpFormatter(), version="%prog "+str(full_version)) #parser.remove_option("--help") #parser.add_option("-h", "--help", dest="show_help", action="store_true", # help="show this help message and exit") @@ -805,7 +798,7 @@ def main(): help="enable debugging output (same as -vvv)") options, args = parser.parse_args() if len(args) != 2: - display_parser_error(parser, "incorrect number of arguments") + parser.error("incorrect number of arguments") if options.verbosity < 10: # Expand multiple "-v" arguments to a real ui._level value options.verbosity *= 10 -- 2.45.2