[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 re import search
from re import findall, search
from string import Formatter
from typing import Generator, Tuple, Iterable, Optional
import discord
from discord.ext.commands.view import StringView, quoted_word
from redbot.core import Config, commands, checks
from redbot.core.i18n import Translator, cog_i18n
from redbot.core.utils.chat_formatting import box
@ -13,6 +15,21 @@ from .alias_entry import AliasEntry
_ = 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(_)
class Alias(commands.Cog):
"""Create aliases for commands.
@ -80,8 +97,25 @@ class Alias(commands.Cog):
return not bool(search(r"\s", alias_name)) and alias_name.isprintable()
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:
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_)
if global_:
@ -142,7 +176,17 @@ class Alias(commands.Cog):
:return:
"""
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
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):
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
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)
@commands.group()
@ -228,7 +280,10 @@ class Alias(commands.Cog):
# At this point we know we need to make a new alias
# 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(
_("A new alias with the trigger `{name}` has been created.").format(name=alias_name)
@ -274,7 +329,10 @@ class Alias(commands.Cog):
return
# 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(
_("A new global alias with the trigger `{name}` has been created.").format(