mirror of
https://github.com/yaakov-h/Shamir.git
synced 2025-01-18 08:46:33 +00:00
line endings
This commit is contained in:
parent
42fba23dd6
commit
f45b840705
6 changed files with 473 additions and 472 deletions
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
* text=auto
|
112
shamir.sln
112
shamir.sln
|
@ -1,56 +1,56 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 16
|
# Visual Studio Version 16
|
||||||
VisualStudioVersion = 16.0.30114.105
|
VisualStudioVersion = 16.0.30114.105
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A5384980-CE26-4FC0-9894-0A7AE7915FA0}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{A5384980-CE26-4FC0-9894-0A7AE7915FA0}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "shamir", "src\console\shamir.csproj", "{5264C707-99B4-43B7-AD5C-5EDD8609E697}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "shamir", "src\console\shamir.csproj", "{5264C707-99B4-43B7-AD5C-5EDD8609E697}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{A1008129-BAE8-49BD-8807-D0A2E0082307}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{A1008129-BAE8-49BD-8807-D0A2E0082307}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "console.tests", "tests\console.tests\console.tests.csproj", "{9133E2DC-9E86-4DF9-A080-4122B0468FDE}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "console.tests", "tests\console.tests\console.tests.csproj", "{9133E2DC-9E86-4DF9-A080-4122B0468FDE}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
Debug|x86 = Debug|x86
|
Debug|x86 = Debug|x86
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
Release|x64 = Release|x64
|
Release|x64 = Release|x64
|
||||||
Release|x86 = Release|x86
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Debug|x64.Build.0 = Debug|Any CPU
|
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Debug|x86.ActiveCfg = Debug|Any CPU
|
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Debug|x86.Build.0 = Debug|Any CPU
|
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Release|Any CPU.Build.0 = Release|Any CPU
|
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Release|x64.ActiveCfg = Release|Any CPU
|
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Release|x64.Build.0 = Release|Any CPU
|
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Release|x86.ActiveCfg = Release|Any CPU
|
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Release|x86.Build.0 = Release|Any CPU
|
{5264C707-99B4-43B7-AD5C-5EDD8609E697}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Debug|x64.Build.0 = Debug|Any CPU
|
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Debug|x86.Build.0 = Debug|Any CPU
|
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Release|Any CPU.Build.0 = Release|Any CPU
|
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Release|x64.ActiveCfg = Release|Any CPU
|
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Release|x64.Build.0 = Release|Any CPU
|
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Release|x86.ActiveCfg = Release|Any CPU
|
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Release|x86.Build.0 = Release|Any CPU
|
{9133E2DC-9E86-4DF9-A080-4122B0468FDE}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{5264C707-99B4-43B7-AD5C-5EDD8609E697} = {A5384980-CE26-4FC0-9894-0A7AE7915FA0}
|
{5264C707-99B4-43B7-AD5C-5EDD8609E697} = {A5384980-CE26-4FC0-9894-0A7AE7915FA0}
|
||||||
{9133E2DC-9E86-4DF9-A080-4122B0468FDE} = {A1008129-BAE8-49BD-8807-D0A2E0082307}
|
{9133E2DC-9E86-4DF9-A080-4122B0468FDE} = {A1008129-BAE8-49BD-8807-D0A2E0082307}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
@ -1,155 +1,155 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommandLine;
|
using CommandLine;
|
||||||
using CommandLine.Text;
|
using CommandLine.Text;
|
||||||
using SysConsole = System.Console;
|
using SysConsole = System.Console;
|
||||||
|
|
||||||
namespace Shamir.Console
|
namespace Shamir.Console
|
||||||
{
|
{
|
||||||
public class CdnOperations : ICommandSet
|
public class CdnOperations : ICommandSet
|
||||||
{
|
{
|
||||||
[Verb("ls", HelpText = "List files on the CDN")]
|
[Verb("ls", HelpText = "List files on the CDN")]
|
||||||
public class CdnLsOptions
|
public class CdnLsOptions
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Verb("add", HelpText = "Upload a file to the CDN")]
|
[Verb("add", HelpText = "Upload a file to the CDN")]
|
||||||
public class CdnAddOptions
|
public class CdnAddOptions
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[Verb("mv", HelpText = "Move a file to the CDN")]
|
[Verb("mv", HelpText = "Move a file to the CDN")]
|
||||||
public class CdnMvOptions
|
public class CdnMvOptions
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<Type> VerbOptionTypes
|
public static IEnumerable<Type> VerbOptionTypes
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
yield return typeof(CdnLsOptions);
|
yield return typeof(CdnLsOptions);
|
||||||
yield return typeof(CdnAddOptions);
|
yield return typeof(CdnAddOptions);
|
||||||
yield return typeof(CdnMvOptions);
|
yield return typeof(CdnMvOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICommand? FindCommand(ReadOnlySpan<string> args)
|
public ICommand? FindCommand(ReadOnlySpan<string> args)
|
||||||
{
|
{
|
||||||
if (args.Length == 0) return null;
|
if (args.Length == 0) return null;
|
||||||
|
|
||||||
var parserResult = Parser.Default.ParseArguments<CdnLsOptions, CdnAddOptions, CdnMvOptions>(args.ToArray());
|
var parserResult = Parser.Default.ParseArguments<CdnLsOptions, CdnAddOptions, CdnMvOptions>(args.ToArray());
|
||||||
return parserResult.MapResult<CdnLsOptions, CdnAddOptions, CdnMvOptions, ICommand>(
|
return parserResult.MapResult<CdnLsOptions, CdnAddOptions, CdnMvOptions, ICommand>(
|
||||||
options => new CdnLsCommand(options),
|
options => new CdnLsCommand(options),
|
||||||
options => new CdnAddCommand(options),
|
options => new CdnAddCommand(options),
|
||||||
options => new CdnMvCommand(options),
|
options => new CdnMvCommand(options),
|
||||||
errors => new HelpTextCommand(parserResult)
|
errors => new HelpTextCommand(parserResult)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CdnLsCommand : ICommand
|
public class CdnLsCommand : ICommand
|
||||||
{
|
{
|
||||||
public CdnLsCommand(CdnLsOptions options)
|
public CdnLsCommand(CdnLsOptions options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<int> ExecuteAsync()
|
public ValueTask<int> ExecuteAsync()
|
||||||
{
|
{
|
||||||
SysConsole.WriteLine($"Executing: cdn-ls");
|
SysConsole.WriteLine($"Executing: cdn-ls");
|
||||||
return ValueTask.FromResult(0);
|
return ValueTask.FromResult(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CdnAddCommand : ICommand
|
public class CdnAddCommand : ICommand
|
||||||
{
|
{
|
||||||
public CdnAddCommand(CdnAddOptions options)
|
public CdnAddCommand(CdnAddOptions options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<int> ExecuteAsync()
|
public ValueTask<int> ExecuteAsync()
|
||||||
{
|
{
|
||||||
SysConsole.WriteLine($"Executing: cdn-add");
|
SysConsole.WriteLine($"Executing: cdn-add");
|
||||||
return ValueTask.FromResult(0);
|
return ValueTask.FromResult(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CdnMvCommand : ICommand
|
public class CdnMvCommand : ICommand
|
||||||
{
|
{
|
||||||
public CdnMvCommand(CdnMvOptions options)
|
public CdnMvCommand(CdnMvOptions options)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public ValueTask<int> ExecuteAsync()
|
public ValueTask<int> ExecuteAsync()
|
||||||
{
|
{
|
||||||
SysConsole.WriteLine($"Executing: cdn-mv");
|
SysConsole.WriteLine($"Executing: cdn-mv");
|
||||||
return ValueTask.FromResult(0);
|
return ValueTask.FromResult(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HelpTextCommand : ICommand
|
public class HelpTextCommand : ICommand
|
||||||
{
|
{
|
||||||
public HelpTextCommand(ParserResult<object> result)
|
public HelpTextCommand(ParserResult<object> result)
|
||||||
{
|
{
|
||||||
this.result = result ?? throw new ArgumentNullException(nameof(result));
|
this.result = result ?? throw new ArgumentNullException(nameof(result));
|
||||||
Debug.Assert(result.Tag == ParserResultType.NotParsed);
|
Debug.Assert(result.Tag == ParserResultType.NotParsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly ParserResult<object> result;
|
readonly ParserResult<object> result;
|
||||||
|
|
||||||
public ValueTask<int> ExecuteAsync()
|
public ValueTask<int> ExecuteAsync()
|
||||||
{
|
{
|
||||||
var helpText = HelpText.AutoBuild(result);
|
var helpText = HelpText.AutoBuild(result);
|
||||||
SysConsole.Error.WriteLine(helpText);
|
SysConsole.Error.WriteLine(helpText);
|
||||||
return ValueTask.FromResult(1);
|
return ValueTask.FromResult(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ICommand
|
public interface ICommand
|
||||||
{
|
{
|
||||||
ValueTask<int> ExecuteAsync();
|
ValueTask<int> ExecuteAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ICommandSet
|
public interface ICommandSet
|
||||||
{
|
{
|
||||||
ICommand? FindCommand(ReadOnlySpan<string> args);
|
ICommand? FindCommand(ReadOnlySpan<string> args);
|
||||||
static IEnumerable<Type> VerbOptionTypes { get; }
|
static IEnumerable<Type> VerbOptionTypes { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CommandTree : ICommandSet
|
public class CommandTree : ICommandSet
|
||||||
{
|
{
|
||||||
IEnumerable<Type> VerbOptionTypes { get; }
|
IEnumerable<Type> VerbOptionTypes { get; }
|
||||||
public ICommand? FindCommand(ReadOnlySpan<string> args)
|
public ICommand? FindCommand(ReadOnlySpan<string> args)
|
||||||
{
|
{
|
||||||
if (args.Length == 0) return null;
|
if (args.Length == 0) return null;
|
||||||
|
|
||||||
return args[0] switch {
|
return args[0] switch {
|
||||||
"cdn" => new CdnOperations().FindCommand(args[1..]),
|
"cdn" => new CdnOperations().FindCommand(args[1..]),
|
||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
public static async Task<int> Main(string[] args)
|
public static async Task<int> Main(string[] args)
|
||||||
{
|
{
|
||||||
var tree = new CommandTree();
|
var tree = new CommandTree();
|
||||||
var command = tree.FindCommand(args);
|
var command = tree.FindCommand(args);
|
||||||
if (command is null)
|
if (command is null)
|
||||||
{
|
{
|
||||||
PrintHelpText(tree);
|
PrintHelpText(tree);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await command.ExecuteAsync();
|
return await command.ExecuteAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PrintHelpText(ICommandSet tree)
|
static void PrintHelpText(ICommandSet tree)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<RootNamespace>Shamir.Console</RootNamespace>
|
<RootNamespace>Shamir.Console</RootNamespace>
|
||||||
<OutputPath>..\..\bin</OutputPath>
|
<OutputPath>..\..\bin</OutputPath>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CommandLineParser" Version="2.8.0" />
|
<PackageReference Include="CommandLineParser" Version="2.8.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,228 +1,228 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace Shamir.Console.Tests
|
namespace Shamir.Console.Tests
|
||||||
{
|
{
|
||||||
public class CommandTreeTests
|
public class CommandTreeTests
|
||||||
{
|
{
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
tree = new DefaultCommandTree(
|
tree = new DefaultCommandTree(
|
||||||
"root",
|
"root",
|
||||||
"top level",
|
"top level",
|
||||||
ImmutableArray.Create<ICommandTree>(
|
ImmutableArray.Create<ICommandTree>(
|
||||||
new DefaultCommandTree(
|
new DefaultCommandTree(
|
||||||
"bar",
|
"bar",
|
||||||
"child command tree",
|
"child command tree",
|
||||||
ImmutableArray<ICommandTree>.Empty,
|
ImmutableArray<ICommandTree>.Empty,
|
||||||
ImmutableArray.Create<ICommand>(
|
ImmutableArray.Create<ICommand>(
|
||||||
new SimpleTextCommand("one", "bar/1 command"),
|
new SimpleTextCommand("one", "bar/1 command"),
|
||||||
new SimpleTextCommand("two", "bar/2 command")
|
new SimpleTextCommand("two", "bar/2 command")
|
||||||
))),
|
))),
|
||||||
ImmutableArray.Create<ICommand>(
|
ImmutableArray.Create<ICommand>(
|
||||||
new SimpleTextCommand("foo", "foo command")
|
new SimpleTextCommand("foo", "foo command")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
ICommandTree tree;
|
ICommandTree tree;
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ConstructsHelpTextWithNoArgs()
|
public void ConstructsHelpTextWithNoArgs()
|
||||||
{
|
{
|
||||||
var command = tree.FindCommand(Array.Empty<string>());
|
var command = tree.FindCommand(Array.Empty<string>());
|
||||||
Assert.That(command, Is.InstanceOf<DefaultHelpTextCommand>());
|
Assert.That(command, Is.InstanceOf<DefaultHelpTextCommand>());
|
||||||
var helpText = ((DefaultHelpTextCommand)command).GetHelpText();
|
var helpText = ((DefaultHelpTextCommand)command).GetHelpText();
|
||||||
Assert.That(helpText, Is.EqualTo(@"
|
Assert.That(helpText, Is.EqualTo(@"
|
||||||
Group
|
Group
|
||||||
root : top level
|
root : top level
|
||||||
|
|
||||||
Subgroups:
|
Subgroups:
|
||||||
bar : child command tree
|
bar : child command tree
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
foo : foo command
|
foo : foo command
|
||||||
".TrimStart()));
|
".TrimStart()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ConstructsHelpTextForSubTree()
|
public void ConstructsHelpTextForSubTree()
|
||||||
{
|
{
|
||||||
var command = tree.FindCommand(new[] { "bar" });
|
var command = tree.FindCommand(new[] { "bar" });
|
||||||
Assert.That(command, Is.InstanceOf<DefaultHelpTextCommand>());
|
Assert.That(command, Is.InstanceOf<DefaultHelpTextCommand>());
|
||||||
var helpText = ((DefaultHelpTextCommand)command).GetHelpText();
|
var helpText = ((DefaultHelpTextCommand)command).GetHelpText();
|
||||||
Assert.That(helpText, Is.EqualTo(@"
|
Assert.That(helpText, Is.EqualTo(@"
|
||||||
Group
|
Group
|
||||||
root bar : child command tree
|
root bar : child command tree
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
one : bar/1 command
|
one : bar/1 command
|
||||||
two : bar/1 command
|
two : bar/1 command
|
||||||
"));
|
"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase((object)new string[] { "foo" }, ExpectedResult = "foo command")]
|
[TestCase((object)new string[] { "foo" }, ExpectedResult = "foo command")]
|
||||||
[TestCase((object)new string[] { "bar", "one" }, ExpectedResult = "bar/1 command")]
|
[TestCase((object)new string[] { "bar", "one" }, ExpectedResult = "bar/1 command")]
|
||||||
[TestCase((object)new string[] { "bar", "two" }, ExpectedResult = "bar/2 command")]
|
[TestCase((object)new string[] { "bar", "two" }, ExpectedResult = "bar/2 command")]
|
||||||
public string FindsCommand(string[] args)
|
public string FindsCommand(string[] args)
|
||||||
{
|
{
|
||||||
var command = tree.FindCommand(args);
|
var command = tree.FindCommand(args);
|
||||||
return command?.Description;
|
return command?.Description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SimpleTextCommand : ICommand
|
class SimpleTextCommand : ICommand
|
||||||
{
|
{
|
||||||
public SimpleTextCommand(string name, string description)
|
public SimpleTextCommand(string name, string description)
|
||||||
{
|
{
|
||||||
Name = name ?? throw new ArgumentNullException(nameof(name));
|
Name = name ?? throw new ArgumentNullException(nameof(name));
|
||||||
Description = description ?? throw new ArgumentNullException(nameof(description));
|
Description = description ?? throw new ArgumentNullException(nameof(description));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
|
||||||
public string Description { get; }
|
public string Description { get; }
|
||||||
|
|
||||||
public ValueTask<int> ExecuteAsync()
|
public ValueTask<int> ExecuteAsync()
|
||||||
{
|
{
|
||||||
return ValueTask.FromResult(0);
|
return ValueTask.FromResult(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IOperationsNode
|
interface IOperationsNode
|
||||||
{
|
{
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
string Description { get; }
|
string Description { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ICommand : IOperationsNode
|
interface ICommand : IOperationsNode
|
||||||
{
|
{
|
||||||
ValueTask<int> ExecuteAsync();
|
ValueTask<int> ExecuteAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ICommandTree : IOperationsNode
|
interface ICommandTree : IOperationsNode
|
||||||
{
|
{
|
||||||
ImmutableArray<ICommandTree> SubTrees { get; }
|
ImmutableArray<ICommandTree> SubTrees { get; }
|
||||||
ImmutableArray<ICommand> Commands { get; }
|
ImmutableArray<ICommand> Commands { get; }
|
||||||
ICommand FindCommand(ReadOnlySpan<string> args);
|
ICommand FindCommand(ReadOnlySpan<string> args);
|
||||||
}
|
}
|
||||||
|
|
||||||
class DefaultCommandTree : ICommandTree
|
class DefaultCommandTree : ICommandTree
|
||||||
{
|
{
|
||||||
public DefaultCommandTree(string name, string description, ImmutableArray<ICommandTree> subtrees, ImmutableArray<ICommand> commands)
|
public DefaultCommandTree(string name, string description, ImmutableArray<ICommandTree> subtrees, ImmutableArray<ICommand> commands)
|
||||||
{
|
{
|
||||||
this.Name = name ?? throw new ArgumentNullException(nameof(name));
|
this.Name = name ?? throw new ArgumentNullException(nameof(name));
|
||||||
this.Description = description ?? throw new ArgumentNullException(nameof(description));
|
this.Description = description ?? throw new ArgumentNullException(nameof(description));
|
||||||
this.SubTrees = subtrees;
|
this.SubTrees = subtrees;
|
||||||
this.Commands = commands;
|
this.Commands = commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public string Description { get; }
|
public string Description { get; }
|
||||||
public ImmutableArray<ICommandTree> SubTrees { get; }
|
public ImmutableArray<ICommandTree> SubTrees { get; }
|
||||||
public ImmutableArray<ICommand> Commands { get; }
|
public ImmutableArray<ICommand> Commands { get; }
|
||||||
|
|
||||||
public ICommand FindCommand(ReadOnlySpan<string> args)
|
public ICommand FindCommand(ReadOnlySpan<string> args)
|
||||||
{
|
{
|
||||||
if (args.Length > 0)
|
if (args.Length > 0)
|
||||||
{
|
{
|
||||||
foreach (var command in Commands)
|
foreach (var command in Commands)
|
||||||
{
|
{
|
||||||
if (command.Name == args[0])
|
if (command.Name == args[0])
|
||||||
{
|
{
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var tree in SubTrees)
|
foreach (var tree in SubTrees)
|
||||||
{
|
{
|
||||||
if (tree.Name == args[0])
|
if (tree.Name == args[0])
|
||||||
{
|
{
|
||||||
return tree.FindCommand(args[1..]);
|
return tree.FindCommand(args[1..]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DefaultHelpTextCommand(this);
|
return new DefaultHelpTextCommand(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DefaultHelpTextCommand : ICommand
|
class DefaultHelpTextCommand : ICommand
|
||||||
{
|
{
|
||||||
public DefaultHelpTextCommand(ICommandTree tree)
|
public DefaultHelpTextCommand(ICommandTree tree)
|
||||||
{
|
{
|
||||||
this.CommandTree = tree ?? throw new ArgumentNullException(nameof(tree));
|
this.CommandTree = tree ?? throw new ArgumentNullException(nameof(tree));
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name => "help";
|
public string Name => "help";
|
||||||
public string Description => "Print help text";
|
public string Description => "Print help text";
|
||||||
|
|
||||||
public ICommandTree CommandTree { get; }
|
public ICommandTree CommandTree { get; }
|
||||||
|
|
||||||
public ValueTask<int> ExecuteAsync()
|
public ValueTask<int> ExecuteAsync()
|
||||||
{
|
{
|
||||||
System.Console.Error.WriteLine(GetHelpText());
|
System.Console.Error.WriteLine(GetHelpText());
|
||||||
return ValueTask.FromResult(1); // TODO: const
|
return ValueTask.FromResult(1); // TODO: const
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetHelpText() => CommandTree.BuildHelpText();
|
public string GetHelpText() => CommandTree.BuildHelpText();
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ICommandTreeExtensions
|
static class ICommandTreeExtensions
|
||||||
{
|
{
|
||||||
public static string BuildHelpText(this ICommandTree tree)
|
public static string BuildHelpText(this ICommandTree tree)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
sb.AppendLine("Group");
|
sb.AppendLine("Group");
|
||||||
sb.Append(" ");
|
sb.Append(" ");
|
||||||
sb.AppendLine(tree.Name);
|
sb.AppendLine(tree.Name);
|
||||||
sb.AppendLine();
|
sb.AppendLine();
|
||||||
|
|
||||||
if (!tree.SubTrees.IsEmpty)
|
if (!tree.SubTrees.IsEmpty)
|
||||||
{
|
{
|
||||||
sb.AppendLine("Subgroups:");
|
sb.AppendLine("Subgroups:");
|
||||||
|
|
||||||
var maxSpacing = tree.SubTrees.Max(c => c.Name.Length) + 1;
|
var maxSpacing = tree.SubTrees.Max(c => c.Name.Length) + 1;
|
||||||
|
|
||||||
foreach (var child in tree.SubTrees)
|
foreach (var child in tree.SubTrees)
|
||||||
{
|
{
|
||||||
sb.Append(" ");
|
sb.Append(" ");
|
||||||
sb.Append(child.Name);
|
sb.Append(child.Name);
|
||||||
for (var i = 0; i < maxSpacing; i++)
|
for (var i = 0; i < maxSpacing; i++)
|
||||||
{
|
{
|
||||||
sb.Append(' ');
|
sb.Append(' ');
|
||||||
}
|
}
|
||||||
sb.Append(": ");
|
sb.Append(": ");
|
||||||
sb.AppendLine(child.Description);
|
sb.AppendLine(child.Description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tree.Commands.IsEmpty)
|
if (!tree.Commands.IsEmpty)
|
||||||
{
|
{
|
||||||
sb.AppendLine("Commands:");
|
sb.AppendLine("Commands:");
|
||||||
|
|
||||||
var maxSpacing = tree.Commands.Max(c => c.Name.Length) + 1;
|
var maxSpacing = tree.Commands.Max(c => c.Name.Length) + 1;
|
||||||
|
|
||||||
foreach (var command in tree.Commands)
|
foreach (var command in tree.Commands)
|
||||||
{
|
{
|
||||||
sb.Append(" ");
|
sb.Append(" ");
|
||||||
sb.Append(command.Name);
|
sb.Append(command.Name);
|
||||||
for (var i = 0; i < maxSpacing; i++)
|
for (var i = 0; i < maxSpacing; i++)
|
||||||
{
|
{
|
||||||
sb.Append(' ');
|
sb.Append(' ');
|
||||||
}
|
}
|
||||||
sb.Append(": ");
|
sb.Append(": ");
|
||||||
sb.AppendLine(command.Description);
|
sb.AppendLine(command.Description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,19 +1,19 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<RootNamespace>Shamir.Console.Tests</RootNamespace>
|
<RootNamespace>Shamir.Console.Tests</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.1" />
|
<PackageReference Include="NUnit" Version="3.13.1" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\console\shamir.csproj" />
|
<ProjectReference Include="..\..\src\console\shamir.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
Loading…
Reference in a new issue