aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRapptz <[email protected]>2016-07-05 21:44:14 -0400
committerRapptz <[email protected]>2016-07-05 21:44:14 -0400
commit166d8257ec739dca681042399acb280e58bc9f97 (patch)
tree75ea97b662812b09f1a9b1faa499a317fc75a9f2
parentFix issue with removing roles out of order. (diff)
downloaddiscord.py-166d8257ec739dca681042399acb280e58bc9f97.tar.xz
discord.py-166d8257ec739dca681042399acb280e58bc9f97.zip
[commands] Refactor pagination into its own class.
This change allows users to more easily create their own formatters without having to reinvent the pagination logic themselves. Hopefully this makes it less of a pain for people to create custom help pages.
-rw-r--r--discord/ext/commands/__init__.py2
-rw-r--r--discord/ext/commands/formatter.py118
2 files changed, 71 insertions, 49 deletions
diff --git a/discord/ext/commands/__init__.py b/discord/ext/commands/__init__.py
index 6d82962d..ed28b6a0 100644
--- a/discord/ext/commands/__init__.py
+++ b/discord/ext/commands/__init__.py
@@ -14,5 +14,5 @@ from .bot import Bot, when_mentioned, when_mentioned_or
from .context import Context
from .core import *
from .errors import *
-from .formatter import HelpFormatter
+from .formatter import HelpFormatter, Paginator
from .converter import *
diff --git a/discord/ext/commands/formatter.py b/discord/ext/commands/formatter.py
index d20d6579..452fd40e 100644
--- a/discord/ext/commands/formatter.py
+++ b/discord/ext/commands/formatter.py
@@ -51,6 +51,64 @@ from .errors import CommandError
# Type <prefix>help command for more info on a command.
# You can also type <prefix>help category for more info on a category.
+class Paginator:
+ """A class that aids in paginating code blocks for Discord messages.
+
+ Attributes
+ -----------
+ prefix: str
+ The prefix inserted to every page. e.g. three backticks.
+ suffix: str
+ The suffix appended at the end of every page. e.g. three backticks.
+ max_size: int
+ The maximum amount of codepoints allowed in a page.
+ """
+ def __init__(self, prefix='```', suffix='```', max_size=2000):
+ self.prefix = prefix
+ self.suffix = suffix
+ self.max_size = max_size - len(suffix)
+ self._current_page = [prefix]
+ self._count = len(prefix) + 1 # prefix + newline
+ self._pages = []
+
+ def add_line(self, line='', *, empty=False):
+ """Adds a line to the current page.
+
+ Parameters
+ -----------
+ line: str
+ The line to add.
+ empty: bool
+ Indicates if another empty line should be added.
+ """
+ if self._count + len(line) + 1 > self.max_size:
+ self.close_page()
+
+ self._count += len(line) + 1
+ self._current_page.append(line)
+
+ if empty:
+ self._current_page.append('')
+ self._count += 1
+
+ def close_page(self):
+ """Prematurely terminate a page."""
+ self._current_page.append(self.suffix)
+ self._pages.append('\n'.join(self._current_page))
+ self._current_page = [self.prefix]
+ self._count = len(self.prefix) + 1 # prefix + newline
+
+ @property
+ def pages(self):
+ """Returns the rendered list of pages."""
+ # we have more than just the prefix in our current page
+ if len(self._current_page) > 1:
+ self.close_page()
+ return self._pages
+
+ def __repr__(self):
+ fmt = '<Paginator prefix: {0.prefix} suffix: {0.suffix} max_size: {0.max_size} count: {0._count}>'
+ return fmt.format(self)
class HelpFormatter:
"""The default base implementation that handles formatting of the help
@@ -190,18 +248,6 @@ class HelpFormatter:
iterator = self.command.commands.items() if not self.is_cog() else self.context.bot.commands.items()
return filter(predicate, iterator)
- def _check_new_page(self):
- # be a little on the safe side
- # we're adding 1 extra newline per page
- if self._count + len(self._current_page) >= 1980:
- # add the page
- self._current_page.append('```')
- self._pages.append('\n'.join(self._current_page))
- self._current_page = ['```']
- self._count = 4
- return True
- return False
-
def _add_subcommands_to_page(self, max_width, commands):
for name, command in commands:
if name in command.aliases:
@@ -210,10 +256,7 @@ class HelpFormatter:
entry = ' {0:<{width}} {1}'.format(name, command.short_doc, width=max_width)
shortened = self.shorten(entry)
- self._count += len(shortened)
- if self._check_new_page():
- self._count += len(shortened)
- self._current_page.append(shortened)
+ self._paginator.add_line(shortened)
def format_help_for(self, context, command_or_bot):
"""Formats the help page and handles the actual heavy lifting of how
@@ -246,9 +289,7 @@ class HelpFormatter:
list
A paginated output of the help command.
"""
- self._pages = []
- self._count = 4 # ``` + '\n'
- self._current_page = ['```']
+ self._paginator = Paginator()
# we need a padding of ~80 or so
@@ -256,30 +297,21 @@ class HelpFormatter:
if description:
# <description> portion
- self._current_page.append(description)
- self._current_page.append('')
- self._count += len(description)
+ self._paginator.add_line(description, empty=True)
if isinstance(self.command, Command):
# <signature portion>
signature = self.get_command_signature()
- self._count += 2 + len(signature) # '\n' sig '\n'
- self._current_page.append(signature)
- self._current_page.append('')
+ self._paginator.add_line(signature, empty=True)
# <long doc> section
if self.command.help:
- self._count += 2 + len(self.command.help)
- self._current_page.append(self.command.help)
- self._current_page.append('')
- self._check_new_page()
+ self._paginator.add_line(self.command.help, empty=True)
# end it here if it's just a regular command
if not self.has_subcommands():
- self._current_page.append('```')
- self._pages.append('\n'.join(self._current_page))
- return self._pages
-
+ self._paginator.close_page()
+ return self._paginator.pages
max_width = self.max_name_size
@@ -295,25 +327,15 @@ class HelpFormatter:
# there simply is no prettier way of doing this.
commands = list(commands)
if len(commands) > 0:
- self._current_page.append(category)
- self._count += len(category)
- self._check_new_page()
+ self._paginator.add_line(category)
self._add_subcommands_to_page(max_width, commands)
else:
- self._current_page.append('Commands:')
- self._count += 1 + len(self._current_page[-1])
+ self._paginator.add_line('Commands:')
self._add_subcommands_to_page(max_width, self.filter_command_list())
# add the ending note
- self._current_page.append('')
+ self._paginator.add_line()
ending_note = self.get_ending_note()
- self._count += len(ending_note)
- self._check_new_page()
- self._current_page.append(ending_note)
-
- if len(self._current_page) > 1:
- self._current_page.append('```')
- self._pages.append('\n'.join(self._current_page))
-
- return self._pages
+ self._paginator.add_line(ending_note)
+ return self._paginator.pages