aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Sam Wedgwood <[email protected]>2018-02-13 17:49:15 +0000
committerGravatar GitHub <[email protected]>2018-02-13 17:49:15 +0000
commit1c26f48109ce4d03dd7cd1662ed666ca0d8c9253 (patch)
tree319969407e4f2797ca6e2ed7badeea42ef94ddf8
parentI'm not even gonna check that error (diff)
parentadded type hinting, and rearranged some code for readability (diff)
Merge pull request #7 from discord-python/help-formatter
new HelpFormatter added #1pv7x
-rw-r--r--bot/__main__.py4
-rw-r--r--bot/constants.py2
-rw-r--r--bot/formatter.py102
3 files changed, 107 insertions, 1 deletions
diff --git a/bot/__main__.py b/bot/__main__.py
index 6d5c2c063..2c9bf4db3 100644
--- a/bot/__main__.py
+++ b/bot/__main__.py
@@ -4,6 +4,7 @@ import os
from discord import Game
from discord.ext.commands import AutoShardedBot, when_mentioned_or
+from bot.formatter import Formatter
from bot.utils import CaseInsensitiveDict
bot = AutoShardedBot(
@@ -14,7 +15,8 @@ bot = AutoShardedBot(
">>>", ">>", ">"
), # Order matters (and so do commas)
game=Game(name="Help: bot.help()"),
- help_attrs={"aliases": ["help()"]}
+ help_attrs={"aliases": ["help()"]},
+ formatter=Formatter()
)
bot.cogs = CaseInsensitiveDict()
diff --git a/bot/constants.py b/bot/constants.py
index e11a625ac..9030a100e 100644
--- a/bot/constants.py
+++ b/bot/constants.py
@@ -9,3 +9,5 @@ ADMIN_ROLE = 267628507062992896
MODERATOR_ROLE = 267629731250176001
VERIFIED_ROLE = 352427296948486144
OWNER_ROLE = 267627879762755584
+
+HELP_PREFIX = "bot."
diff --git a/bot/formatter.py b/bot/formatter.py
new file mode 100644
index 000000000..503ae331d
--- /dev/null
+++ b/bot/formatter.py
@@ -0,0 +1,102 @@
+# coding=utf-8
+
+"""
+Credit to Rapptz's script used as an example:
+https://github.com/Rapptz/discord.py/blob/rewrite/discord/ext/commands/formatter.py
+Which falls under The MIT License.
+"""
+
+import itertools
+from inspect import formatargspec, getfullargspec
+
+from discord.ext.commands import Command, HelpFormatter, Paginator
+
+from bot.constants import HELP_PREFIX
+
+
+class Formatter(HelpFormatter):
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ def _add_subcommands_to_page(self, max_width: int, commands: list):
+ """
+ basically the same function from d.py but changed:
+ - to make the helptext appear as a comment
+ - to change the indentation to the PEP8 standard: 4 spaces
+ """
+ for name, command in commands:
+ if name in command.aliases:
+ # skip aliases
+ continue
+
+ entry = " {0}{1:<{width}} # {2}".format(HELP_PREFIX, name, command.short_doc, width=max_width)
+ shortened = self.shorten(entry)
+ self._paginator.add_line(shortened)
+
+ async def format(self):
+ """
+ rewritten help command to make it more python-y
+
+ example of specific command:
+ async def <command>(ctx, <args>):
+ \"""
+ <help text>
+ \"""
+ await do_<command>(ctx, <args>)
+
+ example of standard help page:
+ class <cog1>:
+ bot.<command1>() # <command1 help>
+ class <cog2>:
+ bot.<command2>() # <command2 help>
+
+ # <ending help note>
+ """
+ self._paginator = Paginator(prefix="```py")
+
+ if isinstance(self.command, Command):
+ # strip the command of bot. and ()
+ stripped_command = self.command.name.replace(HELP_PREFIX, "").replace("()", "")
+
+ # get the args using the handy inspect module
+ argspec = getfullargspec(self.command.callback)
+ arguments = formatargspec(*argspec)
+ args_no_type_hints = ", ".join(argspec[0])
+
+ # remove self from the args
+ arguments = arguments.replace("self, ", "")
+ args_no_type_hints = args_no_type_hints.replace("self, ", "")
+
+ # prepare the different sections of the help output, and add them to the paginator
+ definition = f"async def {stripped_command}{arguments}:"
+ docstring = f" \"\"\"\n {self.command.help}\n \"\"\""
+ invocation = f" await do_{stripped_command}({args_no_type_hints})"
+ self._paginator.add_line(definition)
+ self._paginator.add_line(docstring)
+ self._paginator.add_line(invocation)
+
+ return self._paginator.pages
+
+ max_width = self.max_name_size
+
+ def category_check(tup):
+ cog = tup[1].cog_name
+ # zero width character to make it appear last when put in alphabetical order
+ return cog if cog is not None else "\u200bNoCategory"
+
+ command_list = await self.filter_command_list()
+ data = sorted(command_list, key=category_check)
+
+ for category, commands in itertools.groupby(data, key=category_check):
+ commands = sorted(commands)
+ if len(commands) > 0:
+ self._paginator.add_line(f"class {category}:")
+ self._add_subcommands_to_page(max_width, commands)
+
+ self._paginator.add_line()
+ ending_note = self.get_ending_note()
+ # make the ending note appear as comments
+ ending_note = "# "+ending_note.replace("\n", "\n# ")
+ self._paginator.add_line(ending_note)
+
+ return self._paginator.pages