pyircbot/pyircbot/modules/ModInfo.py

113 lines
3.8 KiB
Python
Raw Normal View History

2017-11-22 22:09:25 -08:00
#!/usr/bin/env python3
"""
.. module::ModInfo
:synopsis: Provides manpage-like info for commands
"""
from pyircbot.modulebase import ModuleBase, command
class info(object):
"""
Decorator for tagging module methods with help text
.. code-block:: python
from pyircbot.modules.ModInfo import info
...
@info("help [command] show the manual for all or [commands]", cmds=["help", "rtfm"])
@command("help")
def cmd_help(self, msg, cmd):
...
:param docstring: command help formatted as above
:type docstring: str
:param cmds: enable command names or aliases this function implements, as a list of strings. E.g. if the "help"
command has the alias "rtfm"
:type cmds: list
"""
2018-02-10 19:52:32 -08:00
def __init__(self, cmdspec, docstring, cmds=None):
self.cmdspec = cmdspec
2017-11-22 22:09:25 -08:00
self.docstring = docstring
2018-02-10 19:52:32 -08:00
self.aliases = cmds or []
2017-11-22 22:09:25 -08:00
def __call__(self, func):
2017-11-27 18:58:20 -08:00
if hasattr(func, "irchelp"):
2018-02-10 19:52:32 -08:00
func.irchelp.append(self)
2017-11-27 18:58:20 -08:00
else:
2018-02-10 19:52:32 -08:00
setattr(func, "irchelp", [self])
2017-11-22 22:09:25 -08:00
return func
class ModInfo(ModuleBase):
2018-02-10 19:52:32 -08:00
@info("help [command]", "show the manual for all or [commands]", cmds=["help"])
2017-11-22 22:09:25 -08:00
@command("help")
def cmd_help(self, msg, cmd):
"""
Get help on a command
"""
if cmd.args:
2018-02-10 19:52:32 -08:00
for modname, module, cmdspec, docstring, aliases in self.iter_modules():
if cmd.args[0] in ["{}{}".format(command.prefix, i) for i in aliases]:
self.bot.act_PRIVMSG(msg.args[0], "RTFM: {}: ({}{}) {}"
.format(cmd.args[0], command.prefix, cmdspec, docstring))
2017-11-22 22:09:25 -08:00
else:
2018-02-10 19:52:32 -08:00
rows = []
for modname, module, cmdspec, docstring, aliases in self.iter_modules():
rows.append((modname, command.prefix + cmdspec, docstring))
rows.sort(key=lambda item: item[0] + item[1])
self.send_columnized(msg.args[0], rows)
def send_columnized(self, channel, rows):
if not rows:
return
widths = []
# Find how many col widths we must calculate
for _ in rows[0]:
widths.append(0)
# Find widest value per col
for row in rows:
for col, value in enumerate(row):
print(col, value)
vlen = len(value)
if vlen > widths[col]:
widths[col] = vlen
# Print each row
for row in rows:
message = ""
for colid, col in enumerate(row):
message += str(col)
message += (" " * (widths[colid] - len(col) + 1))
self.bot.act_PRIVMSG(channel, message)
@info("helpindex", "show a short list of all commands", cmds=["helpindex"])
2017-11-22 22:09:25 -08:00
@command("helpindex")
def cmd_helpindex(self, msg, cmd):
"""
Short index of commands
"""
commands = []
2018-02-10 19:52:32 -08:00
for modname, module, cmdspec, docstring, aliases in self.iter_modules():
commands += ["{}{}".format(command.prefix, i) for i in aliases]
2017-11-22 22:09:25 -08:00
self.bot.act_PRIVMSG(msg.args[0], "{}: commands: {}".format(msg.prefix.nick, ", ".join(commands)))
def iter_modules(self):
"""
Iterator that cycles through module methods that are tagged with help information. The iterator yields tuples
of:
2018-02-10 19:52:32 -08:00
(module_name, module_object, command_spec, command_help, command_list)
2017-11-22 22:09:25 -08:00
"""
for modname, module in self.bot.moduleInstances.items():
for attr_name in dir(module):
attr = getattr(module, attr_name)
if callable(attr) and hasattr(attr, "irchelp"):
2018-02-10 19:52:32 -08:00
for cmdinfo in attr.irchelp:
yield (modname, module, cmdinfo.cmdspec, cmdinfo.docstring, cmdinfo.aliases)
2017-11-22 22:09:25 -08:00
raise StopIteration()