@@ -1,4 +1,5 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Collections.Immutable; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
@@ -14,19 +15,32 @@ namespace Discord.Commands | |||
QuotedParameter | |||
} | |||
/// <summary> | |||
/// Checks to see if the supplied character is a quotation mark | |||
/// from either the default " character, or the list of aliases | |||
/// if they are provided. | |||
/// </summary> | |||
/// <param name="c"></param> | |||
/// <param name="aliases"></param> | |||
private static bool isQuotationChar(char c, char[] aliases) | |||
private static bool isOpenQuote(Dictionary<char,char> map, char c) | |||
{ | |||
if (aliases == null) return c == '\"'; | |||
return Array.Exists(aliases, x => x == c); | |||
// determine if the map contains the key for this value | |||
if(map != null) | |||
{ | |||
return map.ContainsKey(c); | |||
} | |||
// or if the value is a normal quote " | |||
return c == '\"'; | |||
} | |||
// get the corresponding matching quote for the key | |||
private static char getMatch(Dictionary<char,char> map, char c) | |||
{ | |||
if (map != null) | |||
{ | |||
char value; | |||
if( map.TryGetValue(c, out value)) | |||
{ | |||
return value; | |||
} | |||
} | |||
return '\"'; | |||
} | |||
public static async Task<ParseResult> ParseArgsAsync(CommandInfo command, ICommandContext context, bool ignoreExtraArgs, IServiceProvider services, string input, int startPos) | |||
{ | |||
ParameterInfo curParam = null; | |||
@@ -37,7 +51,7 @@ namespace Discord.Commands | |||
var argList = ImmutableArray.CreateBuilder<TypeReaderResult>(); | |||
var paramList = ImmutableArray.CreateBuilder<TypeReaderResult>(); | |||
bool isEscaping = false; | |||
char c; | |||
char c, matchQuote = '\0'; | |||
for (int curPos = startPos; curPos <= endPos; curPos++) | |||
{ | |||
@@ -87,9 +101,11 @@ namespace Discord.Commands | |||
argBuilder.Append(c); | |||
continue; | |||
} | |||
if (isQuotationChar(c, command._quotationAliases)) | |||
if(isOpenQuote(command._quotationAliases, c)) | |||
{ | |||
curPart = ParserPart.QuotedParameter; | |||
matchQuote = getMatch(command._quotationAliases, c); | |||
continue; | |||
} | |||
curPart = ParserPart.Parameter; | |||
@@ -110,7 +126,9 @@ namespace Discord.Commands | |||
} | |||
else if (curPart == ParserPart.QuotedParameter) | |||
{ | |||
if (isQuotationChar(c, command._quotationAliases)) | |||
//if (findQuotationChar(c, false, out matchingQuotation)) | |||
//if( matchingQuotation != null && matchingQuotation.Right == c) | |||
if(c == matchQuote) | |||
{ | |||
argString = argBuilder.ToString(); //Remove quotes | |||
lastArgEndPos = curPos + 1; | |||
@@ -32,7 +32,7 @@ namespace Discord.Commands | |||
internal readonly RunMode _defaultRunMode; | |||
internal readonly Logger _cmdLogger; | |||
internal readonly LogManager _logManager; | |||
internal readonly char[] _quotationMarkAliases; | |||
internal readonly Dictionary<char, char> _quotationMarkAliasMap; | |||
public IEnumerable<ModuleInfo> Modules => _moduleDefs.Select(x => x); | |||
public IEnumerable<CommandInfo> Commands => _moduleDefs.SelectMany(x => x.Commands); | |||
@@ -46,7 +46,7 @@ namespace Discord.Commands | |||
_ignoreExtraArgs = config.IgnoreExtraArgs; | |||
_separatorChar = config.SeparatorChar; | |||
_defaultRunMode = config.DefaultRunMode; | |||
_quotationMarkAliases = config.QuotationMarkAliases; | |||
_quotationMarkAliasMap = config.QuotationMarkAliasMap; | |||
if (_defaultRunMode == RunMode.Default) | |||
throw new InvalidOperationException("The default run mode cannot be set to Default."); | |||
@@ -1,4 +1,5 @@ | |||
namespace Discord.Commands | |||
using System.Collections.Generic; | |||
namespace Discord.Commands | |||
{ | |||
public class CommandServiceConfig | |||
{ | |||
@@ -16,8 +17,29 @@ | |||
/// <summary> Determines whether RunMode.Sync commands should push exceptions up to the caller. </summary> | |||
public bool ThrowOnError { get; set; } = true; | |||
/// <summary> List of aliases for string parsing </summary> | |||
public char[] QuotationMarkAliases { get; set; } = new char[] { '\"', '“', '”', '«', '»', '‹', '›' }; | |||
/// <summary> Collection of aliases that can wrap strings for command parsing. | |||
/// represents the opening quotation mark and the value is the corresponding closing mark.</summary> | |||
public Dictionary<char, char> QuotationMarkAliasMap { get; set; } | |||
= new Dictionary<char, char>() | |||
{ | |||
{'\"', '\"' }, | |||
{'«', '»' }, | |||
{'‘', '’' }, | |||
{'“', '”' }, | |||
{'„', '‟' }, | |||
{'‹', '›' }, | |||
{'‚', '‛' }, | |||
{'《', '》' }, | |||
{'〈', '〉' }, | |||
{'「', '」' }, | |||
{'『', '』' }, | |||
{'〝', '〞' }, | |||
{'﹁', '﹂' }, | |||
{'﹃', '﹄' }, | |||
{'"', '"' }, | |||
{''', ''' }, | |||
{'「', '」' } | |||
}; | |||
/// <summary> Determines whether extra parameters should be ignored. </summary> | |||
public bool IgnoreExtraArgs { get; set; } = false; | |||
@@ -20,7 +20,7 @@ namespace Discord.Commands | |||
private readonly CommandService _commandService; | |||
private readonly Func<ICommandContext, object[], IServiceProvider, CommandInfo, Task> _action; | |||
internal readonly char[] _quotationAliases; | |||
internal readonly Dictionary<char,char> _quotationAliases; | |||
public ModuleInfo Module { get; } | |||
public string Name { get; } | |||
@@ -66,7 +66,7 @@ namespace Discord.Commands | |||
HasVarArgs = builder.Parameters.Count > 0 ? builder.Parameters[builder.Parameters.Count - 1].IsMultiple : false; | |||
_action = builder.Callback; | |||
_quotationAliases = service._quotationMarkAliases; | |||
_quotationAliases = service._quotationMarkAliasMap; | |||
_commandService = service; | |||
} | |||