diff --git a/SabreTools.CommandLine.Test/CommandSetTests.cs b/SabreTools.CommandLine.Test/CommandSetTests.cs index 8760c12..0f0ab01 100644 --- a/SabreTools.CommandLine.Test/CommandSetTests.cs +++ b/SabreTools.CommandLine.Test/CommandSetTests.cs @@ -148,6 +148,63 @@ namespace SabreTools.CommandLine.Test #endregion + #region GetFeature + + [Fact] + public void GetFeature_InvalidKey_Null() + { + var commandSet = new CommandSet(); + var child = new MockFeature("b", "b", "b"); + commandSet.Add(child); + + Feature? actual = commandSet.GetFeature("c"); + Assert.Null(actual); + } + + [Fact] + public void GetFeature_Exists_WrongType_Throws() + { + var commandSet = new CommandSet(); + var child = new MockUserInput("b", "b", "b"); + commandSet.Add(child); + + Assert.Throws(() => _ = commandSet.GetFeature("b")); + } + + [Fact] + public void GetFeature_Exists_Returns() + { + var commandSet = new CommandSet(); + var child = new MockFeature("b", "b", "b"); + commandSet.Add(child); + + int index = 0; + child.ProcessInput(["b"], ref index); + + Feature? actual = commandSet.GetFeature("b"); + Assert.NotNull(actual); + Assert.Equal("b", actual.Name); + Assert.True(actual.Value); + } + + [Fact] + public void GetFeature_NestedExists_Null() + { + var commandSet = new CommandSet(); + var child = new MockUserInput("b", "b", "b"); + commandSet.Add(child); + var subChild = new MockFeature("c", "c", "c"); + child.Add(subChild); + + int index = 0; + subChild.ProcessInput(["c"], ref index); + + Feature? actual = commandSet.GetFeature("c"); + Assert.Null(actual); + } + + #endregion + #region GetInt8 [Fact] @@ -700,6 +757,28 @@ namespace SabreTools.CommandLine.Test #endregion + /// + /// Mock Feature implementation for testing + /// + private class MockFeature : Feature + { + public MockFeature(string name, string flag, string description, string? detailed = null) + : base(name, flag, description, detailed) + { + } + + public MockFeature(string name, string[] flags, string description, string? detailed = null) + : base(name, flags, description, detailed) + { + } + + /// + public override bool Execute() => true; + + /// + public override bool VerifyInputs() => true; + } + /// /// Mock UserInput implementation for testing /// diff --git a/SabreTools.CommandLine/CommandSet.cs b/SabreTools.CommandLine/CommandSet.cs index 558c585..4fb4047 100644 --- a/SabreTools.CommandLine/CommandSet.cs +++ b/SabreTools.CommandLine/CommandSet.cs @@ -117,7 +117,20 @@ namespace SabreTools.CommandLine return defaultValue; } - /// + /// + /// Get a Feature value from a named input + /// + /// Input name to retrieve, if possible + /// The value if found, null otherwise + public Feature? GetFeature(string key) + { + if (TryGetFeature(key, out Feature? value)) + return value; + + return null; + } + + /// /// Get an Int8 value from a named input /// /// Input name to retrieve, if possible @@ -280,7 +293,7 @@ namespace SabreTools.CommandLine return true; } - throw new ArgumentException("Feature is not a bool"); + throw new ArgumentException("Input is not a bool"); } // Check all children recursively @@ -294,6 +307,29 @@ namespace SabreTools.CommandLine return false; } + /// + /// Get a Feature value from a named input + /// + /// Input name to retrieve, if possible + /// Value that was found, default value otherwise + /// True if the value was found, false otherwise + public bool TryGetFeature(string key, out Feature? value) + { + // Try to check immediate children + if (_inputs.TryGetValue(key, out var input)) + { + if (input is not Feature i) + throw new ArgumentException("Input is not a Feature"); + + value = i; + return true; + } + + // TODO: Investigate if nested features should be supported + value = null; + return false; + } + /// /// Get an Int8 value from a named input /// @@ -307,7 +343,7 @@ namespace SabreTools.CommandLine if (_inputs.TryGetValue(key, out var input)) { if (input is not Int8Input i) - throw new ArgumentException("Feature is not an sbyte"); + throw new ArgumentException("Input is not an sbyte"); value = i.Value ?? defaultValue; return true; @@ -337,7 +373,7 @@ namespace SabreTools.CommandLine if (_inputs.TryGetValue(key, out var input)) { if (input is not Int16Input i) - throw new ArgumentException("Feature is not a short"); + throw new ArgumentException("Input is not a short"); value = i.Value ?? defaultValue; return true; @@ -367,7 +403,7 @@ namespace SabreTools.CommandLine if (_inputs.TryGetValue(key, out var input)) { if (input is not Int32Input i) - throw new ArgumentException("Feature is not an int"); + throw new ArgumentException("Input is not an int"); value = i.Value ?? defaultValue; return true; @@ -397,7 +433,7 @@ namespace SabreTools.CommandLine if (_inputs.TryGetValue(key, out var input)) { if (input is not Int64Input l) - throw new ArgumentException("Feature is not a long"); + throw new ArgumentException("Input is not a long"); value = l.Value ?? defaultValue; return true; @@ -427,7 +463,7 @@ namespace SabreTools.CommandLine if (_inputs.TryGetValue(key, out var input)) { if (input is not StringInput s) - throw new ArgumentException("Feature is not a string"); + throw new ArgumentException("Input is not a string"); value = s.Value ?? defaultValue; return true; @@ -456,7 +492,7 @@ namespace SabreTools.CommandLine if (_inputs.TryGetValue(key, out var input)) { if (input is not StringListInput l) - throw new ArgumentException("Feature is not a list"); + throw new ArgumentException("Input is not a list"); value = l.Value ?? []; return true; @@ -486,7 +522,7 @@ namespace SabreTools.CommandLine if (_inputs.TryGetValue(key, out var input)) { if (input is not UInt8Input i) - throw new ArgumentException("Feature is not an byte"); + throw new ArgumentException("Input is not an byte"); value = i.Value ?? defaultValue; return true; @@ -516,7 +552,7 @@ namespace SabreTools.CommandLine if (_inputs.TryGetValue(key, out var input)) { if (input is not UInt16Input i) - throw new ArgumentException("Feature is not a ushort"); + throw new ArgumentException("Input is not a ushort"); value = i.Value ?? defaultValue; return true; @@ -546,7 +582,7 @@ namespace SabreTools.CommandLine if (_inputs.TryGetValue(key, out var input)) { if (input is not UInt32Input i) - throw new ArgumentException("Feature is not an uint"); + throw new ArgumentException("Input is not an uint"); value = i.Value ?? defaultValue; return true; @@ -576,7 +612,7 @@ namespace SabreTools.CommandLine if (_inputs.TryGetValue(key, out var input)) { if (input is not UInt64Input l) - throw new ArgumentException("Feature is not a ulong"); + throw new ArgumentException("Input is not a ulong"); value = l.Value ?? defaultValue; return true; diff --git a/SabreTools.CommandLine/Inputs/UserInput.cs b/SabreTools.CommandLine/Inputs/UserInput.cs index e0e7223..f4f5d06 100644 --- a/SabreTools.CommandLine/Inputs/UserInput.cs +++ b/SabreTools.CommandLine/Inputs/UserInput.cs @@ -298,7 +298,7 @@ namespace SabreTools.CommandLine.Inputs return true; } - throw new ArgumentException("Feature is not a bool"); + throw new ArgumentException("Input is not a bool"); } // Check all children recursively @@ -325,7 +325,7 @@ namespace SabreTools.CommandLine.Inputs if (Children.TryGetValue(key, out var input)) { if (input is not Int8Input i) - throw new ArgumentException("Feature is not an sbyte"); + throw new ArgumentException("Input is not an sbyte"); value = i.Value ?? defaultValue; return true; @@ -355,7 +355,7 @@ namespace SabreTools.CommandLine.Inputs if (Children.TryGetValue(key, out var input)) { if (input is not Int16Input i) - throw new ArgumentException("Feature is not a short"); + throw new ArgumentException("Input is not a short"); value = i.Value ?? defaultValue; return true; @@ -385,7 +385,7 @@ namespace SabreTools.CommandLine.Inputs if (Children.TryGetValue(key, out var input)) { if (input is not Int32Input i) - throw new ArgumentException("Feature is not an int"); + throw new ArgumentException("Input is not an int"); value = i.Value ?? defaultValue; return true; @@ -415,7 +415,7 @@ namespace SabreTools.CommandLine.Inputs if (Children.TryGetValue(key, out var input)) { if (input is not Int64Input l) - throw new ArgumentException("Feature is not a long"); + throw new ArgumentException("Input is not a long"); value = l.Value ?? defaultValue; return true; @@ -445,7 +445,7 @@ namespace SabreTools.CommandLine.Inputs if (Children.TryGetValue(key, out var input)) { if (input is not StringInput s) - throw new ArgumentException("Feature is not a string"); + throw new ArgumentException("Input is not a string"); value = s.Value ?? defaultValue; return true; @@ -474,7 +474,7 @@ namespace SabreTools.CommandLine.Inputs if (Children.TryGetValue(key, out var input)) { if (input is not StringListInput l) - throw new ArgumentException("Feature is not a list"); + throw new ArgumentException("Input is not a list"); value = l.Value ?? []; return true; @@ -504,7 +504,7 @@ namespace SabreTools.CommandLine.Inputs if (Children.TryGetValue(key, out var input)) { if (input is not UInt8Input i) - throw new ArgumentException("Feature is not an byte"); + throw new ArgumentException("Input is not an byte"); value = i.Value ?? defaultValue; return true; @@ -534,7 +534,7 @@ namespace SabreTools.CommandLine.Inputs if (Children.TryGetValue(key, out var input)) { if (input is not UInt16Input i) - throw new ArgumentException("Feature is not a ushort"); + throw new ArgumentException("Input is not a ushort"); value = i.Value ?? defaultValue; return true; @@ -564,7 +564,7 @@ namespace SabreTools.CommandLine.Inputs if (Children.TryGetValue(key, out var input)) { if (input is not UInt32Input i) - throw new ArgumentException("Feature is not an uint"); + throw new ArgumentException("Input is not an uint"); value = i.Value ?? defaultValue; return true; @@ -594,7 +594,7 @@ namespace SabreTools.CommandLine.Inputs if (Children.TryGetValue(key, out var input)) { if (input is not UInt64Input l) - throw new ArgumentException("Feature is not a ulong"); + throw new ArgumentException("Input is not a ulong"); value = l.Value ?? defaultValue; return true;