From da365e3bc1f7f90f57e8c19de628c945ff8e0f1b Mon Sep 17 00:00:00 2001 From: stijndcl Date: Mon, 19 Sep 2022 15:59:12 +0200 Subject: [PATCH] Don't split code in codeblocks --- didier/cogs/currency.py | 16 ++++++++++++++-- didier/cogs/help.py | 30 ++++++++++++++++++++++++------ didier/utils/types/string.py | 26 +++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/didier/cogs/currency.py b/didier/cogs/currency.py index ea96187..87ea898 100644 --- a/didier/cogs/currency.py +++ b/didier/cogs/currency.py @@ -120,7 +120,19 @@ class Currency(commands.Cog): @commands.command(name="invest", aliases=["deposit", "dep"]) async def invest(self, ctx: commands.Context, amount: typing.Annotated[typing.Union[str, int], abbreviated_number]): - """Invest a given amount of Didier Dinks""" + """Invest a given `amount` Didier Dinks. + + The `amount`-parameter can take both raw numbers, and abbreviations of big numbers. Passing `all` as the + value will invest all of your Didier Dinks. + + Example usage: + ``` + didier invest all + didier invest 500 + didier invest 25k + didier invest 5.3b + ``` + """ async with self.client.postgres_session as session: invested = await crud.invest(session, ctx.author.id, amount) plural = pluralize("Didier Dink", invested) @@ -134,7 +146,7 @@ class Currency(commands.Cog): @commands.hybrid_command(name="nightly") async def nightly(self, ctx: commands.Context): - """Claim nightly Didier Dinks""" + """Claim nightly Didier Dinks.""" async with self.client.postgres_session as session: try: await crud.claim_nightly(session, ctx.author.id) diff --git a/didier/cogs/help.py b/didier/cogs/help.py index 0693f50..a43a7f1 100644 --- a/didier/cogs/help.py +++ b/didier/cogs/help.py @@ -7,6 +7,7 @@ from overrides import overrides from didier import Didier from didier.utils.discord.colours import error_red +from didier.utils.types.string import re_find_all, re_replace_with_list class CustomHelpCommand(commands.MinimalHelpCommand): @@ -142,17 +143,34 @@ class CustomHelpCommand(commands.MinimalHelpCommand): embed = discord.Embed(title=title.title(), colour=discord.Colour.blue()) return embed + def _clean_command_help(self, command: commands.Command) -> str: + """Clean up a help docstring + + This will strip out single newlines, because these are only there for readability and line length. + These are instead replaced with spaces. + + Code in codeblocks is ignored, as it is used to create examples. + """ + description = command.help + codeblocks = re_find_all(r"\n?```.*?```", description, flags=re.DOTALL) + + # Regex borrowed from https://stackoverflow.com/a/59843498/13568999 + description = re.sub( + r"([^\S\n]*\n(?:[^\S\n]*\n)+[^\S\n]*)|[^\S\n]*\n[^\S\n]*", lambda x: x.group(1) or " ", description + ) + + # Replace codeblocks with their original form + if codeblocks: + description = re_replace_with_list(r"```.*?```", description, codeblocks) + + return description + def _add_command_help(self, embed: discord.Embed, command: commands.Command): """Add command-related information to an embed This allows re-using this logic for Group commands that can be invoked by themselves. """ - # Regex borrowed from https://stackoverflow.com/a/59843498/13568999 - # Remove single newlines but keep double newlines - # This allows short lines in the docstring, but joins them together for the help description - embed.description = re.sub( - r"([^\S\n]*\n(?:[^\S\n]*\n)+[^\S\n]*)|[^\S\n]*\n[^\S\n]*", lambda x: x.group(1) or " ", command.help - ) + embed.description = self._clean_command_help(command) signature = self.get_command_signature(command) embed.add_field(name="Signature", value=signature, inline=False) diff --git a/didier/utils/types/string.py b/didier/utils/types/string.py index 4e02573..b8c5e04 100644 --- a/didier/utils/types/string.py +++ b/didier/utils/types/string.py @@ -1,7 +1,8 @@ import math +import re from typing import Optional -__all__ = ["abbreviate", "leading", "pluralize", "get_edu_year_name"] +__all__ = ["abbreviate", "leading", "pluralize", "re_find_all", "re_replace_with_list", "get_edu_year_name"] def abbreviate(text: str, max_length: int) -> str: @@ -45,6 +46,29 @@ def pluralize(word: str, amount: int, plural_form: Optional[str] = None) -> str: return plural_form or (word + "s") +def re_find_all(pattern: str, string: str, flags: re.RegexFlag = 0) -> list[str]: + """Find all matches of a regex in a string""" + matches = [] + + while True: + match = re.search(pattern, string, flags=flags) + if not match: + break + + matches.append(match.group(0)) + string = string[match.end() :] + + return matches + + +def re_replace_with_list(pattern: str, string: str, replacements: list[str]) -> str: + """Replace all matches of a pattern one by one using a list of replacements""" + for replacement in replacements: + string = re.sub(pattern, replacement, string, count=1) + + return string + + def get_edu_year_name(year: int) -> str: # pragma: no cover """Get the string representation of a university year""" years = ["1st Bachelor", "2nd Bachelor", "3rd Bachelor", "1st Master", "2nd Master"]