[V3 Alias] Customize Parameters (#2455)

* [alias] custom parameters

Signed-off-by: zephyrkul <zephyrkul@users.noreply.github.com>

* [alias] quoted words remain quoted

Signed-off-by: zephyrkul <zephyrkul@users.noreply.github.com>

* [alias] fix no-parameter aliases

Signed-off-by: zephyrkul <zephyrkul@users.noreply.github.com>

* [alias] remove unneeded error dispatch

it was expensive and did nothing anyway from my own testing
This commit is contained in:
zephyrkul 2019-04-02 21:08:28 -06:00 committed by Will
parent 82cda4b57a
commit d6d6d14977

View File

@ -1,8 +1,10 @@
from copy import copy from copy import copy
from re import search from re import findall, search
from string import Formatter
from typing import Generator, Tuple, Iterable, Optional from typing import Generator, Tuple, Iterable, Optional
import discord import discord
from discord.ext.commands.view import StringView, quoted_word
from redbot.core import Config, commands, checks from redbot.core import Config, commands, checks
from redbot.core.i18n import Translator, cog_i18n from redbot.core.i18n import Translator, cog_i18n
from redbot.core.utils.chat_formatting import box from redbot.core.utils.chat_formatting import box
@ -13,6 +15,21 @@ from .alias_entry import AliasEntry
_ = Translator("Alias", __file__) _ = Translator("Alias", __file__)
class _TrackingFormatter(Formatter):
def __init__(self):
super().__init__()
self.max = -1
def get_value(self, key, args, kwargs):
if isinstance(key, int):
self.max = max((key, self.max))
return super().get_value(key, args, kwargs)
class ArgParseError(Exception):
pass
@cog_i18n(_) @cog_i18n(_)
class Alias(commands.Cog): class Alias(commands.Cog):
"""Create aliases for commands. """Create aliases for commands.
@ -80,8 +97,25 @@ class Alias(commands.Cog):
return not bool(search(r"\s", alias_name)) and alias_name.isprintable() return not bool(search(r"\s", alias_name)) and alias_name.isprintable()
async def add_alias( async def add_alias(
self, ctx: commands.Context, alias_name: str, command: Tuple[str], global_: bool = False self, ctx: commands.Context, alias_name: str, command: str, global_: bool = False
) -> AliasEntry: ) -> AliasEntry:
indices = findall(r"{(\d*)}", command)
if indices:
try:
indices = [int(a[0]) for a in indices]
except IndexError:
raise ArgParseError(_("Arguments must be specified with a number."))
low = min(indices)
indices = [a - low for a in indices]
high = max(indices)
gaps = set(indices).symmetric_difference(range(high + 1))
if gaps:
raise ArgParseError(
_("Arguments must be sequential. Missing arguments: ")
+ ", ".join(str(i + low) for i in gaps)
)
command = command.format(*(f"{{{i}}}" for i in range(-low, high + low + 1)))
alias = AliasEntry(alias_name, command, ctx.author, global_=global_) alias = AliasEntry(alias_name, command, ctx.author, global_=global_)
if global_: if global_:
@ -142,7 +176,17 @@ class Alias(commands.Cog):
:return: :return:
""" """
known_content_length = len(prefix) + len(alias.name) known_content_length = len(prefix) + len(alias.name)
extra = message.content[known_content_length:].strip() extra = message.content[known_content_length:]
view = StringView(extra)
view.skip_ws()
extra = []
while not view.eof:
prev = view.index
word = quoted_word(view)
if len(word) < view.index - prev:
word = "".join((view.buffer[prev], word, view.buffer[view.index - 1]))
extra.append(word)
view.skip_ws()
return extra return extra
async def maybe_call_alias( async def maybe_call_alias(
@ -167,10 +211,18 @@ class Alias(commands.Cog):
async def call_alias(self, message: discord.Message, prefix: str, alias: AliasEntry): async def call_alias(self, message: discord.Message, prefix: str, alias: AliasEntry):
new_message = copy(message) new_message = copy(message)
args = self.get_extra_args_from_alias(message, prefix, alias) try:
args = self.get_extra_args_from_alias(message, prefix, alias)
except commands.BadArgument as bae:
return
trackform = _TrackingFormatter()
command = trackform.format(alias.command, *args)
# noinspection PyDunderSlots # noinspection PyDunderSlots
new_message.content = "{}{} {}".format(prefix, alias.command, args) new_message.content = "{}{} {}".format(
prefix, command, " ".join(args[trackform.max + 1 :])
)
await self.bot.process_commands(new_message) await self.bot.process_commands(new_message)
@commands.group() @commands.group()
@ -228,7 +280,10 @@ class Alias(commands.Cog):
# At this point we know we need to make a new alias # At this point we know we need to make a new alias
# and that the alias name is valid. # and that the alias name is valid.
await self.add_alias(ctx, alias_name, command) try:
await self.add_alias(ctx, alias_name, command)
except ArgParseError as e:
return await ctx.send(" ".join(e.args))
await ctx.send( await ctx.send(
_("A new alias with the trigger `{name}` has been created.").format(name=alias_name) _("A new alias with the trigger `{name}` has been created.").format(name=alias_name)
@ -274,7 +329,10 @@ class Alias(commands.Cog):
return return
# endregion # endregion
await self.add_alias(ctx, alias_name, command, global_=True) try:
await self.add_alias(ctx, alias_name, command, global_=True)
except ArgParseError as e:
return await ctx.send(" ".join(e.args))
await ctx.send( await ctx.send(
_("A new global alias with the trigger `{name}` has been created.").format( _("A new global alias with the trigger `{name}` has been created.").format(