summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipalib/cli.py97
1 files changed, 77 insertions, 20 deletions
diff --git a/ipalib/cli.py b/ipalib/cli.py
index 378bc5715..1e77657d3 100644
--- a/ipalib/cli.py
+++ b/ipalib/cli.py
@@ -418,36 +418,93 @@ class help(frontend.Command):
takes_args = [Bytes('command?')]
+ _PLUGIN_BASE_MODULE = 'ipalib.plugins'
+
+ def _get_command_module(self, cmd_plugin_proxy):
+ """
+ Return bare module name where command represented by PluginProxy
+ instance is defined. Return None if command isn't defined in
+ a plugin module (we consider these commands to be builtins).
+ """
+ # get representation in the form of 'base_module.bare_module.command()'
+ r = repr(cmd_plugin_proxy)
+ # skip base module part and the following dot
+ start = r.find(self._PLUGIN_BASE_MODULE)
+ if start == -1:
+ # command module isn't a plugin module, it's a builtin
+ return None
+ start += len(self._PLUGIN_BASE_MODULE) + 1
+ # parse bare module name
+ end = r.find('.', start)
+ return r[start:end]
+
def finalize(self):
- self.__topics = dict(
- (to_cli(c.name), c) for c in self.Command()
+ # {plugin_module: [mcl, commands]}
+ self._topics = {}
+ # [builtin_commands]
+ self._builtins = []
+
+ # build help topics
+ for c in self.Command():
+ topic = self._get_command_module(c)
+ if topic:
+ self._topics.setdefault(topic, [0]).append(c)
+ # compute maximum length of command in topic
+ mcl = max((self._topics[topic][0], len(c.name)))
+ self._topics[topic][0] = mcl
+ else:
+ self._builtins.append(c)
+
+ # compute maximum topic length
+ self._mtl = max(
+ len(s) for s in (self._topics.keys() + self._builtins)
)
+
super(help, self).finalize()
def run(self, key):
-
if key is None:
- self.print_commands()
+ self.print_topics()
return
name = from_cli(key)
- if name not in self.Command:
- raise HelpError(topic=key)
- cmd = self.Command[name]
- print 'Purpose: %s' % cmd.doc
- self.Backend.cli.build_parser(cmd).print_help()
-
- def print_commands(self):
- mcl = self.get_mcl()
- for cmd in self.api.Command():
- print ' %s %s' % (
- to_cli(cmd.name).ljust(mcl),
- cmd.doc,
- )
- print '\nUse the --help option to see all the global options'
+ if name in self._topics:
+ self.print_commands(name)
+ elif name in self.Command:
+ cmd = self.Command[name]
+ print 'Purpose: %s' % cmd.doc
+ self.Backend.cli.build_parser(cmd).print_help()
+ else:
+ raise HelpError(topic=name)
+
+ def print_topics(self):
+ topics = sorted(self._topics.keys())
+
+ print 'Usage: ipa [global-options] COMMAND ...'
+ print ''
+ print 'Built-in commands:'
+ for c in self._builtins:
+ doc = (c.doc or '').strip().split('\n', 1)[0]
+ print ' %s %s' % (to_cli(c.name).ljust(self._mtl), c.doc)
print ''
+ print 'Help topics:'
+ for t in topics:
+ m = '%s.%s' % (self._PLUGIN_BASE_MODULE, t)
+ doc = (sys.modules[m].__doc__ or '').strip().split('\n', 1)[0]
+ print ' %s %s' % (to_cli(t).ljust(self._mtl), doc)
+ print ''
+ print 'Try `ipa --help` for a list of global options.'
+
+ def print_commands(self, topic):
+ mcl = self._topics[topic][0]
+ commands = self._topics[topic][1:]
+ m = '%s.%s' % (self._PLUGIN_BASE_MODULE, topic)
+ doc = (sys.modules[m].__doc__ or '').strip()
- def get_mcl(self):
- return max(len(k) for k in self.Command)
+ print doc
+ print ''
+ print 'Related commands:'
+ for c in commands:
+ print ' %s %s' % (to_cli(c.name).ljust(mcl), c.doc)
class console(frontend.Application):