-
-
Notifications
You must be signed in to change notification settings - Fork 37
/
InputParser.cs
139 lines (112 loc) · 4.52 KB
/
InputParser.cs
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Baseline;
using Baseline.Conversion;
using Baseline.Reflection;
namespace Oakton.Parsing
{
public static class InputParser
{
private static readonly string LONG_FLAG_PREFIX = "--";
private static readonly Regex LONG_FLAG_REGEX = new Regex("^{0}[^-]+".ToFormat(LONG_FLAG_PREFIX));
private static readonly string SHORT_FLAG_PREFIX = "-";
private static readonly Regex SHORT_FLAG_REGEX = new Regex("^{0}[^-]+".ToFormat(SHORT_FLAG_PREFIX));
private static readonly string FLAG_SUFFIX = "Flag";
private static readonly Conversions _converter = new Conversions();
public static List<ITokenHandler> GetHandlers(Type inputType)
{
var properties = inputType.GetProperties().Where(prop => prop.CanWrite);
var fields = inputType.GetFields(BindingFlags.Public | BindingFlags.Instance);
var members = properties.OfType<MemberInfo>().Concat(fields);
return members
.Where(member => !member.HasAttribute<IgnoreOnCommandLineAttribute>())
.Select(BuildHandler).ToList();
}
public static ITokenHandler BuildHandler(MemberInfo member)
{
var memberType = member.GetMemberType();
if (!member.Name.EndsWith(FLAG_SUFFIX))
{
if (memberType.CanBeCastTo<IDictionary<string, string>>())
{
throw new ArgumentOutOfRangeException("Dictionaries are only supported as 'Flag' members");
}
if (memberType != typeof (string) && memberType.Closes(typeof (IEnumerable<>)))
{
return new EnumerableArgument(member, _converter);
}
return new Argument(member, _converter);
}
// Gotta check this before enumerable!
if (memberType.CanBeCastTo<IDictionary<string, string>>())
{
return new DictionaryFlag(member);
}
if (memberType != typeof(string) && memberType.Closes(typeof(IEnumerable<>)))
{
return new EnumerableFlag(member, _converter);
}
if (memberType == typeof(bool))
{
return new BooleanFlag(member);
}
return new Flag(member, _converter);
}
public static bool IsFlag(string token)
{
return IsShortFlag(token) || IsLongFlag(token);
}
public static bool IsShortFlag(string token)
{
return SHORT_FLAG_REGEX.IsMatch(token);
}
public static bool IsLongFlag(string token)
{
return LONG_FLAG_REGEX.IsMatch(token);
}
public static bool IsFlagFor(string token, MemberInfo property)
{
return ToFlagAliases(property).Matches(token);
}
public static FlagAliases ToFlagAliases(MemberInfo member)
{
var name = RemoveFlagSuffix(member.Name);
name = splitOnPascalCaseAndAddHyphens(name);
var oneLetterName = name.ToLower()[0];
var longFormOnly = false;
member.ForAttribute<FlagAliasAttribute>(att =>
{
name = att.LongAlias ?? name;
oneLetterName = att.OneLetterAlias ?? oneLetterName;
longFormOnly = att.LongAliasOnly;
});
return new FlagAliases
{
ShortForm = (SHORT_FLAG_PREFIX + oneLetterName),
LongForm = LONG_FLAG_PREFIX + name.ToLower(),
LongFormOnly = longFormOnly
};
}
public static string RemoveFlagSuffix(string fullFlagName)
{
var suffixLength = FLAG_SUFFIX.Length;
var shouldBeRemoved = fullFlagName.ToLower().EndsWith(FLAG_SUFFIX.ToLower())
&& fullFlagName.Length > suffixLength;
if (shouldBeRemoved)
{
return fullFlagName.Substring(0, fullFlagName.Length - suffixLength);
}
else
{
return fullFlagName;
}
}
private static string splitOnPascalCaseAndAddHyphens(string name)
{
return name.SplitPascalCase().Split(' ').Join("-");
}
}
}