mirror of
https://github.com/SabreTools/SabreTools.CommandLine.git
synced 2026-02-04 05:36:02 +00:00
Split code from SabreTools
This commit is contained in:
40
.github/workflows/build_and_test.yml
vendored
Normal file
40
.github/workflows/build_and_test.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
name: Build and Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: |
|
||||
6.0.x
|
||||
8.0.x
|
||||
9.0.x
|
||||
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
|
||||
- name: Run publish script
|
||||
run: ./publish-nix.sh
|
||||
|
||||
- name: Upload to rolling
|
||||
uses: ncipollo/release-action@v1.14.0
|
||||
with:
|
||||
allowUpdates: True
|
||||
artifacts: "*.nupkg,*.snupkg"
|
||||
body: 'Last built commit: ${{ github.sha }}'
|
||||
name: 'Rolling Release'
|
||||
prerelease: True
|
||||
replacesArtifacts: True
|
||||
tag: "rolling"
|
||||
updateOnlyUnreleased: True
|
||||
23
.github/workflows/check_pr.yml
vendored
Normal file
23
.github/workflows/check_pr.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: Build PR
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: |
|
||||
6.0.x
|
||||
8.0.x
|
||||
9.0.x
|
||||
|
||||
- name: Build
|
||||
run: dotnet build
|
||||
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
*.swp
|
||||
*.*~
|
||||
project.lock.json
|
||||
.DS_Store
|
||||
*.pyc
|
||||
nupkg/
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode
|
||||
|
||||
# Rider
|
||||
.idea
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
build/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Oo]ut/
|
||||
msbuild.log
|
||||
msbuild.err
|
||||
msbuild.wrn
|
||||
|
||||
# Visual Studio 2015
|
||||
.vs/
|
||||
|
||||
7
LICENSE
Executable file
7
LICENSE
Executable file
@@ -0,0 +1,7 @@
|
||||
Copyright (c) 2016-2025 Matt Nadareski
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
64
README.MD
Normal file
64
README.MD
Normal file
@@ -0,0 +1,64 @@
|
||||
# SabreTools.CommandLine
|
||||
|
||||
This library contains logic to both parse commandlines using typed inputs as well as format and output help text. Formatting and output is context-aware, allowing for different behavior if console outputs are redirected.
|
||||
|
||||
All inputs allow for non-flag inputs in both `a=b` and `a b` formats. This allows for greater flexibility for cross-platform support. Flags for each input are fully defined by the implementer, so inputs of the form `-a`, `--a`, `/a`, and `a` are all accepted and can even be mixed. The only restriction is that flags should not end with the `=` character as it may interfere with default parsing.
|
||||
|
||||
For an example of a program implementing the library, see [SabreTools](https://github.com/SabreTools/SabreTools).
|
||||
|
||||
## Special Types
|
||||
|
||||
Included in the library are a few special classes that make up the core of the functionality. Each work a different layers of implementation and can be used in combination with each other. For more details on their language construct equivalents and longer descriptions, see the table and sections below.
|
||||
|
||||
| Class | Language Construct |
|
||||
| --- | --- |
|
||||
| `CommandSet` | Vocabulary |
|
||||
| `Feature` | Verb |
|
||||
| `Inputs.UserInput` | Noun |
|
||||
|
||||
### `CommandSet`
|
||||
|
||||
Represents a logically-grouped set of functionality, usually scoped to an application. Inputs defined in a command set do not need to be any specific type, but using `Feature` is recommended. `CommandSet` also allows implementers to easily print help text to the screen.
|
||||
|
||||
An example of a command set would be including `Program.exe feature1` and `Program.exe feature2`as top-level pieces of functionality. This can allow implementers to have multiple command sets that depend on execution environment or even other commandline arguments. In single-operation or single-set programs, this can represent the default state of the program internally.
|
||||
|
||||
### `Feature`
|
||||
|
||||
Represents an application-level feature that may have its own custom set of supported inputs. Features can also allow for internal processing if preferred by the implementer. A default implementation of argument parsing is included but can be overridden by any implementing class. It is recommended but not required to include defined features in a `CommandSet` to allow for better flexibility.
|
||||
|
||||
An example of a Feature would be something like `Program.exe featurename` where it represents a single type of operation that can be done. In single-operation programs, this can represent the default state of the program internally without needing an external name.
|
||||
|
||||
### `Inputs.UserInput`
|
||||
|
||||
Base class used for all supported input classes. Both typed and untyped variants exist. This can be used to define custom input classes for any type, including types already defined by one of the default included classes. The typed version of the base class is recommended, but not mandatory.
|
||||
|
||||
`Get` and `TryGet` methods are included to make finding values from child items easier. If new input types are defined by the implementer, it is recommended that extension methods are created to include this functionality.
|
||||
|
||||
## Supported Input Formats
|
||||
|
||||
Below is a mapping from default supported types to their respective class names in `SabreTools.CommandLine.Inputs`.
|
||||
|
||||
| Type | Class | Notes |
|
||||
| --- | --- | --- |
|
||||
| `bool` | `BooleanInput` | Requires either `true` or `false` as the value, e.g. `--flag=true` |
|
||||
| `bool` | `FlagInput` | Inclusion of this indicates a `true` value, e.g. `--flag` |
|
||||
| `sbyte` | `Int8Input` | Numeric input bounded to `sbyte.MinValue` to `sbyte.MaxValue`, inclusive |
|
||||
| `short` | `Int16Input` | Numeric input bounded to `short.MinValue` to `short.MaxValue`, inclusive |
|
||||
| `int` | `Int32Input` | Numeric input bounded to `int.MinValue` to `int.MaxValue`, inclusive |
|
||||
| `long` | `Int64Input` | Numeric input bounded to `long.MinValue` to `long.MaxValue`, inclusive |
|
||||
| `string?` | `StringInput` | Non-repeating generic string input; may be empty |
|
||||
| `List<string>` | `StringListInput` | Repeating generic string input; may be empty |
|
||||
| `byte` | `UInt8Input` | Numeric input bounded to `byte.MinValue` to `byte.MaxValue`, inclusive |
|
||||
| `ushort` | `UInt16Input` | Numeric input bounded to `ushort.MinValue` to `ushort.MaxValue`, inclusive |
|
||||
| `uint` | `UInt32Input` | Numeric input bounded to `uint.MinValue` to `uint.MaxValue`, inclusive |
|
||||
| `ulong` | `UInt64Input` | Numeric input bounded to `ulong.MinValue` to `ulong.MaxValue`, inclusive |
|
||||
|
||||
## Reference Implementations
|
||||
|
||||
Three reference feature implementations are included for common cases. They are defined in the table below.
|
||||
|
||||
| Class | Description |
|
||||
| --- | --- |
|
||||
| `DefaultHelp` | Outputs either a generic help text or one specific to a feature name included as the second argument |
|
||||
| `DefaultHelpExtended` | Outputs either a generic help text with extended descriptions or one specific to a feature name included as the second argument |
|
||||
| `DefaultVersion` | Outputs the version number of the program, derived from the informational version |
|
||||
72
SabreTools.CommandLine.Test/CommandSetTests.cs
Normal file
72
SabreTools.CommandLine.Test/CommandSetTests.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test
|
||||
{
|
||||
public class CommandSetTests
|
||||
{
|
||||
[Fact]
|
||||
public void AddAndRetrieveTest()
|
||||
{
|
||||
var input1 = new FlagInput("input1", "--input1", "input1");
|
||||
var input2 = new FlagInput("input2", "--input2", "input2");
|
||||
|
||||
var featureSet = new CommandSet();
|
||||
featureSet.Add(input1);
|
||||
featureSet.Add(input2);
|
||||
|
||||
var actualInput1 = featureSet["input1"];
|
||||
Assert.NotNull(actualInput1);
|
||||
Assert.Equal("input1", actualInput1.Name);
|
||||
|
||||
var actualInput2 = featureSet[input2];
|
||||
Assert.NotNull(actualInput2);
|
||||
Assert.Equal("input2", actualInput2.Name);
|
||||
|
||||
var actualInput3 = featureSet["input3"];
|
||||
Assert.Null(actualInput3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetInputNameTest()
|
||||
{
|
||||
var input1 = new FlagInput("input1", "--input1", "input1");
|
||||
var input2 = new FlagInput("input2", "--input2", "input2");
|
||||
|
||||
var featureSet = new CommandSet();
|
||||
featureSet.Add(input1);
|
||||
featureSet.Add(input2);
|
||||
|
||||
var actualName1 = featureSet.GetInputName("input1");
|
||||
Assert.NotEmpty(actualName1);
|
||||
Assert.Equal("input1", actualName1);
|
||||
|
||||
var actualName2 = featureSet.GetInputName("--input2");
|
||||
Assert.NotEmpty(actualName2);
|
||||
Assert.Equal("input2", actualName2);
|
||||
|
||||
var actualName3 = featureSet.GetInputName("input3");
|
||||
Assert.Empty(actualName3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TopLevelFlagTest()
|
||||
{
|
||||
var input1 = new FlagInput("input1", "--input1", "input1");
|
||||
var input2 = new FlagInput("input2", "--input2", "input2");
|
||||
|
||||
var featureSet = new CommandSet();
|
||||
featureSet.Add(input1);
|
||||
featureSet.Add(input2);
|
||||
|
||||
bool actualTop1 = featureSet.TopLevelFlag("input1");
|
||||
Assert.True(actualTop1);
|
||||
|
||||
bool actualTop2 = featureSet.TopLevelFlag("--input2");
|
||||
Assert.True(actualTop2);
|
||||
|
||||
bool actualTop3 = featureSet.TopLevelFlag("input3");
|
||||
Assert.False(actualTop3);
|
||||
}
|
||||
}
|
||||
}
|
||||
115
SabreTools.CommandLine.Test/FeatureTests.cs
Normal file
115
SabreTools.CommandLine.Test/FeatureTests.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test
|
||||
{
|
||||
public class FeatureTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessArgs_EmptyArgs_Success()
|
||||
{
|
||||
Feature feature = new MockFeature("", "", "");
|
||||
|
||||
string[] args = [];
|
||||
int index = 0;
|
||||
|
||||
bool actual = feature.ProcessArgs(args, index);
|
||||
Assert.True(actual);
|
||||
Assert.Empty(feature.Inputs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessArgs_NegativeIndex_Failure()
|
||||
{
|
||||
Feature feature = new MockFeature("", "", "");
|
||||
|
||||
string[] args = ["a", "b", "c"];
|
||||
int index = -1;
|
||||
|
||||
bool actual = feature.ProcessArgs(args, index);
|
||||
Assert.False(actual);
|
||||
Assert.Empty(feature.Inputs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessArgs_OverIndex_Failure()
|
||||
{
|
||||
Feature feature = new MockFeature("", "", "");
|
||||
|
||||
string[] args = ["a", "b", "c"];
|
||||
int index = 3;
|
||||
|
||||
bool actual = feature.ProcessArgs(args, index);
|
||||
Assert.False(actual);
|
||||
Assert.Empty(feature.Inputs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessArgs_ValidArgs_Success()
|
||||
{
|
||||
Feature feature = new MockFeature("a", "a", "a");
|
||||
feature.Add(new MockFeature("b", "b", "b"));
|
||||
feature.Add(new MockFeature("c", "c", "c"));
|
||||
|
||||
string[] args = ["a", "b", "c"];
|
||||
int index = 0;
|
||||
|
||||
bool actual = feature.ProcessArgs(args, index);
|
||||
Assert.True(actual);
|
||||
Assert.Empty(feature.Inputs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessArgs_InvalidArg_AddedAsGeneric()
|
||||
{
|
||||
Feature feature = new MockFeature("a", "a", "a");
|
||||
feature.Add(new MockFeature("b", "b", "b"));
|
||||
feature.Add(new MockFeature("d", "d", "d"));
|
||||
|
||||
string[] args = ["a", "b", "c"];
|
||||
int index = 0;
|
||||
|
||||
bool actual = feature.ProcessArgs(args, index);
|
||||
Assert.True(actual);
|
||||
string input = Assert.Single(feature.Inputs);
|
||||
Assert.Equal("c", input);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessArgs_NestedArgs_Success()
|
||||
{
|
||||
Feature feature = new MockFeature("a", "a", "a");
|
||||
var sub = new MockFeature("b", "b", "b");
|
||||
sub.Add(new MockFeature("c", "c", "c"));
|
||||
feature.Add(sub);
|
||||
|
||||
string[] args = ["a", "b", "c"];
|
||||
int index = 0;
|
||||
|
||||
bool actual = feature.ProcessArgs(args, index);
|
||||
Assert.True(actual);
|
||||
Assert.Empty(feature.Inputs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mock Feature implementation for testing
|
||||
/// </summary>
|
||||
private class MockFeature : Feature
|
||||
{
|
||||
public MockFeature(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
}
|
||||
|
||||
public MockFeature(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute() => true;
|
||||
}
|
||||
}
|
||||
}
|
||||
134
SabreTools.CommandLine.Test/Inputs/BooleanInputTests.cs
Normal file
134
SabreTools.CommandLine.Test/Inputs/BooleanInputTests.cs
Normal file
@@ -0,0 +1,134 @@
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test.Inputs
|
||||
{
|
||||
public class BooleanInputTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessInput_EmptyArgs_Failure()
|
||||
{
|
||||
string[] args = [];
|
||||
int index = 0;
|
||||
|
||||
var input = new BooleanInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_NegativeIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "true"];
|
||||
int index = -1;
|
||||
|
||||
var input = new BooleanInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(-1, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_OverIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "true"];
|
||||
int index = 2;
|
||||
|
||||
var input = new BooleanInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(2, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a"];
|
||||
int index = 0;
|
||||
|
||||
var input = new BooleanInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a", "ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new BooleanInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a", "true"];
|
||||
int index = 0;
|
||||
|
||||
var input = new BooleanInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(1, index);
|
||||
Assert.True(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a="];
|
||||
int index = 0;
|
||||
|
||||
var input = new BooleanInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a=ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new BooleanInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a=true"];
|
||||
int index = 0;
|
||||
|
||||
var input = new BooleanInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.True(input.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
64
SabreTools.CommandLine.Test/Inputs/FlagInputTests.cs
Normal file
64
SabreTools.CommandLine.Test/Inputs/FlagInputTests.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test.Inputs
|
||||
{
|
||||
public class FlagInputTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessInput_EmptyArgs_Failure()
|
||||
{
|
||||
string[] args = [];
|
||||
int index = 0;
|
||||
|
||||
var input = new FlagInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.False(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_NegativeIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "true"];
|
||||
int index = -1;
|
||||
|
||||
var input = new FlagInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(-1, index);
|
||||
Assert.False(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_OverIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "true"];
|
||||
int index = 2;
|
||||
|
||||
var input = new FlagInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(2, index);
|
||||
Assert.False(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a"];
|
||||
int index = 0;
|
||||
|
||||
var input = new FlagInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.True(input.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
136
SabreTools.CommandLine.Test/Inputs/Int16InputTests.cs
Normal file
136
SabreTools.CommandLine.Test/Inputs/Int16InputTests.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test.Inputs
|
||||
{
|
||||
public class Int16InputTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessInput_EmptyArgs_Failure()
|
||||
{
|
||||
string[] args = [];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_NegativeIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = -1;
|
||||
|
||||
var input = new Int16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(-1, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_OverIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 2;
|
||||
|
||||
var input = new Int16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(2, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a", "ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(1, index);
|
||||
short value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5, value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a="];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a=ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a=5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
short value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
136
SabreTools.CommandLine.Test/Inputs/Int32InputTests.cs
Normal file
136
SabreTools.CommandLine.Test/Inputs/Int32InputTests.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test.Inputs
|
||||
{
|
||||
public class Int32InputTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessInput_EmptyArgs_Failure()
|
||||
{
|
||||
string[] args = [];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_NegativeIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = -1;
|
||||
|
||||
var input = new Int32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(-1, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_OverIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 2;
|
||||
|
||||
var input = new Int32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(2, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a", "ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(1, index);
|
||||
int value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5, value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a="];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a=ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a=5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
int value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
136
SabreTools.CommandLine.Test/Inputs/Int64InputTests.cs
Normal file
136
SabreTools.CommandLine.Test/Inputs/Int64InputTests.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test.Inputs
|
||||
{
|
||||
public class Int64InputTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessInput_EmptyArgs_Failure()
|
||||
{
|
||||
string[] args = [];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_NegativeIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = -1;
|
||||
|
||||
var input = new Int64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(-1, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_OverIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 2;
|
||||
|
||||
var input = new Int64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(2, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a", "ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(1, index);
|
||||
long value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5, value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a="];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a=ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a=5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
long value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
136
SabreTools.CommandLine.Test/Inputs/Int8InputTests.cs
Normal file
136
SabreTools.CommandLine.Test/Inputs/Int8InputTests.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test.Inputs
|
||||
{
|
||||
public class Int8InputTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessInput_EmptyArgs_Failure()
|
||||
{
|
||||
string[] args = [];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_NegativeIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = -1;
|
||||
|
||||
var input = new Int8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(-1, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_OverIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 2;
|
||||
|
||||
var input = new Int8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(2, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a", "ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(1, index);
|
||||
sbyte value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5, value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a="];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a=ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a=5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new Int8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
sbyte value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
107
SabreTools.CommandLine.Test/Inputs/StringInputTests.cs
Normal file
107
SabreTools.CommandLine.Test/Inputs/StringInputTests.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test.Inputs
|
||||
{
|
||||
public class StringInputTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessInput_EmptyArgs_Failure()
|
||||
{
|
||||
string[] args = [];
|
||||
int index = 0;
|
||||
|
||||
var input = new StringInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_NegativeIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "value"];
|
||||
int index = -1;
|
||||
|
||||
var input = new StringInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(-1, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_OverIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "value"];
|
||||
int index = 2;
|
||||
|
||||
var input = new StringInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(2, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a"];
|
||||
int index = 0;
|
||||
|
||||
var input = new StringInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a", "value"];
|
||||
int index = 0;
|
||||
|
||||
var input = new StringInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(1, index);
|
||||
Assert.Equal("value", input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_Empty_Success()
|
||||
{
|
||||
string[] args = ["a="];
|
||||
int index = 0;
|
||||
|
||||
var input = new StringInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.NotNull(input.Value);
|
||||
Assert.Empty(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a=value"];
|
||||
int index = 0;
|
||||
|
||||
var input = new StringInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Equal("value", input.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
112
SabreTools.CommandLine.Test/Inputs/StringListInputTests.cs
Normal file
112
SabreTools.CommandLine.Test/Inputs/StringListInputTests.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test.Inputs
|
||||
{
|
||||
public class StringListInputTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessInput_EmptyArgs_Failure()
|
||||
{
|
||||
string[] args = [];
|
||||
int index = 0;
|
||||
|
||||
var input = new StringListInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_NegativeIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "true"];
|
||||
int index = -1;
|
||||
|
||||
var input = new StringListInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(-1, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_OverIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "true"];
|
||||
int index = 2;
|
||||
|
||||
var input = new StringListInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(2, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a"];
|
||||
int index = 0;
|
||||
|
||||
var input = new StringListInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a", "value"];
|
||||
int index = 0;
|
||||
|
||||
var input = new StringListInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(1, index);
|
||||
Assert.NotNull(input.Value);
|
||||
var value = Assert.Single(input.Value);
|
||||
Assert.Equal("value", value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_Empty_Success()
|
||||
{
|
||||
string[] args = ["a="];
|
||||
int index = 0;
|
||||
|
||||
var input = new StringListInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.NotNull(input.Value);
|
||||
var value = Assert.Single(input.Value);
|
||||
Assert.Empty(value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a=value"];
|
||||
int index = 0;
|
||||
|
||||
var input = new StringListInput("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.NotNull(input.Value);
|
||||
var value = Assert.Single(input.Value);
|
||||
Assert.Equal("value", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
136
SabreTools.CommandLine.Test/Inputs/UInt16InputTests.cs
Normal file
136
SabreTools.CommandLine.Test/Inputs/UInt16InputTests.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test.Inputs
|
||||
{
|
||||
public class UInt16InputTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessInput_EmptyArgs_Failure()
|
||||
{
|
||||
string[] args = [];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_NegativeIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = -1;
|
||||
|
||||
var input = new UInt16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(-1, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_OverIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 2;
|
||||
|
||||
var input = new UInt16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(2, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a", "ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(1, index);
|
||||
ushort value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5, value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a="];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a=ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a=5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt16Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
ushort value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
136
SabreTools.CommandLine.Test/Inputs/UInt32InputTests.cs
Normal file
136
SabreTools.CommandLine.Test/Inputs/UInt32InputTests.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test.Inputs
|
||||
{
|
||||
public class UInt32InputTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessInput_EmptyArgs_Failure()
|
||||
{
|
||||
string[] args = [];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_NegativeIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = -1;
|
||||
|
||||
var input = new UInt32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(-1, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_OverIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 2;
|
||||
|
||||
var input = new UInt32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(2, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a", "ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(1, index);
|
||||
uint value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5u, value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a="];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a=ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a=5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt32Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
uint value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5u, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
136
SabreTools.CommandLine.Test/Inputs/UInt64InputTests.cs
Normal file
136
SabreTools.CommandLine.Test/Inputs/UInt64InputTests.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test.Inputs
|
||||
{
|
||||
public class UInt64InputTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessInput_EmptyArgs_Failure()
|
||||
{
|
||||
string[] args = [];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_NegativeIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = -1;
|
||||
|
||||
var input = new UInt64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(-1, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_OverIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 2;
|
||||
|
||||
var input = new UInt64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(2, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a", "ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(1, index);
|
||||
ulong value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5u, value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a="];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a=ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a=5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt64Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
ulong value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5u, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
136
SabreTools.CommandLine.Test/Inputs/UInt8InputTests.cs
Normal file
136
SabreTools.CommandLine.Test/Inputs/UInt8InputTests.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test.Inputs
|
||||
{
|
||||
public class UInt8InputTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProcessInput_EmptyArgs_Failure()
|
||||
{
|
||||
string[] args = [];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_NegativeIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = -1;
|
||||
|
||||
var input = new UInt8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(-1, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_OverIndex_Failure()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 2;
|
||||
|
||||
var input = new UInt8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(2, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a", "ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Space_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a", "5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(1, index);
|
||||
byte value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5, value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidLength_Failure()
|
||||
{
|
||||
string[] args = ["a="];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_InvalidValue_Failure()
|
||||
{
|
||||
string[] args = ["a=ANY"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.False(actual);
|
||||
Assert.Equal(0, index);
|
||||
Assert.Null(input.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProcessInput_Equal_ValidValue_Success()
|
||||
{
|
||||
string[] args = ["a=5"];
|
||||
int index = 0;
|
||||
|
||||
var input = new UInt8Input("a", "a", "a");
|
||||
bool actual = input.ProcessInput(args, ref index);
|
||||
|
||||
Assert.True(actual);
|
||||
Assert.Equal(0, index);
|
||||
byte value = Assert.NotNull(input.Value);
|
||||
Assert.Equal(5, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
691
SabreTools.CommandLine.Test/Inputs/UserInputTests.cs
Normal file
691
SabreTools.CommandLine.Test/Inputs/UserInputTests.cs
Normal file
@@ -0,0 +1,691 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
using Xunit;
|
||||
|
||||
namespace SabreTools.CommandLine.Test.Inputs
|
||||
{
|
||||
public class UserInputTests
|
||||
{
|
||||
[Fact]
|
||||
public void AddAndRetrieveTest()
|
||||
{
|
||||
var input1 = new FlagInput("input1", "--input1", "input1");
|
||||
var input2 = new FlagInput("input2", "--input2", "input2");
|
||||
|
||||
var userInput = new MockUserInput("a", "a", "a");
|
||||
userInput.Add(input1);
|
||||
userInput.Add(input2);
|
||||
|
||||
var actualInput1 = userInput["input1"];
|
||||
Assert.NotNull(actualInput1);
|
||||
Assert.Equal("input1", actualInput1.Name);
|
||||
|
||||
var actualInput2 = userInput[input2];
|
||||
Assert.NotNull(actualInput2);
|
||||
Assert.Equal("input2", actualInput2.Name);
|
||||
|
||||
var actualInput3 = userInput["input3"];
|
||||
Assert.Null(actualInput3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ContainsFlagTest()
|
||||
{
|
||||
var userInput = new MockUserInput("a", ["a", "--b"], "a");
|
||||
|
||||
bool exactActual = userInput.ContainsFlag("a");
|
||||
Assert.True(exactActual);
|
||||
|
||||
bool equalsActual = userInput.ContainsFlag("--b=");
|
||||
Assert.True(equalsActual);
|
||||
|
||||
bool noMatchActual = userInput.ContainsFlag("-c");
|
||||
Assert.False(noMatchActual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StartsWithTest()
|
||||
{
|
||||
var userInput = new MockUserInput("a", ["a", "--b"], "a");
|
||||
|
||||
bool exactActual = userInput.StartsWith('a');
|
||||
Assert.True(exactActual);
|
||||
|
||||
bool trimActual = userInput.StartsWith('b');
|
||||
Assert.True(trimActual);
|
||||
|
||||
bool noMatchActual = userInput.StartsWith('c');
|
||||
Assert.False(noMatchActual);
|
||||
}
|
||||
|
||||
#region GetBoolean
|
||||
|
||||
[Fact]
|
||||
public void GetBoolean_InvalidKey_DefaultValue()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new BooleanInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
bool actual = userInput.GetBoolean("c");
|
||||
Assert.False(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBoolean_Exists_WrongType_Throws()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
Assert.Throws<ArgumentException>(() => _ = userInput.GetBoolean("b"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBoolean_Exists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new BooleanInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
int index = 0;
|
||||
child.ProcessInput(["b", "true"], ref index);
|
||||
|
||||
bool actual = userInput.GetBoolean("b");
|
||||
Assert.True(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetBoolean_NestedExists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
var subChild = new BooleanInput("c", "c", "c");
|
||||
child.Add(subChild);
|
||||
|
||||
int index = 0;
|
||||
subChild.ProcessInput(["c", "true"], ref index);
|
||||
|
||||
bool actual = userInput.GetBoolean("c");
|
||||
Assert.True(actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetInt8
|
||||
|
||||
[Fact]
|
||||
public void GetInt8_InvalidKey_DefaultValue()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new Int8Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
sbyte actual = userInput.GetInt8("c");
|
||||
Assert.Equal(sbyte.MinValue, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetInt8_Exists_WrongType_Throws()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
Assert.Throws<ArgumentException>(() => _ = userInput.GetInt8("b"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetInt8_Exists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new Int8Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
int index = 0;
|
||||
child.ProcessInput(["b", "5"], ref index);
|
||||
|
||||
sbyte actual = userInput.GetInt8("b");
|
||||
Assert.Equal(5, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetInt8_NestedExists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
var subChild = new Int8Input("c", "c", "c");
|
||||
child.Add(subChild);
|
||||
|
||||
int index = 0;
|
||||
subChild.ProcessInput(["c", "5"], ref index);
|
||||
|
||||
sbyte actual = userInput.GetInt8("c");
|
||||
Assert.Equal(5, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetInt16
|
||||
|
||||
[Fact]
|
||||
public void GetInt16_InvalidKey_DefaultValue()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new Int16Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
short actual = userInput.GetInt16("c");
|
||||
Assert.Equal(short.MinValue, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetInt16_Exists_WrongType_Throws()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
Assert.Throws<ArgumentException>(() => _ = userInput.GetInt16("b"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetInt16_Exists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new Int16Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
int index = 0;
|
||||
child.ProcessInput(["b", "5"], ref index);
|
||||
|
||||
short actual = userInput.GetInt16("b");
|
||||
Assert.Equal(5, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetInt16_NestedExists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
var subChild = new Int16Input("c", "c", "c");
|
||||
child.Add(subChild);
|
||||
|
||||
int index = 0;
|
||||
subChild.ProcessInput(["c", "5"], ref index);
|
||||
|
||||
short actual = userInput.GetInt16("c");
|
||||
Assert.Equal(5, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetInt32
|
||||
|
||||
[Fact]
|
||||
public void GetInt32_InvalidKey_DefaultValue()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new Int32Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
int actual = userInput.GetInt32("c");
|
||||
Assert.Equal(int.MinValue, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetInt32_Exists_WrongType_Throws()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
Assert.Throws<ArgumentException>(() => _ = userInput.GetInt32("b"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetInt32_Exists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new Int32Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
int index = 0;
|
||||
child.ProcessInput(["b", "5"], ref index);
|
||||
|
||||
int actual = userInput.GetInt32("b");
|
||||
Assert.Equal(5, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetInt32_NestedExists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
var subChild = new Int32Input("c", "c", "c");
|
||||
child.Add(subChild);
|
||||
|
||||
int index = 0;
|
||||
subChild.ProcessInput(["c", "5"], ref index);
|
||||
|
||||
int actual = userInput.GetInt32("c");
|
||||
Assert.Equal(5, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetInt64
|
||||
|
||||
[Fact]
|
||||
public void GetInt64_InvalidKey_DefaultValue()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new Int64Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
long actual = userInput.GetInt64("c");
|
||||
Assert.Equal(long.MinValue, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetInt64_Exists_WrongType_Throws()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
Assert.Throws<ArgumentException>(() => _ = userInput.GetInt64("b"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetInt64_Exists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new Int64Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
int index = 0;
|
||||
child.ProcessInput(["b", "5"], ref index);
|
||||
|
||||
long actual = userInput.GetInt64("b");
|
||||
Assert.Equal(5, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetInt64_NestedExists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
var subChild = new Int64Input("c", "c", "c");
|
||||
child.Add(subChild);
|
||||
|
||||
int index = 0;
|
||||
subChild.ProcessInput(["c", "5"], ref index);
|
||||
|
||||
long actual = userInput.GetInt64("c");
|
||||
Assert.Equal(5, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetString
|
||||
|
||||
[Fact]
|
||||
public void GetString_InvalidKey_DefaultValue()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new StringInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
string? actual = userInput.GetString("c");
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetString_Exists_WrongType_Throws()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
Assert.Throws<ArgumentException>(() => _ = userInput.GetString("b"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetString_Exists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new StringInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
int index = 0;
|
||||
child.ProcessInput(["b", "value"], ref index);
|
||||
|
||||
string? actual = userInput.GetString("b");
|
||||
Assert.Equal("value", actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetString_NestedExists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
var subChild = new StringInput("c", "c", "c");
|
||||
child.Add(subChild);
|
||||
|
||||
int index = 0;
|
||||
subChild.ProcessInput(["c", "value"], ref index);
|
||||
|
||||
string? actual = userInput.GetString("c");
|
||||
Assert.Equal("value", actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetStringList
|
||||
|
||||
[Fact]
|
||||
public void GetStringList_InvalidKey_DefaultValue()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new StringListInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
List<string> actual = userInput.GetStringList("c");
|
||||
Assert.Empty(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetStringList_Exists_WrongType_Throws()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
Assert.Throws<ArgumentException>(() => _ = userInput.GetStringList("b"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetStringList_Exists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new StringListInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
int index = 0;
|
||||
child.ProcessInput(["b", "value"], ref index);
|
||||
|
||||
List<string> actual = userInput.GetStringList("b");
|
||||
string value = Assert.Single(actual);
|
||||
Assert.Equal("value", value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetStringList_NestedExists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
var subChild = new StringListInput("c", "c", "c");
|
||||
child.Add(subChild);
|
||||
|
||||
int index = 0;
|
||||
subChild.ProcessInput(["c", "value"], ref index);
|
||||
|
||||
List<string> actual = userInput.GetStringList("c");
|
||||
string value = Assert.Single(actual);
|
||||
Assert.Equal("value", value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetUInt8
|
||||
|
||||
[Fact]
|
||||
public void GetUInt8_InvalidKey_DefaultValue()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new UInt8Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
byte actual = userInput.GetUInt8("c");
|
||||
Assert.Equal(byte.MinValue, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUInt8_Exists_WrongType_Throws()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
Assert.Throws<ArgumentException>(() => _ = userInput.GetUInt8("b"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUInt8_Exists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new UInt8Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
int index = 0;
|
||||
child.ProcessInput(["b", "5"], ref index);
|
||||
|
||||
byte actual = userInput.GetUInt8("b");
|
||||
Assert.Equal(5, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUInt8_NestedExists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
var subChild = new UInt8Input("c", "c", "c");
|
||||
child.Add(subChild);
|
||||
|
||||
int index = 0;
|
||||
subChild.ProcessInput(["c", "5"], ref index);
|
||||
|
||||
byte actual = userInput.GetUInt8("c");
|
||||
Assert.Equal(5, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetUInt16
|
||||
|
||||
[Fact]
|
||||
public void GetUInt16_InvalidKey_DefaultValue()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new UInt16Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
ushort actual = userInput.GetUInt16("c");
|
||||
Assert.Equal(ushort.MinValue, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUInt16_Exists_WrongType_Throws()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
Assert.Throws<ArgumentException>(() => _ = userInput.GetUInt16("b"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUInt16_Exists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new UInt16Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
int index = 0;
|
||||
child.ProcessInput(["b", "5"], ref index);
|
||||
|
||||
ushort actual = userInput.GetUInt16("b");
|
||||
Assert.Equal(5, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUInt16_NestedExists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
var subChild = new UInt16Input("c", "c", "c");
|
||||
child.Add(subChild);
|
||||
|
||||
int index = 0;
|
||||
subChild.ProcessInput(["c", "5"], ref index);
|
||||
|
||||
ushort actual = userInput.GetUInt16("c");
|
||||
Assert.Equal(5, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetUInt32
|
||||
|
||||
[Fact]
|
||||
public void GetUInt32_InvalidKey_DefaultValue()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new UInt32Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
uint actual = userInput.GetUInt32("c");
|
||||
Assert.Equal(uint.MinValue, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUInt32_Exists_WrongType_Throws()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
Assert.Throws<ArgumentException>(() => _ = userInput.GetUInt32("b"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUInt32_Exists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new UInt32Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
int index = 0;
|
||||
child.ProcessInput(["b", "5"], ref index);
|
||||
|
||||
uint actual = userInput.GetUInt32("b");
|
||||
Assert.Equal(5u, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUInt32_NestedExists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
var subChild = new UInt32Input("c", "c", "c");
|
||||
child.Add(subChild);
|
||||
|
||||
int index = 0;
|
||||
subChild.ProcessInput(["c", "5"], ref index);
|
||||
|
||||
uint actual = userInput.GetUInt32("c");
|
||||
Assert.Equal(5u, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetUInt64
|
||||
|
||||
[Fact]
|
||||
public void GetUInt64_InvalidKey_DefaultValue()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new UInt64Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
ulong actual = userInput.GetUInt64("c");
|
||||
Assert.Equal(ulong.MinValue, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUInt64_Exists_WrongType_Throws()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
Assert.Throws<ArgumentException>(() => _ = userInput.GetUInt64("b"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUInt64_Exists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new UInt64Input("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
|
||||
int index = 0;
|
||||
child.ProcessInput(["b", "5"], ref index);
|
||||
|
||||
ulong actual = userInput.GetUInt64("b");
|
||||
Assert.Equal(5u, actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetUInt64_NestedExists_Returns()
|
||||
{
|
||||
UserInput userInput = new MockUserInput("a", "a", "a");
|
||||
var child = new MockUserInput("b", "b", "b");
|
||||
userInput.Add(child);
|
||||
var subChild = new UInt64Input("c", "c", "c");
|
||||
child.Add(subChild);
|
||||
|
||||
int index = 0;
|
||||
subChild.ProcessInput(["c", "5"], ref index);
|
||||
|
||||
ulong actual = userInput.GetUInt64("c");
|
||||
Assert.Equal(5u, actual);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Mock UserInput implementation for testing
|
||||
/// </summary>
|
||||
private class MockUserInput : UserInput<object?>
|
||||
{
|
||||
public MockUserInput(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
}
|
||||
|
||||
public MockUserInput(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessInput(string[] args, ref int index) => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string FormatFlags() => string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
|
||||
<IsPackable>false</IsPackable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SabreTools.CommandLine\SabreTools.CommandLine.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
48
SabreTools.CommandLine.sln
Normal file
48
SabreTools.CommandLine.sln
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.CommandLine", "SabreTools.CommandLine\SabreTools.CommandLine.csproj", "{B34354AD-82BD-477F-AE21-9BE0B755A6DE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.CommandLine.Test", "SabreTools.CommandLine.Test\SabreTools.CommandLine.Test.csproj", "{4AB88B62-E927-40B2-B491-9C2673A74589}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B34354AD-82BD-477F-AE21-9BE0B755A6DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B34354AD-82BD-477F-AE21-9BE0B755A6DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B34354AD-82BD-477F-AE21-9BE0B755A6DE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B34354AD-82BD-477F-AE21-9BE0B755A6DE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B34354AD-82BD-477F-AE21-9BE0B755A6DE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B34354AD-82BD-477F-AE21-9BE0B755A6DE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B34354AD-82BD-477F-AE21-9BE0B755A6DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B34354AD-82BD-477F-AE21-9BE0B755A6DE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B34354AD-82BD-477F-AE21-9BE0B755A6DE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B34354AD-82BD-477F-AE21-9BE0B755A6DE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B34354AD-82BD-477F-AE21-9BE0B755A6DE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B34354AD-82BD-477F-AE21-9BE0B755A6DE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4AB88B62-E927-40B2-B491-9C2673A74589}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4AB88B62-E927-40B2-B491-9C2673A74589}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4AB88B62-E927-40B2-B491-9C2673A74589}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4AB88B62-E927-40B2-B491-9C2673A74589}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4AB88B62-E927-40B2-B491-9C2673A74589}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4AB88B62-E927-40B2-B491-9C2673A74589}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4AB88B62-E927-40B2-B491-9C2673A74589}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4AB88B62-E927-40B2-B491-9C2673A74589}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4AB88B62-E927-40B2-B491-9C2673A74589}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4AB88B62-E927-40B2-B491-9C2673A74589}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4AB88B62-E927-40B2-B491-9C2673A74589}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4AB88B62-E927-40B2-B491-9C2673A74589}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
312
SabreTools.CommandLine/CommandSet.cs
Normal file
312
SabreTools.CommandLine/CommandSet.cs
Normal file
@@ -0,0 +1,312 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
|
||||
namespace SabreTools.CommandLine
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a logically-grouped set of user inputs
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It is recommended to use this class as the primary
|
||||
/// way to address user inputs from the application. It
|
||||
/// is also recommended that all directly-included
|
||||
/// inputs are <see cref="Feature"/> unless the implementing
|
||||
/// program only has a single utility.
|
||||
/// </remarks>
|
||||
public class CommandSet
|
||||
{
|
||||
#region Private variables
|
||||
|
||||
/// <summary>
|
||||
/// Preamble used when printing help text to console
|
||||
/// </summary>
|
||||
private readonly List<string> _header = [];
|
||||
|
||||
/// <summary>
|
||||
/// Trailing lines used when printing help text to console
|
||||
/// </summary>
|
||||
private readonly List<string> _footer = [];
|
||||
|
||||
/// <summary>
|
||||
/// Set of all user inputs in this grouping
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only the top level inputs need to be defined. All
|
||||
/// children will be included by default.
|
||||
/// </remarks>
|
||||
private readonly Dictionary<string, UserInput> _inputs = [];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Create a new CommandSet with no printable header
|
||||
/// </summary>
|
||||
public CommandSet() { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a new CommandSet with a printable header
|
||||
/// </summary>
|
||||
/// <param name="header">Custom commandline header to be printed when outputting help</param>
|
||||
public CommandSet(List<string> header)
|
||||
{
|
||||
_header.AddRange(header);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new CommandSet with a printable header
|
||||
/// </summary>
|
||||
/// <param name="header">Custom commandline header to be printed when outputting help</param>
|
||||
/// <param name="footer">Custom commandline footer to be printed when outputting help</param>
|
||||
public CommandSet(List<string> header, List<string> footer)
|
||||
{
|
||||
_header.AddRange(header);
|
||||
_footer.AddRange(footer);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Accessors
|
||||
|
||||
public UserInput? this[string name]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_inputs.ContainsKey(name))
|
||||
return null;
|
||||
|
||||
return _inputs[name];
|
||||
}
|
||||
}
|
||||
|
||||
public UserInput? this[UserInput subfeature]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_inputs.ContainsKey(subfeature.Name))
|
||||
return null;
|
||||
|
||||
return _inputs[subfeature.Name];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a new input to the set
|
||||
/// </summary>
|
||||
/// <param name="input">UserInput object to map to</param>
|
||||
public void Add(UserInput input)
|
||||
=> _inputs.Add(input.Name, input);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Inputs
|
||||
|
||||
/// <summary>
|
||||
/// Get the input name for a given flag or short name
|
||||
/// </summary>
|
||||
public string GetInputName(string name)
|
||||
{
|
||||
// Pre-split the input for efficiency
|
||||
string[] splitInput = name.Split('=');
|
||||
|
||||
foreach (var key in _inputs.Keys)
|
||||
{
|
||||
// Validate the name matches
|
||||
var feature = _inputs[key];
|
||||
if (feature.Name == splitInput[0])
|
||||
return key;
|
||||
|
||||
// Validate the flag is contained
|
||||
if (feature.ContainsFlag(splitInput[0]))
|
||||
return key;
|
||||
}
|
||||
|
||||
// No feature could be found
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if a flag is a top-level (main application) flag
|
||||
/// </summary>
|
||||
/// <param name="flag">Name of the flag to check</param>
|
||||
/// <returns>True if the feature was found, false otherwise</returns>
|
||||
public bool TopLevelFlag(string flag)
|
||||
=> GetInputName(flag).Length > 0;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Output
|
||||
|
||||
/// <summary>
|
||||
/// Output top-level features only
|
||||
/// </summary>
|
||||
public void OutputGenericHelp()
|
||||
{
|
||||
// Start building the output list
|
||||
List<string> output = [];
|
||||
|
||||
// Append the header, if needed
|
||||
if (_header.Count > 0)
|
||||
output.AddRange(_header);
|
||||
|
||||
// Now append all available top-level flags
|
||||
output.Add("Available options:");
|
||||
foreach (string feature in _inputs.Keys)
|
||||
{
|
||||
var outputs = _inputs[feature]?.Output(pre: 2, midpoint: 30);
|
||||
if (outputs != null)
|
||||
output.AddRange(outputs);
|
||||
}
|
||||
|
||||
// Append the footer, if needed
|
||||
if (_footer.Count > 0)
|
||||
output.AddRange(_footer);
|
||||
|
||||
// Now write out everything in a staged manner
|
||||
WriteOutWithPauses(output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output all features recursively
|
||||
/// </summary>
|
||||
public void OutputAllHelp()
|
||||
{
|
||||
// Start building the output list
|
||||
List<string> output = [];
|
||||
|
||||
// Append the header first, if needed
|
||||
if (_header.Count > 0)
|
||||
output.AddRange(_header);
|
||||
|
||||
// Now append all available flags recursively
|
||||
output.Add("Available options:");
|
||||
foreach (string feature in _inputs.Keys)
|
||||
{
|
||||
var outputs = _inputs[feature]?.OutputRecursive(0, pre: 2, midpoint: 30, includeLongDescription: true);
|
||||
if (outputs != null)
|
||||
output.AddRange(outputs);
|
||||
}
|
||||
|
||||
// Append the footer, if needed
|
||||
if (_footer.Count > 0)
|
||||
output.AddRange(_footer);
|
||||
|
||||
// Now write out everything in a staged manner
|
||||
WriteOutWithPauses(output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output a single feature recursively
|
||||
/// </summary>
|
||||
/// <param name="featureName">Name of the feature to output information for, if possible</param>
|
||||
/// <param name="includeLongDescription">True if the long description should be formatted and output, false otherwise</param>
|
||||
public void OutputIndividualFeature(string? featureName, bool includeLongDescription = false)
|
||||
{
|
||||
// Start building the output list
|
||||
List<string> output = [];
|
||||
|
||||
// If the feature name is null, empty, or just consisting of `-` characters, just show everything
|
||||
if (string.IsNullOrEmpty(featureName?.TrimStart('-')))
|
||||
{
|
||||
OutputGenericHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Now try to find the feature that has the name included
|
||||
string? realname = null;
|
||||
List<string> startsWith = [];
|
||||
foreach (string feature in _inputs.Keys)
|
||||
{
|
||||
// If we have a match to the feature name somehow
|
||||
if (feature == featureName)
|
||||
{
|
||||
realname = feature;
|
||||
break;
|
||||
}
|
||||
|
||||
// If we have an invalid feature
|
||||
else if (!_inputs.ContainsKey(feature) || _inputs[feature] == null)
|
||||
{
|
||||
startsWith.Add(feature);
|
||||
}
|
||||
|
||||
// If we have a match within the flags
|
||||
else if (_inputs[feature]!.ContainsFlag(featureName!))
|
||||
{
|
||||
realname = feature;
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise, we want to get features with the same start
|
||||
else if (_inputs[feature]!.StartsWith(featureName!.TrimStart('-')[0]))
|
||||
{
|
||||
startsWith.Add(feature);
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a real name found, append all available subflags recursively
|
||||
if (realname != null)
|
||||
{
|
||||
output.Add($"Available options for {realname}:");
|
||||
output.AddRange(_inputs[realname]!.OutputRecursive(0, pre: 2, midpoint: 30, includeLongDescription: includeLongDescription));
|
||||
}
|
||||
|
||||
// If no name was found but we have possible matches, show them
|
||||
else if (startsWith.Count > 0)
|
||||
{
|
||||
output.Add($"\"{featureName}\" not found. Did you mean:");
|
||||
foreach (string possible in startsWith)
|
||||
{
|
||||
output.AddRange(_inputs[possible]!.Output(pre: 2, midpoint: 30, includeLongDescription: includeLongDescription));
|
||||
}
|
||||
}
|
||||
|
||||
// Now write out everything in a staged manner
|
||||
WriteOutWithPauses(output);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pause on console output
|
||||
/// </summary>
|
||||
private static void Pause()
|
||||
{
|
||||
#if NET452_OR_GREATER || NETCOREAPP || NETSTANDARD2_0_OR_GREATER
|
||||
if (!Console.IsOutputRedirected)
|
||||
#endif
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Press enter to continue...");
|
||||
Console.ReadLine();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write out the help text with pauses, if needed
|
||||
/// </summary>
|
||||
private static void WriteOutWithPauses(List<string> helpText)
|
||||
{
|
||||
// Now output based on the size of the screen
|
||||
int i = 0;
|
||||
for (int line = 0; line < helpText.Count; line++)
|
||||
{
|
||||
string help = helpText[line];
|
||||
|
||||
Console.WriteLine(help);
|
||||
i++;
|
||||
|
||||
// If we're not being redirected and we reached the size of the screen, pause
|
||||
if (i == Console.WindowHeight - 3 && line != helpText.Count - 1)
|
||||
{
|
||||
i = 0;
|
||||
Pause();
|
||||
}
|
||||
}
|
||||
|
||||
Pause();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
84
SabreTools.CommandLine/Feature.cs
Executable file
84
SabreTools.CommandLine/Feature.cs
Executable file
@@ -0,0 +1,84 @@
|
||||
using System.Collections.Generic;
|
||||
using SabreTools.CommandLine.Inputs;
|
||||
|
||||
namespace SabreTools.CommandLine
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an application-level feature
|
||||
/// </summary>
|
||||
public abstract class Feature : FlagInput
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// List of undefined inputs
|
||||
/// </summary>
|
||||
public readonly List<string> Inputs = [];
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if the feature requires inputs to be set
|
||||
/// </summary>
|
||||
public bool RequiresInputs { get; protected set; } = false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public Feature(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
}
|
||||
|
||||
public Feature(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Processing
|
||||
|
||||
/// <summary>
|
||||
/// Process args list based on current feature
|
||||
/// </summary>
|
||||
/// <param name="args">Set of arguments to process</param>
|
||||
/// <param name="index">Starting index into the arguments</param>
|
||||
/// <returns>True if all arguments were processed correctly, false otherwise</returns>
|
||||
public virtual bool ProcessArgs(string[] args, int index)
|
||||
{
|
||||
// Empty arguments is always successful
|
||||
if (args.Length == 0)
|
||||
return true;
|
||||
|
||||
// Invalid index values are not processed
|
||||
if (index < 0 || index >= args.Length)
|
||||
return false;
|
||||
|
||||
for (int i = index; i < args.Length; i++)
|
||||
{
|
||||
// Verify that the current flag is proper for the feature
|
||||
if (ProcessInput(args, ref i))
|
||||
continue;
|
||||
|
||||
// Add all other arguments to the generic inputs
|
||||
Inputs.Add(item: args[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify all inputs based on the feature requirements
|
||||
/// </summary>
|
||||
/// <returns>True if the inputs verified correctly, false otherwise</returns>
|
||||
public abstract bool VerifyInputs();
|
||||
|
||||
/// <summary>
|
||||
/// Execute the logic associated with the feature
|
||||
/// </summary>
|
||||
/// <returns>True if execution was successful, false otherwise</returns>
|
||||
public abstract bool Execute();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
57
SabreTools.CommandLine/Features/Help.cs
Normal file
57
SabreTools.CommandLine/Features/Help.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
namespace SabreTools.CommandLine.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// Default help feature implementation
|
||||
/// </summary>
|
||||
public class Help : Feature
|
||||
{
|
||||
public const string DisplayName = "Help";
|
||||
|
||||
private static readonly string[] _defaultFlags = ["?", "h", "help"];
|
||||
|
||||
private const string _description = "Show this help";
|
||||
|
||||
private const string _longDescription = "Built-in to most of the programs is a basic help text.";
|
||||
|
||||
public Help()
|
||||
: base(DisplayName, _defaultFlags, _description, _longDescription)
|
||||
{
|
||||
RequiresInputs = false;
|
||||
}
|
||||
|
||||
public Help(string[] flags)
|
||||
: base(DisplayName, flags, _description, _longDescription)
|
||||
{
|
||||
RequiresInputs = false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessArgs(string[] args, int index)
|
||||
=> ProcessArgs(args, index, null);
|
||||
|
||||
/// <inheritdoc cref="ProcessArgs(string[], int)"/>
|
||||
/// <param name="parentSet">Reference to the enclosing parent set</param>
|
||||
public bool ProcessArgs(string[] args, int index, CommandSet? parentSet)
|
||||
{
|
||||
// If we had something else after help
|
||||
if (args.Length > 1)
|
||||
{
|
||||
parentSet?.OutputIndividualFeature(args[1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, show generic help
|
||||
else
|
||||
{
|
||||
parentSet?.OutputGenericHelp();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute() => true;
|
||||
}
|
||||
}
|
||||
57
SabreTools.CommandLine/Features/HelpExtended.cs
Normal file
57
SabreTools.CommandLine/Features/HelpExtended.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
namespace SabreTools.CommandLine.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// Default extended help feature implementation
|
||||
/// </summary>
|
||||
public class HelpExtended : Feature
|
||||
{
|
||||
public const string DisplayName = "Help (Detailed)";
|
||||
|
||||
private static readonly string[] _defaultFlags = ["??", "hd", "help-detailed"];
|
||||
|
||||
private const string _description = "Show this detailed help";
|
||||
|
||||
private const string _longDescription = "Display a detailed help text to the screen.";
|
||||
|
||||
public HelpExtended()
|
||||
: base(DisplayName, _defaultFlags, _description, _longDescription)
|
||||
{
|
||||
RequiresInputs = false;
|
||||
}
|
||||
|
||||
public HelpExtended(string[] flags)
|
||||
: base(DisplayName, flags, _description, _longDescription)
|
||||
{
|
||||
RequiresInputs = false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessArgs(string[] args, int index)
|
||||
=> ProcessArgs(args, index, null);
|
||||
|
||||
/// <inheritdoc cref="ProcessArgs(string[], int)"/>
|
||||
/// <param name="parentSet">Reference to the enclosing parent set</param>
|
||||
public bool ProcessArgs(string[] args, int index, CommandSet? parentSet)
|
||||
{
|
||||
// If we had something else after help
|
||||
if (args.Length > 1)
|
||||
{
|
||||
parentSet?.OutputIndividualFeature(args[1], includeLongDescription: true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, show generic help
|
||||
else
|
||||
{
|
||||
parentSet?.OutputAllHelp();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute() => true;
|
||||
}
|
||||
}
|
||||
61
SabreTools.CommandLine/Features/Version.cs
Normal file
61
SabreTools.CommandLine/Features/Version.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace SabreTools.CommandLine.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// Default version feature implementation
|
||||
/// </summary>
|
||||
public class Version : Feature
|
||||
{
|
||||
public const string DisplayName = "Version";
|
||||
|
||||
private static readonly string[] _defaultFlags = ["v", "version"];
|
||||
|
||||
private const string _description = "Prints version";
|
||||
|
||||
private const string _longDescription = "Prints current program version.";
|
||||
|
||||
public Version()
|
||||
: base(DisplayName, _defaultFlags, _description, _longDescription)
|
||||
{
|
||||
RequiresInputs = false;
|
||||
}
|
||||
|
||||
public Version(string[] flags)
|
||||
: base(DisplayName, flags, _description, _longDescription)
|
||||
{
|
||||
RequiresInputs = false;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool VerifyInputs() => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool Execute()
|
||||
{
|
||||
Console.WriteLine($"Version: {GetVersion()}");
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The current toolset version to be used by all child applications
|
||||
/// </summary>
|
||||
private static string? GetVersion()
|
||||
{
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.GetEntryAssembly();
|
||||
if (assembly == null)
|
||||
return null;
|
||||
|
||||
var assemblyVersion = Attribute.GetCustomAttribute(assembly, typeof(AssemblyInformationalVersionAttribute)) as AssemblyInformationalVersionAttribute;
|
||||
return assemblyVersion?.InformationalVersion;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ex.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
96
SabreTools.CommandLine/Inputs/BooleanInput.cs
Normal file
96
SabreTools.CommandLine/Inputs/BooleanInput.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a user input bounded to the range of <see cref="bool"/>
|
||||
/// </summary>
|
||||
public class BooleanInput : UserInput<bool?>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public BooleanInput(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
public BooleanInput(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessInput(string[] args, ref int index)
|
||||
{
|
||||
// If the index is invalid
|
||||
if (index < 0 || index >= args.Length)
|
||||
return false;
|
||||
|
||||
// Get the current part
|
||||
string part = args[index];
|
||||
|
||||
// If the current flag doesn't match, check to see if any of the subfeatures are valid
|
||||
if (!ContainsFlag(part))
|
||||
{
|
||||
foreach (var kvp in Children)
|
||||
{
|
||||
if (kvp.Value.ProcessInput(args, ref index))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for space-separated
|
||||
if (!part.Contains("="))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= args.Length)
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!bool.TryParse(args[index + 1], out bool value))
|
||||
return false;
|
||||
|
||||
index++;
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
else
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!bool.TryParse(val, out bool value))
|
||||
return false;
|
||||
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string FormatFlags()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
Flags.ForEach(flag => sb.Append($"{flag}=, "));
|
||||
return sb.ToString().TrimEnd(' ', ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
64
SabreTools.CommandLine/Inputs/FlagInput.cs
Normal file
64
SabreTools.CommandLine/Inputs/FlagInput.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a boolean user input
|
||||
/// </summary>
|
||||
public class FlagInput : UserInput<bool>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public FlagInput(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
Value = false;
|
||||
}
|
||||
|
||||
public FlagInput(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
Value = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessInput(string[] args, ref int index)
|
||||
{
|
||||
// If the index is invalid
|
||||
if (index < 0 || index >= args.Length)
|
||||
return false;
|
||||
|
||||
// Get the current part
|
||||
string part = args[index];
|
||||
|
||||
// If the current flag doesn't match, check to see if any of the subfeatures are valid
|
||||
if (!ContainsFlag(part))
|
||||
{
|
||||
foreach (var kvp in Children)
|
||||
{
|
||||
if (kvp.Value.ProcessInput(args, ref index))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Value = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string FormatFlags()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
Flags.ForEach(flag => sb.Append($"{flag}, "));
|
||||
return sb.ToString().TrimEnd(' ', ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
96
SabreTools.CommandLine/Inputs/Int16Input.cs
Normal file
96
SabreTools.CommandLine/Inputs/Int16Input.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a user input bounded to the range of <see cref="short"/>
|
||||
/// </summary>
|
||||
public class Int16Input : UserInput<short?>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public Int16Input(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
public Int16Input(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessInput(string[] args, ref int index)
|
||||
{
|
||||
// If the index is invalid
|
||||
if (index < 0 || index >= args.Length)
|
||||
return false;
|
||||
|
||||
// Get the current part
|
||||
string part = args[index];
|
||||
|
||||
// If the current flag doesn't match, check to see if any of the subfeatures are valid
|
||||
if (!ContainsFlag(part))
|
||||
{
|
||||
foreach (var kvp in Children)
|
||||
{
|
||||
if (kvp.Value.ProcessInput(args, ref index))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for space-separated
|
||||
if (!part.Contains("="))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= args.Length)
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!short.TryParse(args[index + 1], out short value))
|
||||
return false;
|
||||
|
||||
index++;
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
else
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!short.TryParse(val, out short value))
|
||||
return false;
|
||||
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string FormatFlags()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
Flags.ForEach(flag => sb.Append($"{flag}=, "));
|
||||
return sb.ToString().TrimEnd(' ', ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
96
SabreTools.CommandLine/Inputs/Int32Input.cs
Normal file
96
SabreTools.CommandLine/Inputs/Int32Input.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a user input bounded to the range of <see cref="int"/>
|
||||
/// </summary>
|
||||
public class Int32Input : UserInput<int?>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public Int32Input(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
public Int32Input(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessInput(string[] args, ref int index)
|
||||
{
|
||||
// If the index is invalid
|
||||
if (index < 0 || index >= args.Length)
|
||||
return false;
|
||||
|
||||
// Get the current part
|
||||
string part = args[index];
|
||||
|
||||
// If the current flag doesn't match, check to see if any of the subfeatures are valid
|
||||
if (!ContainsFlag(part))
|
||||
{
|
||||
foreach (var kvp in Children)
|
||||
{
|
||||
if (kvp.Value.ProcessInput(args, ref index))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for space-separated
|
||||
if (!part.Contains("="))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= args.Length)
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!int.TryParse(args[index + 1], out int value))
|
||||
return false;
|
||||
|
||||
index++;
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
else
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!int.TryParse(val, out int value))
|
||||
return false;
|
||||
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string FormatFlags()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
Flags.ForEach(flag => sb.Append($"{flag}=, "));
|
||||
return sb.ToString().TrimEnd(' ', ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
96
SabreTools.CommandLine/Inputs/Int64Input.cs
Normal file
96
SabreTools.CommandLine/Inputs/Int64Input.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a user input bounded to the range of <see cref="long"/>
|
||||
/// </summary>
|
||||
public class Int64Input : UserInput<long?>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public Int64Input(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
public Int64Input(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessInput(string[] args, ref int index)
|
||||
{
|
||||
// If the index is invalid
|
||||
if (index < 0 || index >= args.Length)
|
||||
return false;
|
||||
|
||||
// Get the current part
|
||||
string part = args[index];
|
||||
|
||||
// If the current flag doesn't match, check to see if any of the subfeatures are valid
|
||||
if (!ContainsFlag(part))
|
||||
{
|
||||
foreach (var kvp in Children)
|
||||
{
|
||||
if (kvp.Value.ProcessInput(args, ref index))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for space-separated
|
||||
if (!part.Contains("="))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= args.Length)
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!long.TryParse(args[index + 1], out long value))
|
||||
return false;
|
||||
|
||||
index++;
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
else
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!long.TryParse(val, out long value))
|
||||
return false;
|
||||
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string FormatFlags()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
Flags.ForEach(flag => sb.Append($"{flag}=, "));
|
||||
return sb.ToString().TrimEnd(' ', ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
96
SabreTools.CommandLine/Inputs/Int8Input.cs
Normal file
96
SabreTools.CommandLine/Inputs/Int8Input.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a user input bounded to the range of <see cref="sbyte"/>
|
||||
/// </summary>
|
||||
public class Int8Input : UserInput<sbyte?>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public Int8Input(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
public Int8Input(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessInput(string[] args, ref int index)
|
||||
{
|
||||
// If the index is invalid
|
||||
if (index < 0 || index >= args.Length)
|
||||
return false;
|
||||
|
||||
// Get the current part
|
||||
string part = args[index];
|
||||
|
||||
// If the current flag doesn't match, check to see if any of the subfeatures are valid
|
||||
if (!ContainsFlag(part))
|
||||
{
|
||||
foreach (var kvp in Children)
|
||||
{
|
||||
if (kvp.Value.ProcessInput(args, ref index))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for space-separated
|
||||
if (!part.Contains("="))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= args.Length)
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!sbyte.TryParse(args[index + 1], out sbyte value))
|
||||
return false;
|
||||
|
||||
index++;
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
else
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!sbyte.TryParse(val, out sbyte value))
|
||||
return false;
|
||||
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string FormatFlags()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
Flags.ForEach(flag => sb.Append($"{flag}=, "));
|
||||
return sb.ToString().TrimEnd(' ', ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
84
SabreTools.CommandLine/Inputs/StringInput.cs
Normal file
84
SabreTools.CommandLine/Inputs/StringInput.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a string input with a single instance allowed
|
||||
/// </summary>
|
||||
public class StringInput : UserInput<string?>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public StringInput(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
public StringInput(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessInput(string[] args, ref int index)
|
||||
{
|
||||
// If the index is invalid
|
||||
if (index < 0 || index >= args.Length)
|
||||
return false;
|
||||
|
||||
/// Get the current part
|
||||
string part = args[index];
|
||||
|
||||
// If the current flag doesn't match, check to see if any of the subfeatures are valid
|
||||
if (!ContainsFlag(part))
|
||||
{
|
||||
foreach (var kvp in Children)
|
||||
{
|
||||
if (kvp.Value.ProcessInput(args, ref index))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for space-separated
|
||||
if (!part.Contains("="))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= args.Length)
|
||||
return false;
|
||||
|
||||
index++;
|
||||
Value = args[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
else
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
Value = val;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string FormatFlags()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
Flags.ForEach(flag => sb.Append($"{flag}=, "));
|
||||
return sb.ToString().TrimEnd(' ', ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
87
SabreTools.CommandLine/Inputs/StringListInput.cs
Normal file
87
SabreTools.CommandLine/Inputs/StringListInput.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a string input with multiple instances allowed
|
||||
/// </summary>
|
||||
public class StringListInput : UserInput<List<string>>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public StringListInput(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
public StringListInput(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessInput(string[] args, ref int index)
|
||||
{
|
||||
// If the index is invalid
|
||||
if (index < 0 || index >= args.Length)
|
||||
return false;
|
||||
|
||||
// Get the current part
|
||||
string part = args[index];
|
||||
|
||||
// If the current flag doesn't match, check to see if any of the subfeatures are valid
|
||||
if (!ContainsFlag(part))
|
||||
{
|
||||
foreach (var kvp in Children)
|
||||
{
|
||||
if (kvp.Value.ProcessInput(args, ref index))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for space-separated
|
||||
if (!part.Contains("="))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= args.Length)
|
||||
return false;
|
||||
|
||||
index++;
|
||||
Value ??= [];
|
||||
Value.Add(args[index]);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
else
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
Value ??= [];
|
||||
Value.Add(val);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string FormatFlags()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
Flags.ForEach(flag => sb.Append($"{flag}=, "));
|
||||
return sb.ToString().TrimEnd(' ', ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
96
SabreTools.CommandLine/Inputs/UInt16Input.cs
Normal file
96
SabreTools.CommandLine/Inputs/UInt16Input.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a user input bounded to the range of <see cref="ushort"/>
|
||||
/// </summary>
|
||||
public class UInt16Input : UserInput<ushort?>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public UInt16Input(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
public UInt16Input(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessInput(string[] args, ref int index)
|
||||
{
|
||||
// If the index is invalid
|
||||
if (index < 0 || index >= args.Length)
|
||||
return false;
|
||||
|
||||
// Get the current part
|
||||
string part = args[index];
|
||||
|
||||
// If the current flag doesn't match, check to see if any of the subfeatures are valid
|
||||
if (!ContainsFlag(part))
|
||||
{
|
||||
foreach (var kvp in Children)
|
||||
{
|
||||
if (kvp.Value.ProcessInput(args, ref index))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for space-separated
|
||||
if (!part.Contains("="))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= args.Length)
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!ushort.TryParse(args[index + 1], out ushort value))
|
||||
return false;
|
||||
|
||||
index++;
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
else
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!ushort.TryParse(val, out ushort value))
|
||||
return false;
|
||||
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string FormatFlags()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
Flags.ForEach(flag => sb.Append($"{flag}=, "));
|
||||
return sb.ToString().TrimEnd(' ', ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
96
SabreTools.CommandLine/Inputs/UInt32Input.cs
Normal file
96
SabreTools.CommandLine/Inputs/UInt32Input.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a user input bounded to the range of <see cref="uint"/>
|
||||
/// </summary>
|
||||
public class UInt32Input : UserInput<uint?>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public UInt32Input(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
public UInt32Input(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessInput(string[] args, ref int index)
|
||||
{
|
||||
// If the index is invalid
|
||||
if (index < 0 || index >= args.Length)
|
||||
return false;
|
||||
|
||||
// Get the current part
|
||||
string part = args[index];
|
||||
|
||||
// If the current flag doesn't match, check to see if any of the subfeatures are valid
|
||||
if (!ContainsFlag(part))
|
||||
{
|
||||
foreach (var kvp in Children)
|
||||
{
|
||||
if (kvp.Value.ProcessInput(args, ref index))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for space-separated
|
||||
if (!part.Contains("="))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= args.Length)
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!uint.TryParse(args[index + 1], out uint value))
|
||||
return false;
|
||||
|
||||
index++;
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
else
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!uint.TryParse(val, out uint value))
|
||||
return false;
|
||||
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string FormatFlags()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
Flags.ForEach(flag => sb.Append($"{flag}=, "));
|
||||
return sb.ToString().TrimEnd(' ', ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
96
SabreTools.CommandLine/Inputs/UInt64Input.cs
Normal file
96
SabreTools.CommandLine/Inputs/UInt64Input.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a user input bounded to the range of <see cref="ulong"/>
|
||||
/// </summary>
|
||||
public class UInt64Input : UserInput<ulong?>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public UInt64Input(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
public UInt64Input(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessInput(string[] args, ref int index)
|
||||
{
|
||||
// If the index is invalid
|
||||
if (index < 0 || index >= args.Length)
|
||||
return false;
|
||||
|
||||
// Get the current part
|
||||
string part = args[index];
|
||||
|
||||
// If the current flag doesn't match, check to see if any of the subfeatures are valid
|
||||
if (!ContainsFlag(part))
|
||||
{
|
||||
foreach (var kvp in Children)
|
||||
{
|
||||
if (kvp.Value.ProcessInput(args, ref index))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for space-separated
|
||||
if (!part.Contains("="))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= args.Length)
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!ulong.TryParse(args[index + 1], out ulong value))
|
||||
return false;
|
||||
|
||||
index++;
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
else
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!ulong.TryParse(val, out ulong value))
|
||||
return false;
|
||||
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string FormatFlags()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
Flags.ForEach(flag => sb.Append($"{flag}=, "));
|
||||
return sb.ToString().TrimEnd(' ', ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
96
SabreTools.CommandLine/Inputs/UInt8Input.cs
Normal file
96
SabreTools.CommandLine/Inputs/UInt8Input.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a user input bounded to the range of <see cref="byte"/>
|
||||
/// </summary>
|
||||
public class UInt8Input : UserInput<byte?>
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
public UInt8Input(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
public UInt8Input(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
Value = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override bool ProcessInput(string[] args, ref int index)
|
||||
{
|
||||
// If the index is invalid
|
||||
if (index < 0 || index >= args.Length)
|
||||
return false;
|
||||
|
||||
// Get the current part
|
||||
string part = args[index];
|
||||
|
||||
// If the current flag doesn't match, check to see if any of the subfeatures are valid
|
||||
if (!ContainsFlag(part))
|
||||
{
|
||||
foreach (var kvp in Children)
|
||||
{
|
||||
if (kvp.Value.ProcessInput(args, ref index))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for space-separated
|
||||
if (!part.Contains("="))
|
||||
{
|
||||
// Ensure the value exists
|
||||
if (index + 1 >= args.Length)
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!byte.TryParse(args[index + 1], out byte value))
|
||||
return false;
|
||||
|
||||
index++;
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for equal separated
|
||||
else
|
||||
{
|
||||
// Split the string, using the first equal sign as the separator
|
||||
string[] tempSplit = part.Split('=');
|
||||
string val = string.Join("=", tempSplit, 1, tempSplit.Length - 1);
|
||||
|
||||
// Ensure the value exists
|
||||
if (string.IsNullOrEmpty(val))
|
||||
return false;
|
||||
|
||||
// If the next value is valid
|
||||
if (!byte.TryParse(val, out byte value))
|
||||
return false;
|
||||
|
||||
Value = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override string FormatFlags()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
Flags.ForEach(flag => sb.Append($"{flag}=, "));
|
||||
return sb.ToString().TrimEnd(' ', ',');
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
874
SabreTools.CommandLine/Inputs/UserInput.cs
Normal file
874
SabreTools.CommandLine/Inputs/UserInput.cs
Normal file
@@ -0,0 +1,874 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single user input which may contain children
|
||||
/// </summary>
|
||||
public abstract class UserInput
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Display name for the feature
|
||||
/// </summary>
|
||||
public string Name { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set of children associated with this input
|
||||
/// </summary>
|
||||
public readonly Dictionary<string, UserInput> Children = [];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Set of flags associated with the feature
|
||||
/// </summary>
|
||||
protected readonly List<string> Flags = [];
|
||||
|
||||
/// <summary>
|
||||
/// Short description of the feature
|
||||
/// </summary>
|
||||
private readonly string _description;
|
||||
|
||||
/// <summary>
|
||||
/// Optional long description of the feature
|
||||
/// </summary>
|
||||
private readonly string? _longDescription;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
internal UserInput(string name, string flag, string description, string? longDescription = null)
|
||||
{
|
||||
Name = name;
|
||||
Flags.Add(flag);
|
||||
_description = description;
|
||||
_longDescription = longDescription;
|
||||
}
|
||||
|
||||
internal UserInput(string name, string[] flags, string description, string? longDescription = null)
|
||||
{
|
||||
Name = name;
|
||||
Flags.AddRange(flags);
|
||||
_description = description;
|
||||
_longDescription = longDescription;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Accessors
|
||||
|
||||
/// <summary>
|
||||
/// Directly address a given subfeature
|
||||
/// </summary>
|
||||
public UserInput? this[string name]
|
||||
{
|
||||
get { return Children.ContainsKey(name) ? Children[name] : null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Directly address a given subfeature
|
||||
/// </summary>
|
||||
public UserInput? this[UserInput subfeature]
|
||||
{
|
||||
get { return Children.ContainsKey(subfeature.Name) ? Children[subfeature.Name] : null; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a new child input
|
||||
/// </summary>
|
||||
public void Add(UserInput input)
|
||||
=> Children[input.Name] = input;
|
||||
|
||||
/// <summary>
|
||||
/// Returns if a flag exists for the current feature
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the flag to check</param>
|
||||
/// <returns>True if the flag was found, false otherwise</returns>
|
||||
public bool ContainsFlag(string name)
|
||||
=> Flags.Exists(f => f == name || name.StartsWith($"{f}="));
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the feature contains a flag that starts with the given character
|
||||
/// </summary>
|
||||
/// <param name="c">Character to check against</param>
|
||||
/// <returns>True if the flag was found, false otherwise</returns>
|
||||
public bool StartsWith(char c)
|
||||
=> Flags.Exists(f => f.TrimStart('-').ToLowerInvariant()[0] == c);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Children
|
||||
|
||||
/// <summary>
|
||||
/// Get a boolean value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>The value if found, the default value otherwise</returns>
|
||||
public bool GetBoolean(string key, bool defaultValue = false)
|
||||
{
|
||||
if (TryGetBoolean(key, out bool value, defaultValue))
|
||||
return value;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an Int8 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>The value if found, the default value otherwise</returns>
|
||||
public sbyte GetInt8(string key, sbyte defaultValue = sbyte.MinValue)
|
||||
{
|
||||
if (TryGetInt8(key, out sbyte value, defaultValue))
|
||||
return value;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an Int16 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>The value if found, the default value otherwise</returns>
|
||||
public short GetInt16(string key, short defaultValue = short.MinValue)
|
||||
{
|
||||
if (TryGetInt16(key, out short value, defaultValue))
|
||||
return value;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an Int32 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>The value if found, the default value otherwise</returns>
|
||||
public int GetInt32(string key, int defaultValue = int.MinValue)
|
||||
{
|
||||
if (TryGetInt32(key, out int value, defaultValue))
|
||||
return value;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an Int64 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>The value if found, the default value otherwise</returns>
|
||||
public long GetInt64(string key, long defaultValue = long.MinValue)
|
||||
{
|
||||
if (TryGetInt64(key, out long value, defaultValue))
|
||||
return value;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a string value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>The value if found, the default value otherwise</returns>
|
||||
public string? GetString(string key, string? defaultValue = null)
|
||||
{
|
||||
if (TryGetString(key, out string? value, defaultValue))
|
||||
return value;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a string list value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>The value if found, the default value otherwise</returns>
|
||||
public List<string> GetStringList(string key)
|
||||
{
|
||||
if (TryGetStringList(key, out var value))
|
||||
return value;
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a UInt8 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>The value if found, the default value otherwise</returns>
|
||||
public byte GetUInt8(string key, byte defaultValue = byte.MinValue)
|
||||
{
|
||||
if (TryGetUInt8(key, out byte value, defaultValue))
|
||||
return value;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a UInt16 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>The value if found, the default value otherwise</returns>
|
||||
public ushort GetUInt16(string key, ushort defaultValue = ushort.MinValue)
|
||||
{
|
||||
if (TryGetUInt16(key, out ushort value, defaultValue))
|
||||
return value;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a UInt32 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>The value if found, the default value otherwise</returns>
|
||||
public uint GetUInt32(string key, uint defaultValue = uint.MinValue)
|
||||
{
|
||||
if (TryGetUInt32(key, out uint value, defaultValue))
|
||||
return value;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a UInt64 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>The value if found, the default value otherwise</returns>
|
||||
public ulong GetUInt64(string key, ulong defaultValue = ulong.MinValue)
|
||||
{
|
||||
if (TryGetUInt64(key, out ulong value, defaultValue))
|
||||
return value;
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a boolean value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="value">Value that was found, default value otherwise</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>True if the value was found, false otherwise</returns>
|
||||
public bool TryGetBoolean(string key, out bool value, bool defaultValue = false)
|
||||
{
|
||||
// Try to check immediate children
|
||||
if (Children.TryGetValue(key, out var input))
|
||||
{
|
||||
if (input is BooleanInput b)
|
||||
{
|
||||
value = b.Value ?? defaultValue;
|
||||
return true;
|
||||
}
|
||||
else if (input is FlagInput f)
|
||||
{
|
||||
value = f.Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Feature is not a bool");
|
||||
}
|
||||
|
||||
// Check all children recursively
|
||||
foreach (var child in Children.Values)
|
||||
{
|
||||
if (child.TryGetBoolean(key, out value, defaultValue))
|
||||
return true;
|
||||
}
|
||||
|
||||
value = defaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an Int8 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="value">Value that was found, default value otherwise</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>True if the value was found, false otherwise</returns>
|
||||
public bool TryGetInt8(string key, out sbyte value, sbyte defaultValue = sbyte.MinValue)
|
||||
{
|
||||
// Try to check immediate children
|
||||
if (Children.TryGetValue(key, out var input))
|
||||
{
|
||||
if (input is not Int8Input i)
|
||||
throw new ArgumentException("Feature is not an sbyte");
|
||||
|
||||
value = i.Value ?? defaultValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check all children recursively
|
||||
foreach (var child in Children.Values)
|
||||
{
|
||||
if (child.TryGetInt8(key, out value, defaultValue))
|
||||
return true;
|
||||
}
|
||||
|
||||
value = defaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an Int16 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="value">Value that was found, default value otherwise</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>True if the value was found, false otherwise</returns>
|
||||
public bool TryGetInt16(string key, out short value, short defaultValue = short.MinValue)
|
||||
{
|
||||
// Try to check immediate children
|
||||
if (Children.TryGetValue(key, out var input))
|
||||
{
|
||||
if (input is not Int16Input i)
|
||||
throw new ArgumentException("Feature is not a short");
|
||||
|
||||
value = i.Value ?? defaultValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check all children recursively
|
||||
foreach (var child in Children.Values)
|
||||
{
|
||||
if (child.TryGetInt16(key, out value, defaultValue))
|
||||
return true;
|
||||
}
|
||||
|
||||
value = defaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an Int32 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="value">Value that was found, default value otherwise</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>True if the value was found, false otherwise</returns>
|
||||
public bool TryGetInt32(string key, out int value, int defaultValue = int.MinValue)
|
||||
{
|
||||
// Try to check immediate children
|
||||
if (Children.TryGetValue(key, out var input))
|
||||
{
|
||||
if (input is not Int32Input i)
|
||||
throw new ArgumentException("Feature is not an int");
|
||||
|
||||
value = i.Value ?? defaultValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check all children recursively
|
||||
foreach (var child in Children.Values)
|
||||
{
|
||||
if (child.TryGetInt32(key, out value, defaultValue))
|
||||
return true;
|
||||
}
|
||||
|
||||
value = defaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get an Int64 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="value">Value that was found, default value otherwise</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>True if the value was found, false otherwise</returns>
|
||||
public bool TryGetInt64(string key, out long value, long defaultValue = long.MinValue)
|
||||
{
|
||||
// Try to check immediate children
|
||||
if (Children.TryGetValue(key, out var input))
|
||||
{
|
||||
if (input is not Int64Input l)
|
||||
throw new ArgumentException("Feature is not a long");
|
||||
|
||||
value = l.Value ?? defaultValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check all children recursively
|
||||
foreach (var child in Children.Values)
|
||||
{
|
||||
if (child.TryGetInt64(key, out value, defaultValue))
|
||||
return true;
|
||||
}
|
||||
|
||||
value = defaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a string value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="value">Value that was found, default value otherwise</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>True if the value was found, false otherwise</returns>
|
||||
public bool TryGetString(string key, out string? value, string? defaultValue = null)
|
||||
{
|
||||
// Try to check immediate children
|
||||
if (Children.TryGetValue(key, out var input))
|
||||
{
|
||||
if (input is not StringInput s)
|
||||
throw new ArgumentException("Feature is not a string");
|
||||
|
||||
value = s.Value ?? defaultValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check all children recursively
|
||||
foreach (var child in Children.Values)
|
||||
{
|
||||
if (child.TryGetString(key, out value, defaultValue))
|
||||
return true;
|
||||
}
|
||||
|
||||
value = defaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a string list value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="value">Value that was found, default value otherwise</param>
|
||||
/// <returns>True if the value was found, false otherwise</returns>
|
||||
public bool TryGetStringList(string key, out List<string> value)
|
||||
{
|
||||
// Try to check immediate children
|
||||
if (Children.TryGetValue(key, out var input))
|
||||
{
|
||||
if (input is not StringListInput l)
|
||||
throw new ArgumentException("Feature is not a list");
|
||||
|
||||
value = l.Value ?? [];
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check all children recursively
|
||||
foreach (var child in Children.Values)
|
||||
{
|
||||
if (child.TryGetStringList(key, out value))
|
||||
return true;
|
||||
}
|
||||
|
||||
value = [];
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a UInt8 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="value">Value that was found, default value otherwise</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>True if the value was found, false otherwise</returns>
|
||||
public bool TryGetUInt8(string key, out byte value, byte defaultValue = byte.MinValue)
|
||||
{
|
||||
// Try to check immediate children
|
||||
if (Children.TryGetValue(key, out var input))
|
||||
{
|
||||
if (input is not UInt8Input i)
|
||||
throw new ArgumentException("Feature is not an byte");
|
||||
|
||||
value = i.Value ?? defaultValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check all children recursively
|
||||
foreach (var child in Children.Values)
|
||||
{
|
||||
if (child.TryGetUInt8(key, out value, defaultValue))
|
||||
return true;
|
||||
}
|
||||
|
||||
value = defaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a UInt16 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="value">Value that was found, default value otherwise</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>True if the value was found, false otherwise</returns>
|
||||
public bool TryGetUInt16(string key, out ushort value, ushort defaultValue = ushort.MinValue)
|
||||
{
|
||||
// Try to check immediate children
|
||||
if (Children.TryGetValue(key, out var input))
|
||||
{
|
||||
if (input is not UInt16Input i)
|
||||
throw new ArgumentException("Feature is not a ushort");
|
||||
|
||||
value = i.Value ?? defaultValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check all children recursively
|
||||
foreach (var child in Children.Values)
|
||||
{
|
||||
if (child.TryGetUInt16(key, out value, defaultValue))
|
||||
return true;
|
||||
}
|
||||
|
||||
value = defaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a UInt32 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="value">Value that was found, default value otherwise</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>True if the value was found, false otherwise</returns>
|
||||
public bool TryGetUInt32(string key, out uint value, uint defaultValue = uint.MinValue)
|
||||
{
|
||||
// Try to check immediate children
|
||||
if (Children.TryGetValue(key, out var input))
|
||||
{
|
||||
if (input is not UInt32Input i)
|
||||
throw new ArgumentException("Feature is not an uint");
|
||||
|
||||
value = i.Value ?? defaultValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check all children recursively
|
||||
foreach (var child in Children.Values)
|
||||
{
|
||||
if (child.TryGetUInt32(key, out value, defaultValue))
|
||||
return true;
|
||||
}
|
||||
|
||||
value = defaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a UInt64 value from a named input
|
||||
/// </summary>
|
||||
/// <param name="key">Input name to retrieve, if possible</param>
|
||||
/// <param name="value">Value that was found, default value otherwise</param>
|
||||
/// <param name="defaultValue">Optional default value if not found</param>
|
||||
/// <returns>True if the value was found, false otherwise</returns>
|
||||
public bool TryGetUInt64(string key, out ulong value, ulong defaultValue = ulong.MinValue)
|
||||
{
|
||||
// Try to check immediate children
|
||||
if (Children.TryGetValue(key, out var input))
|
||||
{
|
||||
if (input is not UInt64Input l)
|
||||
throw new ArgumentException("Feature is not a ulong");
|
||||
|
||||
value = l.Value ?? defaultValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check all children recursively
|
||||
foreach (var child in Children.Values)
|
||||
{
|
||||
if (child.TryGetUInt64(key, out value, defaultValue))
|
||||
return true;
|
||||
}
|
||||
|
||||
value = defaultValue;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Processing
|
||||
|
||||
/// <summary>
|
||||
/// Validate whether a flag is valid for this feature or not
|
||||
/// </summary>
|
||||
/// <param name="args">Set of arguments to parse</param>
|
||||
/// <param name="index">Reference index into the argument set</param>
|
||||
/// <returns>True if the flag was valid, false otherwise</returns>
|
||||
public abstract bool ProcessInput(string[] args, ref int index);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Output
|
||||
|
||||
/// <summary>
|
||||
/// Output this feature only
|
||||
/// </summary>
|
||||
/// <param name="pre">Positive number representing number of spaces to put in front of the feature</param>
|
||||
/// <param name="midpoint">Positive number representing the column where the description should start</param>
|
||||
/// <param name="includeLongDescription">True if the long description should be formatted and output, false otherwise</param>
|
||||
public List<string> Output(int pre = 0, int midpoint = 0, bool includeLongDescription = false)
|
||||
{
|
||||
// Create the output list
|
||||
List<string> outputList = [];
|
||||
|
||||
// Build the output string first
|
||||
var output = new StringBuilder();
|
||||
|
||||
// Add the pre-space first
|
||||
output.Append(CreatePadding(pre));
|
||||
|
||||
// Preprocess and add the flags
|
||||
output.Append(FormatFlags());
|
||||
|
||||
// If we have a midpoint set, check to see if the string needs padding
|
||||
if (midpoint > 0 && output.ToString().Length < midpoint)
|
||||
output.Append(CreatePadding(midpoint - output.ToString().Length));
|
||||
else
|
||||
output.Append(" ");
|
||||
|
||||
// Append the description
|
||||
output.Append(_description);
|
||||
|
||||
// Now append it to the list
|
||||
outputList.Add(output.ToString());
|
||||
|
||||
// If we are outputting the long description, format it and then add it as well
|
||||
if (includeLongDescription)
|
||||
{
|
||||
// Get the width of the console for wrapping reference
|
||||
int width = (Console.WindowWidth == 0 ? 80 : Console.WindowWidth) - 1;
|
||||
|
||||
// Prepare the output string
|
||||
#if NET20 || NET35
|
||||
output = new();
|
||||
#else
|
||||
output.Clear();
|
||||
#endif
|
||||
output.Append(CreatePadding(pre + 4));
|
||||
|
||||
// Now split the input description and start processing
|
||||
string[]? split = _longDescription?.Split(' ');
|
||||
if (split == null)
|
||||
return outputList;
|
||||
|
||||
for (int i = 0; i < split.Length; i++)
|
||||
{
|
||||
// If we have a newline character, reset the line and continue
|
||||
if (split[i].Contains("\n"))
|
||||
{
|
||||
string[] subsplit = split[i].Replace("\r", string.Empty).Split('\n');
|
||||
for (int j = 0; j < subsplit.Length - 1; j++)
|
||||
{
|
||||
// Add the next word only if the total length doesn't go above the width of the screen
|
||||
if (output.ToString().Length + subsplit[j].Length < width)
|
||||
{
|
||||
output.Append((output.ToString().Length == pre + 4 ? string.Empty : " ") + subsplit[j]);
|
||||
}
|
||||
// Otherwise, we want to cache the line to output and create a new blank string
|
||||
else
|
||||
{
|
||||
outputList.Add(output.ToString());
|
||||
#if NET20 || NET35
|
||||
output = new();
|
||||
#else
|
||||
output.Clear();
|
||||
#endif
|
||||
output.Append(CreatePadding(pre + 4));
|
||||
output.Append((output.ToString().Length == pre + 4 ? string.Empty : " ") + subsplit[j]);
|
||||
}
|
||||
|
||||
outputList.Add(output.ToString());
|
||||
#if NET20 || NET35
|
||||
output = new();
|
||||
#else
|
||||
output.Clear();
|
||||
#endif
|
||||
output.Append(CreatePadding(pre + 4));
|
||||
}
|
||||
|
||||
output.Append(subsplit[subsplit.Length - 1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the next word only if the total length doesn't go above the width of the screen
|
||||
if (output.ToString().Length + split[i].Length < width)
|
||||
{
|
||||
output.Append((output.ToString().Length == pre + 4 ? string.Empty : " ") + split[i]);
|
||||
}
|
||||
// Otherwise, we want to cache the line to output and create a new blank string
|
||||
else
|
||||
{
|
||||
outputList.Add(output.ToString());
|
||||
output.Append(CreatePadding(pre + 4));
|
||||
output.Append((output.ToString().Length == pre + 4 ? string.Empty : " ") + split[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the last created output and a blank line for clarity
|
||||
outputList.Add(output.ToString());
|
||||
outputList.Add(string.Empty);
|
||||
}
|
||||
|
||||
return outputList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output this feature and all subfeatures
|
||||
/// </summary>
|
||||
/// <param name="tabLevel">Level of indentation for this feature</param>
|
||||
/// <param name="pre">Positive number representing number of spaces to put in front of the feature</param>
|
||||
/// <param name="midpoint">Positive number representing the column where the description should start</param>
|
||||
/// <param name="includeLongDescription">True if the long description should be formatted and output, false otherwise</param>
|
||||
public List<string> OutputRecursive(int tabLevel, int pre = 0, int midpoint = 0, bool includeLongDescription = false)
|
||||
{
|
||||
// Create the output list
|
||||
List<string> outputList = [];
|
||||
|
||||
// Build the output string first
|
||||
var output = new StringBuilder();
|
||||
|
||||
// Normalize based on the tab level
|
||||
int preAdjusted = pre;
|
||||
int midpointAdjusted = midpoint;
|
||||
if (tabLevel > 0)
|
||||
{
|
||||
preAdjusted += 4 * tabLevel;
|
||||
midpointAdjusted += 4 * tabLevel;
|
||||
}
|
||||
|
||||
// Add the pre-space first
|
||||
output.Append(CreatePadding(preAdjusted));
|
||||
|
||||
// Preprocess and add the flags
|
||||
output.Append(FormatFlags());
|
||||
|
||||
// If we have a midpoint set, check to see if the string needs padding
|
||||
if (midpoint > 0 && output.ToString().Length < midpointAdjusted)
|
||||
output.Append(CreatePadding(midpointAdjusted - output.ToString().Length));
|
||||
else
|
||||
output.Append(" ");
|
||||
|
||||
// Append the description
|
||||
output.Append(_description);
|
||||
|
||||
// Now append it to the list
|
||||
outputList.Add(output.ToString());
|
||||
|
||||
// If we are outputting the long description, format it and then add it as well
|
||||
if (includeLongDescription)
|
||||
{
|
||||
// Get the width of the console for wrapping reference
|
||||
int width = (Console.WindowWidth == 0 ? 80 : Console.WindowWidth) - 1;
|
||||
|
||||
// Prepare the output string
|
||||
#if NET20 || NET35
|
||||
output = new();
|
||||
#else
|
||||
output.Clear();
|
||||
#endif
|
||||
output.Append(CreatePadding(preAdjusted + 4));
|
||||
|
||||
// Now split the input description and start processing
|
||||
string[]? split = _longDescription?.Split(' ');
|
||||
if (split == null)
|
||||
return outputList;
|
||||
|
||||
for (int i = 0; i < split.Length; i++)
|
||||
{
|
||||
// If we have a newline character, reset the line and continue
|
||||
if (split[i].Contains("\n"))
|
||||
{
|
||||
string[] subsplit = split[i].Replace("\r", string.Empty).Split('\n');
|
||||
for (int j = 0; j < subsplit.Length - 1; j++)
|
||||
{
|
||||
// Add the next word only if the total length doesn't go above the width of the screen
|
||||
if (output.ToString().Length + subsplit[j].Length < width)
|
||||
{
|
||||
output.Append((output.ToString().Length == preAdjusted + 4 ? string.Empty : " ") + subsplit[j]);
|
||||
}
|
||||
// Otherwise, we want to cache the line to output and create a new blank string
|
||||
else
|
||||
{
|
||||
outputList.Add(output.ToString());
|
||||
#if NET20 || NET35
|
||||
output = new();
|
||||
#else
|
||||
output.Clear();
|
||||
#endif
|
||||
output.Append(CreatePadding(preAdjusted + 4));
|
||||
output.Append((output.ToString().Length == preAdjusted + 4 ? string.Empty : " ") + subsplit[j]);
|
||||
}
|
||||
|
||||
outputList.Add(output.ToString());
|
||||
#if NET20 || NET35
|
||||
output = new();
|
||||
#else
|
||||
output.Clear();
|
||||
#endif
|
||||
output.Append(CreatePadding(preAdjusted + 4));
|
||||
}
|
||||
|
||||
output.Append(subsplit[subsplit.Length - 1]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add the next word only if the total length doesn't go above the width of the screen
|
||||
if (output.ToString().Length + split[i].Length < width)
|
||||
{
|
||||
output.Append((output.ToString().Length == preAdjusted + 4 ? string.Empty : " ") + split[i]);
|
||||
}
|
||||
// Otherwise, we want to cache the line to output and create a new blank string
|
||||
else
|
||||
{
|
||||
outputList.Add(output.ToString());
|
||||
#if NET20 || NET35
|
||||
output = new();
|
||||
#else
|
||||
output.Clear();
|
||||
#endif
|
||||
output.Append(CreatePadding(preAdjusted + 4));
|
||||
output.Append((output.ToString().Length == preAdjusted + 4 ? string.Empty : " ") + split[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Add the last created output and a blank line for clarity
|
||||
outputList.Add(output.ToString());
|
||||
outputList.Add(string.Empty);
|
||||
}
|
||||
|
||||
// Now let's append all subfeatures
|
||||
foreach (string feature in Children.Keys)
|
||||
{
|
||||
outputList.AddRange(Children[feature]!.OutputRecursive(tabLevel + 1, pre, midpoint, includeLongDescription));
|
||||
}
|
||||
|
||||
return outputList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pre-format the flags for output
|
||||
/// </summary>
|
||||
protected abstract string FormatFlags();
|
||||
|
||||
/// <summary>
|
||||
/// Create a padding space based on the given length
|
||||
/// </summary>
|
||||
/// <param name="spaces">Number of padding spaces to add</param>
|
||||
/// <returns>String with requested number of blank spaces</returns>
|
||||
private static string CreatePadding(int spaces) => string.Empty.PadRight(spaces);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
37
SabreTools.CommandLine/Inputs/UserInputT.cs
Normal file
37
SabreTools.CommandLine/Inputs/UserInputT.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
namespace SabreTools.CommandLine.Inputs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single user input which may contain children
|
||||
/// </summary>
|
||||
public abstract class UserInput<T> : UserInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Typed value provided by the user
|
||||
/// </summary>
|
||||
public T? Value { get; protected set; }
|
||||
|
||||
#region Constructors
|
||||
|
||||
internal UserInput(string name, string flag, string description, string? longDescription = null)
|
||||
: base(name, flag, description, longDescription)
|
||||
{
|
||||
}
|
||||
|
||||
internal UserInput(string name, string[] flags, string description, string? longDescription = null)
|
||||
: base(name, flags, description, longDescription)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Instance Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override abstract bool ProcessInput(string[] args, ref int index);
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override abstract string FormatFlags();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
28
SabreTools.CommandLine/SabreTools.CommandLine.csproj
Executable file
28
SabreTools.CommandLine/SabreTools.CommandLine.csproj
Executable file
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Assembly Properties -->
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>1.2.1</Version>
|
||||
|
||||
<!-- Package Properties -->
|
||||
<Authors>Matt Nadareski</Authors>
|
||||
<Copyright>Copyright (c)2016-2025 Matt Nadareski</Copyright>
|
||||
<PackageProjectUrl>https://github.com/SabreTools/</PackageProjectUrl>
|
||||
<RepositoryUrl>https://github.com/SabreTools/SabreTools</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="SabreTools.CommandLine.Test" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
36
publish-nix.sh
Executable file
36
publish-nix.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#! /bin/bash
|
||||
|
||||
# This batch file assumes the following:
|
||||
# - .NET 9.0 (or newer) SDK is installed and in PATH
|
||||
#
|
||||
# If any of these are not satisfied, the operation may fail
|
||||
# in an unpredictable way and result in an incomplete output.
|
||||
|
||||
# Optional parameters
|
||||
NO_BUILD=false
|
||||
while getopts "b" OPTION
|
||||
do
|
||||
case $OPTION in
|
||||
b)
|
||||
NO_BUILD=true
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option provided"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Set the current directory as a variable
|
||||
BUILD_FOLDER=$PWD
|
||||
|
||||
# Only build if requested
|
||||
if [ $NO_BUILD = false ]
|
||||
then
|
||||
# Restore Nuget packages for all builds
|
||||
echo "Restoring Nuget packages"
|
||||
dotnet restore
|
||||
|
||||
# Create Nuget Package
|
||||
dotnet pack SabreTools.CommandLine/SabreTools.CommandLine.csproj --output $BUILD_FOLDER
|
||||
fi
|
||||
26
publish-win.ps1
Normal file
26
publish-win.ps1
Normal file
@@ -0,0 +1,26 @@
|
||||
# This batch file assumes the following:
|
||||
# - .NET 9.0 (or newer) SDK is installed and in PATH
|
||||
#
|
||||
# If any of these are not satisfied, the operation may fail
|
||||
# in an unpredictable way and result in an incomplete output.
|
||||
|
||||
# Optional parameters
|
||||
param(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[Alias("NoBuild")]
|
||||
[switch]$NO_BUILD
|
||||
)
|
||||
|
||||
# Set the current directory as a variable
|
||||
$BUILD_FOLDER = $PSScriptRoot
|
||||
|
||||
# Only build if requested
|
||||
if (!$NO_BUILD.IsPresent)
|
||||
{
|
||||
# Restore Nuget packages for all builds
|
||||
Write-Host "Restoring Nuget packages"
|
||||
dotnet restore
|
||||
|
||||
# Create Nuget Package
|
||||
dotnet pack SabreTools.CommandLine\SabreTools.CommandLine.csproj --output $BUILD_FOLDER
|
||||
}
|
||||
Reference in New Issue
Block a user