Browse Source

change quotation mark parsing to use a map of matching pairs

pull/943/head
Chris Johnston 7 years ago
parent
commit
3e54e6fa04
4 changed files with 61 additions and 21 deletions
  1. +32
    -14
      src/Discord.Net.Commands/CommandParser.cs
  2. +2
    -2
      src/Discord.Net.Commands/CommandService.cs
  3. +25
    -3
      src/Discord.Net.Commands/CommandServiceConfig.cs
  4. +2
    -2
      src/Discord.Net.Commands/Info/CommandInfo.cs

+ 32
- 14
src/Discord.Net.Commands/CommandParser.cs View File

@@ -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;


+ 2
- 2
src/Discord.Net.Commands/CommandService.cs View File

@@ -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.");



+ 25
- 3
src/Discord.Net.Commands/CommandServiceConfig.cs View File

@@ -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;


+ 2
- 2
src/Discord.Net.Commands/Info/CommandInfo.cs View File

@@ -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;
}



Loading…
Cancel
Save