11# Warning: The implementation below touches several private attributes.
2- # While this implementation will be updated, and public interfaces maintained, derived classes
3- # should not assume these private attributes are version safe, and use the provided HelpSettings
4- # class for these settings.
2+ # While this implementation will be updated, and public interfaces maintained,
3+ # derived classes should not assume these private attributes are version safe,
4+ # and use the provided HelpSettings class for these settings.
55
66# This is a full replacement of discord.py's help command
77#
8- # At a later date, there should be things added to support extra formatter
9- # registration from 3rd party cogs.
10- #
118# This exists due to deficiencies in discord.py which conflict
129# with our needs for per-context help settings
1310# see https://github.com/Rapptz/discord.py/issues/2123
3027# Additionally, this gives our users a bit more customization options including by
3128# 3rd party cogs down the road.
3229
33- # Note: 3rd party help must not remove the copyright notice
34-
30+ import abc
3531import asyncio
3632from collections import namedtuple
3733from dataclasses import dataclass
4844from ..utils ._internal_utils import fuzzy_command_search , format_fuzzy_results
4945from ..utils .chat_formatting import box , pagify
5046
51- __all__ = ["red_help" , "RedHelpFormatter" , "HelpSettings" ]
47+ __all__ = ["red_help" , "RedHelpFormatter" , "HelpSettings" , "HelpFormatterABC" ]
5248
5349_ = Translator ("Help" , __file__ )
5450
6561class HelpSettings :
6662 """
6763 A representation of help settings.
64+
65+ .. warning::
66+
67+ This class is provisional.
68+
6869 """
6970
7071 page_char_limit : int = 1000
@@ -78,8 +79,10 @@ class HelpSettings:
7879
7980 # Contrib Note: This is intentional to not accept the bot object
8081 # There are plans to allow guild and user specific help settings
81- # Adding a non-context based method now would involve a breaking change later.
82- # At a later date, more methods should be exposed for non-context based creation.
82+ # Adding a non-context based method now would involve a breaking
83+ # change later.
84+ # At a later date, more methods should be exposed for
85+ # non-context based creation.
8386 #
8487 # This is also why we aren't just caching the
8588 # current state of these settings on the bot object.
@@ -102,23 +105,72 @@ def __init__(self, *, last, not_found):
102105 self .not_found = not_found
103106
104107
105- class RedHelpFormatter :
108+ class HelpFormatterABC (abc .ABC ):
109+ """
110+ Describes the required interface of a help formatter.
111+
112+ Additional notes for 3rd party developers are included in this class.
113+
114+ .. note::
115+ You may define __init__ however you want
116+ (such as to include config),
117+ Red will not initialize a formatter for you,
118+ and must be passed an initialized formatter.
119+
120+ If you want to use Red's existing settings, use ``HelpSettings.from_context``
121+
122+ .. warning::
123+
124+ This class is documented but provisional with expected changes.
125+
126+ In the future, this class will receive changes to support
127+ invoking the help command without context.
128+ """
129+
130+ @abc .abstractmethod
131+ async def send_help (
132+ self , ctx : Context , help_for : HelpTarget = None , * , from_help_command : bool = False
133+ ):
134+ """
135+ This is (currently) the only method you must implement.
136+
137+ This method should handle any and all errors which may arise.
138+
139+ The types subclasses must handle are defined as ``HelpTarget``
140+ """
141+ ...
142+
143+
144+ class RedHelpFormatter (HelpFormatterABC ):
106145 """
107146 Red's help implementation
108147
109148 This is intended to be overridable in parts to only change some behavior.
110149
111- While currently, there is a global formatter, later plans include a context specific
112- formatter selector as well as an API for cogs to register/un-register a formatter with the bot.
150+ While this exists as a class for easy partial overriding,
151+ most implementations should not need or want a shared state.
152+
153+ .. warning::
113154
114- When implementing your own formatter, at minimum you must provide an implementation of
115- `send_help` with identical signature.
155+ This class is documented but may receive changes between
156+ versions without warning as needed.
157+ The supported way to modify help is to write a separate formatter.
116158
117- While this exists as a class for easy partial overriding, most implementations
118- should not need or want a shared state.
159+ The primary reason for this class being documented is to allow
160+ the opaque use of the class as a fallback, as any method in base
161+ class which is intended for use will be present and implemented here.
162+
163+ .. note::
164+
165+ This class may use various internal methods which are not safe to
166+ use in third party code.
167+ The internal methods used here may change,
168+ with this class being updated at the same time.
119169 """
120170
121- async def send_help (self , ctx : Context , help_for : HelpTarget = None ):
171+ async def send_help (
172+ self , ctx : Context , help_for : HelpTarget = None , * , from_help_command : bool = False
173+ ):
122174 """
123175 This delegates to other functions.
124176
@@ -724,4 +776,4 @@ async def red_help(ctx: Context, *, thing_to_get_help_for: str = None):
724776 (Help) you know I need someone
725777 (Help!)
726778 """
727- await ctx .bot .send_help_for (ctx , thing_to_get_help_for )
779+ await ctx .bot .send_help_for (ctx , thing_to_get_help_for , from_help_command = True )
0 commit comments