Skip to content

Commit

Permalink
Support typed options
Browse files Browse the repository at this point in the history
  • Loading branch information
kcartlidge committed Nov 2, 2020
1 parent c290d72 commit 7b03f38
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 1 deletion.
43 changes: 43 additions & 0 deletions ArgsParser.Tests/ArgsParserTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NUnit.Framework;
using System;
using System.Linq;

namespace ArgsParser.Tests
Expand Down Expand Up @@ -138,6 +139,48 @@ public void ComplexOptionsAndFlags_ConditionsMet_HasNoErrors()
Assert.IsEmpty(result.Errors);
}

[Test]
public void OptionsWithTypes_ValuesCannotBeConverted_HasErrors()
{
var parser = new ArgsParser(new string[] { "-dtm", "a", "-f", "b" })
.RequiresOption<DateTime>("dtm", "A datetime value")
.RequiresOption<float>("f", "A float value");

var result = parser.Parse();

Assert.AreEqual(2, result.Errors.Count);
Assert.Contains("dtm", result.Errors.Keys.ToList());
StringAssert.Contains("value of type", result.Errors["dtm"].First());
Assert.Contains("f", result.Errors.Keys.ToList());
StringAssert.Contains("value of type", result.Errors["f"].First());
}

[Test]
public void OptionsWithTypes_TypeConversionOccurs()
{
var parser = new ArgsParser(new string[] {
"-s", "a", "-i", "1", "-n", "1.2", "-d", "2020-10-03", "-b", "true" })
.RequiresOption<string>("s", "A string value")
.RequiresOption<int>("i", "An integer value")
.RequiresOption<decimal>("n", "A numeric value")
.RequiresOption<DateTime>("d", "A datetime value")
.RequiresOption<bool>("b", "A boolean value");

var result = parser.Parse();

Assert.IsEmpty(result.Errors);
Assert.IsInstanceOf<string>(result.ParsedOptions["s"]);
Assert.IsInstanceOf<int>(result.ParsedOptions["i"]);
Assert.IsInstanceOf<decimal>(result.ParsedOptions["n"]);
Assert.IsInstanceOf<DateTime>(result.ParsedOptions["d"]);
Assert.IsInstanceOf<bool>(result.ParsedOptions["b"]);
Assert.AreEqual("a", result.ParsedOptions["s"]);
Assert.AreEqual(1, result.ParsedOptions["i"]);
Assert.AreEqual(1.2D, result.ParsedOptions["n"]);
Assert.AreEqual(new DateTime(2020, 10, 3), result.ParsedOptions["d"]);
Assert.AreEqual(true, result.ParsedOptions["b"]);
}

[Test]
public void UnexpectedValueProvided_HasErrors()
{
Expand Down
17 changes: 16 additions & 1 deletion ArgsParser/ArgsParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace ArgsParser
public class ArgsParser
{
public List<string> ParsedFlags = new List<string>();
public SortedList<string, string> ParsedOptions = new SortedList<string, string>();
public SortedList<string, object> ParsedOptions = new SortedList<string, object>();
public bool HasErrors { get => Errors.Any(); }
public SortedList<string, List<string>> Errors = new SortedList<string, List<string>>();

Expand Down Expand Up @@ -68,6 +68,7 @@ public ArgsParser Help()
public ArgsParser Parse()
{
// Extract all the flags and options.
// In this initial splitting process, all option values are treated as strings.
var currentName = (string)null;
foreach (var arg in RawArgs)
{
Expand Down Expand Up @@ -121,6 +122,20 @@ public ArgsParser Parse()
if (currentName != null)
ParsedFlags.Add(currentName.ToLower());

// Convert any non-string options.
foreach (var option in Options.Where(x => x.Value.ArgType != typeof(string)))
if (ParsedOptions.ContainsKey(option.Key))
{
try
{
ParsedOptions[option.Key] = Convert.ChangeType(ParsedOptions[option.Key], option.Value.ArgType);
}
catch
{
AddError(option.Key, $"Expected a value of type {option.Value.ArgType}: {option.Key}");
}
}

// Enforce any options requirements.
// No required flags, as that would force the value to always be true.
foreach (var option in Options.Where(x => x.Value.IsRequired))
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
- And tests
- Add `ArgsParser` class
- And tests
- Support typed options
- Converts where possible
- Else returns as strings

0 comments on commit 7b03f38

Please sign in to comment.