From a34233f106bfcc3248bd5ed89a63836e45814bda Mon Sep 17 00:00:00 2001 From: Fabio Erculiani Date: Thu, 20 Oct 2011 18:39:04 +0200 Subject: [PATCH] [eit.commands.help] rewrite ColorfulFormatter, drop side effects completely --- server/eit/colorful.py | 82 +++++++++++++++++++++++++++---------- server/eit/commands/help.py | 15 +++---- 2 files changed, 66 insertions(+), 31 deletions(-) diff --git a/server/eit/colorful.py b/server/eit/colorful.py index ee1652e0f..a18b8cea4 100644 --- a/server/eit/colorful.py +++ b/server/eit/colorful.py @@ -8,38 +8,76 @@ B{Entropy Infrastructure Toolkit}. -NOTE: this colorful stuff introduces some unwanted effects. -But it's better than living in a black/white world. """ import sys import argparse import textwrap as _textwrap -from entropy.output import decolorize +from entropy.output import decolorize, purple, teal, darkgreen -class ColorfulFormatter(argparse.RawDescriptionHelpFormatter): +class ColorfulFormatter(argparse.RawTextHelpFormatter): """ This is just a whacky HelpFormatter flavour to add some coloring. """ - def _split_lines(self, text, width): - text = self._whitespace_matcher.sub(' ', text).strip() - width_span = len(text) - len(decolorize(text)) - return _textwrap.wrap(text, width + width_span) + def __colors(self, tup_str, orig_str): + pre_spaces = len(tup_str) - len(tup_str.lstrip()) + post_spaces = len(tup_str) - len(tup_str.rstrip()) + return " "*pre_spaces + orig_str.strip() \ + + " "*post_spaces -if sys.hexversion >= 0x3000000: - str_class = str -else: - str_class = unicode -class ColorfulStr(str_class): - """ - This String object has been introduced to fake - argparse width calculations and allow colorful - help. - """ - def __new__(cls, seq): - return str_class.__new__(cls, seq) + def _format_action(self, action): + # determine the required width and the entry label + help_position = min(self._action_max_length + 2, + self._max_help_position) + help_width = self._width - help_position + action_width = help_position - self._current_indent - 2 + orig_action_header = self._format_action_invocation(action) + action_header = decolorize(orig_action_header) - def __len__(self): - return len(decolorize(self)) + # ho nelp; start on same line and add a final newline + if not action.help: + tup = self._current_indent, '', action_header + action_header = '%*s%s\n' % tup + + # short action name; start on the same line and pad two spaces + elif len(action_header) <= action_width: + tup = self._current_indent, '', action_width, action_header + tup_str = '%*s%-*s ' % tup + action_header = self.__colors(tup_str, orig_action_header) + indent_first = 0 + + # long action name; start on the next line + else: + tup = self._current_indent, '', action_header + tup_str = '%*s%-*s ' % tup + action_header = self.__colors(tup_str, orig_action_header) + indent_first = help_position + + # collect the pieces of the action help + parts = [action_header] + + # if there was help for the action, add lines of help text + if action.help: + orig_help_text = self._expand_help(action) + help_text = decolorize(orig_help_text) + help_lines = self._split_lines(help_text, help_width) + orig_help_lines = self._split_lines(orig_help_text, help_width) + tup_str = '%*s%s' % (indent_first, '', help_lines[0]) + parts.append(self.__colors(tup_str, orig_help_lines[0]) + "\n") + for idx, line in enumerate(help_lines[1:]): + tup_str = '%*s%s' % (help_position, '', line) + parts.append( + self.__colors(tup_str, orig_help_lines[idx+1]) + "\n") + + # or add a newline if the description doesn't end with one + elif not action_header.endswith('\n'): + parts.append('\n') + + # if there are any sub-actions, add their help as well + for subaction in self._iter_indented_subactions(action): + parts.append(self._format_action(subaction)) + + # return a single string + return self._join_parts(parts) diff --git a/server/eit/commands/help.py b/server/eit/commands/help.py index bbf9fc3c2..86e94632c 100644 --- a/server/eit/commands/help.py +++ b/server/eit/commands/help.py @@ -12,9 +12,9 @@ import argparse from entropy.i18n import _ -from entropy.output import purple, teal, darkgreen +from entropy.output import teal, purple, darkgreen -from eit.colorful import ColorfulFormatter, ColorfulStr +from eit.colorful import ColorfulFormatter from eit.commands.descriptor import EitCommandDescriptor from eit.commands.command import EitCommand @@ -44,16 +44,13 @@ class EitHelp(EitCommand): group = parser.add_argument_group("command", "available commands") for descriptor in descriptors: aliases = descriptor.get_class().ALIASES - aliases_str = ", ".join( - [teal(x) for x in aliases]) + aliases_str = ", ".join([teal(x) for x in aliases]) if aliases_str: aliases_str = " [%s]" % (aliases_str,) - name = u"%s%s" % (purple(descriptor.get_name()), + name = "%s%s" % (purple(descriptor.get_name()), aliases_str) - desc = darkgreen(descriptor.get_description()) - group.add_argument(ColorfulStr(name), - help=ColorfulStr(desc), - action="store_true") + desc = descriptor.get_description() + group.add_argument(name, help=darkgreen(desc), action="store_true") parser.print_help() if not self._args: return 1