-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathCommandParser.cs
More file actions
107 lines (94 loc) · 3.87 KB
/
CommandParser.cs
File metadata and controls
107 lines (94 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
using System.Collections.Generic;
namespace DevChatter.Bot.Core.Util
{
public static class CommandParser
{
public static (string commandWord, List<string> arguments) Parse(string commandString, int startIndex = 0)
{
if (startIndex < 0 || string.IsNullOrWhiteSpace(commandString))
{
return (string.Empty, new List<string>());
}
int commandWordEndIndex = commandString.IndexOf(' ', startIndex);
if (commandWordEndIndex == -1)
{
commandWordEndIndex = commandString.Length - 1;
}
int commandWordLength = commandWordEndIndex - startIndex + 1;
string commandWord = commandString.Substring(startIndex, commandWordLength).Trim();
if (commandWordEndIndex == commandString.Length - 1)
{
// return early because we have no arguments
return (commandWord, new List<string>());
}
string remainingCommand = commandString.Substring(commandWordLength).Trim();
var arguments = SplitArguments(remainingCommand);
return (commandWord, arguments);
}
private static List<string> SplitArguments(string arguments)
{
const char argumentDelimiter = ' ';
const char quoteCharacter = '"';
if (string.IsNullOrWhiteSpace(arguments))
return new List<string>();
List<string> splitArguments = new List<string>();
bool wasInQuotedSection = false;
bool inQuotedSection = false;
int argumentStart = -1;
for (int i = 0; i < arguments.Length; ++i)
{
if (arguments[i] == quoteCharacter)
{
if (!inQuotedSection)
{
if (i == 0 || arguments[i - 1] == argumentDelimiter)
{
inQuotedSection = true;
wasInQuotedSection = false;
}
}
else
{
if (i == arguments.Length - 1 || arguments[i + 1] == argumentDelimiter)
{
wasInQuotedSection = true;
inQuotedSection = false;
}
}
}
else if(arguments[i] == argumentDelimiter && !inQuotedSection)
{
int argumentLength = i - argumentStart;
if (wasInQuotedSection)
{
// If we were previously in a quoted section we
// need to offset our length by -1 otherwise we get the closing quote
argumentLength -= 1;
}
var argument = arguments.Substring(argumentStart, argumentLength);
splitArguments.Add(argument);
argumentStart = -1;
wasInQuotedSection = false;
inQuotedSection = false;
}
else if(arguments[i] != argumentDelimiter && argumentStart == -1)
{
// we only want to record the start index
// if the current character is NOT the delimiter
argumentStart = i;
}
}
if(argumentStart != -1)
{
int argumentLength = arguments.Length - argumentStart;
if(wasInQuotedSection)
{
argumentLength -= 1;
}
var argument = arguments.Substring(argumentStart, argumentLength);
splitArguments.Add(argument);
}
return splitArguments;
}
}
}