mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-04-21 08:17:47 +00:00
[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.
This commit is contained in:
parent
6f3bd7c0e6
commit
166d8257ec
@ -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 *
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user