summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2021-08-06 18:29:46 +0000
committerGerrit Code Review <review@openstack.org>2021-08-06 18:29:46 +0000
commit734bc0c5da6915f10823a3124e08ba3ddbd4cc63 (patch)
tree155d9d73126d263f4c88223888a7a0684faf3eab
parent865ab44713db03deb8147925801c33a14eba16e3 (diff)
parent8fa916e9169f507ce7b861f3d9df9a14734672d2 (diff)
downloadcliff-734bc0c5da6915f10823a3124e08ba3ddbd4cc63.tar.gz
Merge "Colourise and automatically page help output"xena-em3.9.0
-rw-r--r--cliff/_argparse.py8
-rw-r--r--cliff/help.py86
-rw-r--r--requirements.txt1
3 files changed, 57 insertions, 38 deletions
diff --git a/cliff/_argparse.py b/cliff/_argparse.py
index c03d709..cb5e4c5 100644
--- a/cliff/_argparse.py
+++ b/cliff/_argparse.py
@@ -12,9 +12,11 @@
"""Overrides of standard argparse behavior."""
-import argparse
+import argparse as orig_argparse
import warnings
+from autopage import argparse
+
class _ArgumentContainerMixIn(object):
@@ -75,12 +77,12 @@ def _handle_conflict_ignore(container, option_string_actions,
)
-class _ArgumentGroup(_ArgumentContainerMixIn, argparse._ArgumentGroup):
+class _ArgumentGroup(_ArgumentContainerMixIn, orig_argparse._ArgumentGroup):
pass
class _MutuallyExclusiveGroup(_ArgumentContainerMixIn,
- argparse._MutuallyExclusiveGroup):
+ orig_argparse._MutuallyExclusiveGroup):
pass
diff --git a/cliff/help.py b/cliff/help.py
index 9ccfeb7..2a235de 100644
--- a/cliff/help.py
+++ b/cliff/help.py
@@ -14,6 +14,8 @@ import argparse
import inspect
import traceback
+import autopage.argparse
+
from . import command
@@ -37,43 +39,53 @@ class HelpAction(argparse.Action):
"""
def __call__(self, parser, namespace, values, option_string=None):
app = self.default
- parser.print_help(app.stdout)
- app.stdout.write('\nCommands:\n')
- dists_by_module = command._get_distributions_by_modules()
+ pager = autopage.argparse.help_pager(app.stdout)
+ color = pager.to_terminal()
+ autopage.argparse.use_color_for_parser(parser, color)
+ with pager as out:
+ parser.print_help(out)
+ title_hl = ('\033[4m', '\033[0m') if color else ('', '')
+ out.write('\n%sCommands%s:\n' % title_hl)
+ dists_by_module = command._get_distributions_by_modules()
- def dist_for_obj(obj):
- name = inspect.getmodule(obj).__name__.partition('.')[0]
- return dists_by_module.get(name)
+ def dist_for_obj(obj):
+ name = inspect.getmodule(obj).__name__.partition('.')[0]
+ return dists_by_module.get(name)
- app_dist = dist_for_obj(app)
- command_manager = app.command_manager
- for name, ep in sorted(command_manager):
- try:
- factory = ep.load()
- except Exception:
- app.stdout.write('Could not load %r\n' % ep)
- if namespace.debug:
- traceback.print_exc(file=app.stdout)
- continue
- try:
- kwargs = {}
- if 'cmd_name' in inspect.getfullargspec(factory.__init__).args:
- kwargs['cmd_name'] = name
- cmd = factory(app, None, **kwargs)
- if cmd.deprecated:
+ app_dist = dist_for_obj(app)
+ command_manager = app.command_manager
+ for name, ep in sorted(command_manager):
+ try:
+ factory = ep.load()
+ except Exception:
+ out.write('Could not load %r\n' % ep)
+ if namespace.debug:
+ traceback.print_exc(file=out)
+ continue
+ try:
+ kwargs = {}
+ fact_args = inspect.getfullargspec(factory.__init__).args
+ if 'cmd_name' in fact_args:
+ kwargs['cmd_name'] = name
+ cmd = factory(app, None, **kwargs)
+ if cmd.deprecated:
+ continue
+ except Exception as err:
+ out.write('Could not instantiate %r: %s\n' % (ep, err))
+ if namespace.debug:
+ traceback.print_exc(file=out)
continue
- except Exception as err:
- app.stdout.write('Could not instantiate %r: %s\n' % (ep, err))
- if namespace.debug:
- traceback.print_exc(file=app.stdout)
- continue
- one_liner = cmd.get_description().split('\n')[0]
- dist_name = dist_for_obj(factory)
- if dist_name and dist_name != app_dist:
- dist_info = ' (' + dist_name + ')'
- else:
- dist_info = ''
- app.stdout.write(' %-13s %s%s\n' % (name, one_liner, dist_info))
+ one_liner = cmd.get_description().split('\n')[0]
+ dist_name = dist_for_obj(factory)
+ if dist_name and dist_name != app_dist:
+ dist_info = ' (' + dist_name + ')'
+ if color:
+ dist_info = '\033[90m%s\033[39m' % dist_info
+ else:
+ dist_info = ''
+ if color:
+ name = '\033[36m%s\033[39m' % name
+ out.write(' %-13s %s%s\n' % (name, one_liner, dist_info))
raise HelpExit()
@@ -118,7 +130,11 @@ class HelpCommand(command.Command):
else ' '.join([self.app.NAME, cmd_name])
)
cmd_parser = cmd.get_parser(full_name)
- cmd_parser.print_help(self.app.stdout)
+ pager = autopage.argparse.help_pager(self.app.stdout)
+ with pager as out:
+ autopage.argparse.use_color_for_parser(cmd_parser,
+ pager.to_terminal())
+ cmd_parser.print_help(out)
else:
action = HelpAction(None, None, default=self.app)
action(self.app.parser, self.app.options, None, None)
diff --git a/requirements.txt b/requirements.txt
index 774d9d2..4450bd7 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,6 +2,7 @@
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
pbr!=2.1.0,>=2.0.0 # Apache-2.0
+autopage>=0.4.0 # Apache 2.0
cmd2>=1.0.0 # MIT
PrettyTable>=0.7.2 # BSD
pyparsing>=2.1.0 # MIT