From 95cf63243d7b31644206678382600c57bbd380fb Mon Sep 17 00:00:00 2001 From: FiniteReality Date: Fri, 26 Aug 2016 22:23:37 +0100 Subject: [PATCH 1/2] Implement Command Aliases This implementation could probably be more efficient, but I opted for clarity and simplicity where possible. --- .../Attributes/AliasAttribute.cs | 18 +++++++++++++ src/Discord.Net.Commands/Command.cs | 25 ++++++++++++++++++- src/Discord.Net.Commands/Map/CommandMap.cs | 24 ++++++++++-------- 3 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 src/Discord.Net.Commands/Attributes/AliasAttribute.cs diff --git a/src/Discord.Net.Commands/Attributes/AliasAttribute.cs b/src/Discord.Net.Commands/Attributes/AliasAttribute.cs new file mode 100644 index 000000000..9aa1371f6 --- /dev/null +++ b/src/Discord.Net.Commands/Attributes/AliasAttribute.cs @@ -0,0 +1,18 @@ +using System; + +namespace Discord.Commands +{ + /// Provides aliases for a command. + [AttributeUsage(AttributeTargets.Method)] + public class AliasAttribute : Attribute + { + /// The aliases which have been defined for the command. + public string[] Aliases { get; } + + /// Creates a new with the given aliases. + public AliasAttribute(params string[] aliases) + { + Aliases = aliases; + } + } +} diff --git a/src/Discord.Net.Commands/Command.cs b/src/Discord.Net.Commands/Command.cs index 3e8d596dd..f7bbc7d35 100644 --- a/src/Discord.Net.Commands/Command.cs +++ b/src/Discord.Net.Commands/Command.cs @@ -25,6 +25,7 @@ namespace Discord.Commands public string Summary { get; } public string Text { get; } public bool HasVarArgs { get; } + public IReadOnlyList Aliases { get; } public IReadOnlyList Parameters { get; } public IReadOnlyList Preconditions { get; } @@ -37,6 +38,16 @@ namespace Discord.Commands Name = source.Name; Text = groupPrefix + attribute.Text; + var aliasesBuilder = ImmutableArray.CreateBuilder(); + + aliasesBuilder.Add(Text); + + var aliasesAttr = source.GetCustomAttribute(); + if (aliasesAttr != null) + aliasesBuilder.AddRange(aliasesAttr.Aliases.Select(x => groupPrefix + x)); + + Aliases = aliasesBuilder.ToImmutable(); + var nameAttr = source.GetCustomAttribute(); if (nameAttr != null) Name = nameAttr.Text; @@ -81,7 +92,19 @@ namespace Discord.Commands if (preconditionResult != null && !preconditionResult.Value.IsSuccess) return ParseResult.FromError(preconditionResult.Value); - return await CommandParser.ParseArgs(this, msg, searchResult.Text.Substring(Text.Length), 0).ConfigureAwait(false); + string input = searchResult.Text; + var matchingAliases = Aliases.Where(alias => input.StartsWith(alias)); + + string matchingAlias = ""; + foreach (string alias in matchingAliases) + { + if (alias.Length > matchingAlias.Length) + matchingAlias = alias; + } + + input = input.Substring(matchingAlias.Length); + + return await CommandParser.ParseArgs(this, msg, input, 0).ConfigureAwait(false); } public Task Execute(IMessage msg, ParseResult parseResult) { diff --git a/src/Discord.Net.Commands/Map/CommandMap.cs b/src/Discord.Net.Commands/Map/CommandMap.cs index 98ff297b0..ac0a4b7fc 100644 --- a/src/Discord.Net.Commands/Map/CommandMap.cs +++ b/src/Discord.Net.Commands/Map/CommandMap.cs @@ -17,19 +17,21 @@ namespace Discord.Commands public void AddCommand(Command command) { - string text = command.Text; - int nextSpace = NextWhitespace(text); - string name; + foreach (string text in command.Aliases) + { + int nextSpace = NextWhitespace(text); + string name; - if (nextSpace == -1) - name = command.Text; - else - name = command.Text.Substring(0, nextSpace); + if (nextSpace == -1) + name = command.Text; + else + name = command.Text.Substring(0, nextSpace); - lock (this) - { - var nextNode = _nodes.GetOrAdd(name, x => new CommandMapNode(x)); - nextNode.AddCommand(nextSpace == -1 ? "" : text, nextSpace + 1, command); + lock (this) + { + var nextNode = _nodes.GetOrAdd(name, x => new CommandMapNode(x)); + nextNode.AddCommand(nextSpace == -1 ? "" : text, nextSpace + 1, command); + } } } public void RemoveCommand(Command command) From 94dc123e8d6d16d05ffeb4964933f5e2ff02f750 Mon Sep 17 00:00:00 2001 From: FiniteReality Date: Sat, 27 Aug 2016 19:44:53 +0100 Subject: [PATCH 2/2] Use aliases while removing from the CommandMap --- src/Discord.Net.Commands/Map/CommandMap.cs | 30 ++++++++++++---------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/Discord.Net.Commands/Map/CommandMap.cs b/src/Discord.Net.Commands/Map/CommandMap.cs index ac0a4b7fc..f75a0f12f 100644 --- a/src/Discord.Net.Commands/Map/CommandMap.cs +++ b/src/Discord.Net.Commands/Map/CommandMap.cs @@ -36,23 +36,25 @@ namespace Discord.Commands } public void RemoveCommand(Command command) { - string text = command.Text; - int nextSpace = NextWhitespace(text); - string name; + foreach (string text in command.Aliases) + { + int nextSpace = NextWhitespace(text); + string name; - if (nextSpace == -1) - name = command.Text; - else - name = command.Text.Substring(0, nextSpace); + if (nextSpace == -1) + name = command.Text; + else + name = command.Text.Substring(0, nextSpace); - lock (this) - { - CommandMapNode nextNode; - if (_nodes.TryGetValue(name, out nextNode)) + lock (this) { - nextNode.AddCommand(nextSpace == -1 ? "" : text, nextSpace + 1, command); - if (nextNode.IsEmpty) - _nodes.TryRemove(name, out nextNode); + CommandMapNode nextNode; + if (_nodes.TryGetValue(name, out nextNode)) + { + nextNode.RemoveCommand(nextSpace == -1 ? "" : text, nextSpace + 1, command); + if (nextNode.IsEmpty) + _nodes.TryRemove(name, out nextNode); + } } } }