diff --git a/willie/bot.py b/willie/bot.py index c182683100..b8dc1089d6 100644 --- a/willie/bot.py +++ b/willie/bot.py @@ -306,6 +306,9 @@ def setup(self): self.callables = set() self.shutdown_methods = set() + # module name: list(command names) + self.modules_commands = {} + filenames = self.config.enumerate_modules() # Coretasks is special. No custom user coretasks. this_dir = os.path.dirname(os.path.abspath(__file__)) @@ -327,6 +330,7 @@ def setup(self): if hasattr(module, 'setup'): module.setup(self) self.register(vars(module)) + self.register_help(module) modules.append(name) except Exception as e: error_count = error_count + 1 @@ -426,6 +430,33 @@ def remove_func(func, commands): ) self.shutdown_methods.remove(obj) + def register_help(self, module): + commands = sum([ + obj.commands + for _, obj in iteritems(vars(module)) + if hasattr(obj, 'commands') + ], []) + # single command are put in special group "others" + if len(commands) == 1: + others = self.modules_commands.setdefault("others", []) + others.append(commands[0]) + elif commands: + self.modules_commands[module.__name__] = commands + + def unregister_help(self, module): + commands = sum([ + obj.commands + for _, obj in iteritems(vars(module)) + if hasattr(obj, 'commands') + ], []) + if len(commands) == 1: + command = commands[0] + others = self.modules_commands.get("others", []) + if command in others: + del others[others.index(command)] + else: + del self.modules_commands[module.__name__] + def sub(self, pattern): """Replace any of the following special directives in a function's rule expression: $nickname -> the bot's nick diff --git a/willie/modules/help.py b/willie/modules/help.py index 6f235fa6e9..b32e001935 100644 --- a/willie/modules/help.py +++ b/willie/modules/help.py @@ -12,6 +12,8 @@ from willie.module import commands, rule, example, priority from willie.tools import iterkeys +import textwrap + def setup(bot=None): if not bot: @@ -30,7 +32,26 @@ def setup(bot=None): def help(bot, trigger): """Shows a command's documentation, and possibly an example.""" if not trigger.group(2): - bot.reply('Say .help (for example .help c) to get help for a command, or .commands for a list of commands.') + if not trigger.is_privmsg: + bot.reply("Sending my resume in private...") + + bot.notice("Send e.g. '.help length' for more.", trigger.nick) + + groups = bot.modules_commands + name_length = max(6, max(len(k) for k in groups)) + for name in sorted(groups): + group = groups[name] + # set the name column to a constant width + name = name.upper().ljust(name_length) + # bolden the name + group_help = "\002" + name + "\002 " + " ".join(group) + # wrap message with indent for name column + indent = " " * name_length + " " + group_help = textwrap.wrap(group_help, subsequent_indent=indent) + # send it + for line in group_help: + bot.notice(line, trigger.nick) + else: name = trigger.group(2) name = name.lower() diff --git a/willie/modules/reload.py b/willie/modules/reload.py index 0f2999b49d..639495e3f4 100644 --- a/willie/modules/reload.py +++ b/willie/modules/reload.py @@ -45,6 +45,7 @@ def f_reload(bot, trigger): if bot.is_callable(obj) or bot.is_shutdown(obj): old_callables[obj_name] = obj + bot.unregister_help(old_module) bot.unregister(old_callables) # Also remove all references to willie callables from top level of the # module, so that they will not get loaded again if reloading the @@ -72,6 +73,7 @@ def f_reload(bot, trigger): modified = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(mtime)) bot.register(vars(module)) + bot.register_help(module) bot.bind_commands() bot.reply('%r (version: %s)' % (module, modified)) @@ -120,6 +122,7 @@ def f_load(bot, trigger): if hasattr(module, 'setup'): module.setup(bot) bot.register(vars(module)) + bot.register_help(module) bot.bind_commands() bot.reply('%r (version: %s)' % (module, modified))