├── .gitignore ├── Beverage ├── Beverage.csproj ├── Commands │ ├── BlackRussian.cs │ ├── Martini.cs │ └── WhiteRussian.cs └── Program.cs ├── Beverage_old ├── App.config ├── Beverage.csproj ├── Commands │ ├── BlackRussian.cs │ ├── Martini.cs │ └── WhiteRussian.cs ├── Program.cs └── Properties │ └── AssemblyInfo.cs ├── CHANGELOG.md ├── GoCommando.Tests ├── GoCommando.Tests.csproj ├── TestArgParser.cs └── TestCommand.cs ├── GoCommando.Tests_old ├── GoCommando.Tests.csproj ├── Properties │ └── AssemblyInfo.cs ├── TestArgParser.cs ├── TestCommand.cs └── packages.config ├── GoCommando.sln ├── GoCommando ├── BannerAttribute.cs ├── CommandAttribute.cs ├── DescriptionAttribute.cs ├── ExampleAttribute.cs ├── ExitCodeException.cs ├── Go.cs ├── GoCommando.csproj ├── GoCommandoException.cs ├── ICommand.cs ├── ICommandFactory.cs ├── Internals │ ├── Arguments.cs │ ├── CommandInvoker.cs │ ├── EnvironmentSettings.cs │ ├── InternalsVisibleTo.cs │ ├── Parameter.cs │ ├── Settings.cs │ ├── StringExtensions.cs │ └── Switch.cs ├── ParameterAttribute.cs └── SupportImpersonationAttribute.cs ├── GoCommando_old ├── BannerAttribute.cs ├── CommandAttribute.cs ├── DescriptionAttribute.cs ├── ExampleAttribute.cs ├── ExitCodeException.cs ├── Go.cs ├── GoCommando.csproj ├── GoCommandoException.cs ├── ICommand.cs ├── ICommandFactory.cs ├── Internals │ ├── Arguments.cs │ ├── CommandInvoker.cs │ ├── EnvironmentSettings.cs │ ├── Parameter.cs │ ├── Settings.cs │ ├── StringExtensions.cs │ └── Switch.cs ├── ParameterAttribute.cs ├── Properties │ └── AssemblyInfo.cs └── SupportImpersonationAttribute.cs ├── Package.nuspec ├── README.md ├── TestApp2_old ├── App.config ├── ElCommandante.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── TestApp2.csproj ├── TestApp_old ├── App.config ├── Commands │ ├── NewCommand.cs │ ├── RunCommand.cs │ ├── StopCommand.cs │ └── TestAppConfigBinding.cs ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── TestApp.csproj ├── build.cmd ├── nuget └── NuGet.exe ├── old ├── .gitignore ├── Package.nuspec ├── README.md ├── build.bat ├── lib │ ├── nunit │ │ └── nunit.framework.dll │ └── rhino │ │ ├── Rhino.Mocks.dll │ │ └── Rhino.Mocks.xml ├── scripts │ └── build.proj ├── src │ ├── GoCommando.ConsoleApplication │ │ ├── GoCommando.ConsoleApplication.csproj │ │ ├── Program.cs │ │ └── Properties │ │ │ └── AssemblyInfo.cs │ ├── GoCommando.Tests │ │ ├── FixtureBase.cs │ │ ├── GoCommando.Tests.csproj │ │ ├── Helpers │ │ │ ├── TestArgParser.cs │ │ │ ├── TestBinder.cs │ │ │ └── TestHelper.cs │ │ ├── Integration │ │ │ └── ErrorTestCases.cs │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ └── todo.txt │ ├── GoCommando.sln │ └── GoCommando │ │ ├── Api │ │ └── ICommando.cs │ │ ├── ArgumentAttribute.cs │ │ ├── Attributes │ │ ├── ArgumentAttribute.cs │ │ ├── BannerAttribute.cs │ │ ├── DescriptionAttribute.cs │ │ ├── ExampleAttribute.cs │ │ ├── NamedArgumentAttribute.cs │ │ └── PositionalArgumentAttribute.cs │ │ ├── BannerAttribute.cs │ │ ├── CommandLineParameter.cs │ │ ├── Exceptions │ │ └── CommandoException.cs │ │ ├── Extensions │ │ └── AttributeExtensions.cs │ │ ├── Go.cs │ │ ├── GoCommando.cs │ │ ├── GoCommando.csproj │ │ ├── GoCommando.nuspec │ │ ├── Helpers │ │ ├── ArgParser.cs │ │ ├── Binder.cs │ │ ├── BindingReport.cs │ │ ├── Helper.cs │ │ ├── IHasPositionerCounter.cs │ │ └── Parameter.cs │ │ ├── IGoCommando.cs │ │ ├── NamedArgumentAttribute.cs │ │ ├── NamedCommandLineParameter.cs │ │ ├── NamedFlagCommandLineParameter.cs │ │ ├── Parameters │ │ ├── CommandLineParameter.cs │ │ ├── NamedCommandLineParameter.cs │ │ └── PositionalCommandLineParameter.cs │ │ ├── PositionalArgumentAttribute.cs │ │ ├── PositionalCommandLineParameter.cs │ │ └── Properties │ │ └── AssemblyInfo.cs └── tools │ └── NuGet.exe ├── packages └── NUnit.2.6.4 │ ├── NUnit.2.6.4.nupkg │ ├── lib │ ├── nunit.framework.dll │ └── nunit.framework.xml │ └── license.txt ├── scripts ├── build.cmd ├── patch_assemblyinfo.cmd ├── push.cmd └── release.cmd └── tools └── NuGet └── nuget.exe /.gitignore: -------------------------------------------------------------------------------- 1 | obj 2 | bin 3 | deploy 4 | deploy/* 5 | _ReSharper.* 6 | *.csproj.user 7 | *.resharper.user 8 | *.ReSharper.user 9 | *.teamcity.user 10 | *.TeamCity.user 11 | *.resharper 12 | *.DotSettings.user 13 | *.dotsettings.user 14 | *.ncrunchproject 15 | *.ncrunchsolution 16 | *.suo 17 | *.cache 18 | ~$* 19 | asb_connection_string.txt 20 | sqs_connectionstring.txt 21 | azure_storage_connection_string.txt 22 | .vs 23 | .vs/* -------------------------------------------------------------------------------- /Beverage/Beverage.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Beverage/Commands/BlackRussian.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GoCommando; 3 | 4 | namespace Beverage.Commands 5 | { 6 | [Command("black-russian", group: "duderino")] 7 | [Description("Mixes a White Russian, pouring in milk till full")] 8 | public class BlackRussian : ICommand 9 | { 10 | [Parameter("vodka")] 11 | [Description("How many cl of vodka?")] 12 | public double Vodka { get; set; } 13 | 14 | [Parameter("kahlua")] 15 | [Description("How many cl of Kahlua?")] 16 | public double Kahlua { get; set; } 17 | 18 | [Parameter("lukewarm", optional: true)] 19 | [Description("Avoid refrigerated ingredients?")] 20 | public bool LukeWarm { get; set; } 21 | 22 | public void Run() 23 | { 24 | Console.WriteLine($"Making a {(LukeWarm ? "luke-warm" : "")} beverage" + 25 | $" with {Vodka:0.#} cl of vodka" + 26 | $" and {Kahlua:0.#} cl of Kahlua"); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Beverage/Commands/Martini.cs: -------------------------------------------------------------------------------- 1 | using GoCommando; 2 | 3 | namespace Beverage.Commands 4 | { 5 | [Command("martini", group: "simple")] 6 | [Description("It's just Martini.")] 7 | public class Martini : ICommand 8 | { 9 | public void Run() 10 | { 11 | throw new System.NotImplementedException(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Beverage/Commands/WhiteRussian.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GoCommando; 3 | 4 | namespace Beverage.Commands 5 | { 6 | [Command("white-russian", group: "duderino")] 7 | [Description("Mixes a White Russian, pouring in milk till full")] 8 | public class WhiteRussian : ICommand 9 | { 10 | [Parameter("vodka")] 11 | [Description("How many cl of vodka?")] 12 | public double Vodka { get; set; } 13 | 14 | [Parameter("kahlua")] 15 | [Description("How many cl of Kahlua?")] 16 | public double Kahlua { get; set; } 17 | 18 | [Parameter("lukewarm", optional: true)] 19 | [Description("Avoid refrigerated ingredients?")] 20 | public bool LukeWarm { get; set; } 21 | 22 | public void Run() 23 | { 24 | Console.WriteLine($"Making a {(LukeWarm ? "luke-warm" : "")} beverage" + 25 | $" with {Vodka:0.#} cl of vodka" + 26 | $" and {Kahlua:0.#} cl of Kahlua"); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Beverage/Program.cs: -------------------------------------------------------------------------------- 1 | using GoCommando; 2 | 3 | namespace Beverage 4 | { 5 | [Banner(@"------------------------------ 6 | Beverage Utility 7 | 8 | Copyright (c) 2015 El Duderino 9 | ------------------------------")] 10 | [SupportImpersonation] 11 | class Program 12 | { 13 | static void Main() 14 | { 15 | Go.Run(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Beverage_old/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Beverage_old/Beverage.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {324FC1A5-749A-44BF-BDB7-EB093F5DD88F} 8 | Exe 9 | Properties 10 | Beverage 11 | Beverage 12 | v4.6 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 63 | -------------------------------------------------------------------------------- /Beverage_old/Commands/BlackRussian.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GoCommando; 3 | 4 | namespace Beverage.Commands 5 | { 6 | [Command("black-russian", group: "duderino")] 7 | [Description("Mixes a White Russian, pouring in milk till full")] 8 | public class BlackRussian : ICommand 9 | { 10 | [Parameter("vodka")] 11 | [Description("How many cl of vodka?")] 12 | public double Vodka { get; set; } 13 | 14 | [Parameter("kahlua")] 15 | [Description("How many cl of Kahlua?")] 16 | public double Kahlua { get; set; } 17 | 18 | [Parameter("lukewarm", optional: true)] 19 | [Description("Avoid refrigerated ingredients?")] 20 | public bool LukeWarm { get; set; } 21 | 22 | public void Run() 23 | { 24 | Console.WriteLine($"Making a {(LukeWarm ? "luke-warm" : "")} beverage" + 25 | $" with {Vodka:0.#} cl of vodka" + 26 | $" and {Kahlua:0.#} cl of Kahlua"); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Beverage_old/Commands/Martini.cs: -------------------------------------------------------------------------------- 1 | using GoCommando; 2 | 3 | namespace Beverage.Commands 4 | { 5 | [Command("martini", group: "simple")] 6 | [Description("It's just Martini.")] 7 | public class Martini : ICommand 8 | { 9 | public void Run() 10 | { 11 | throw new System.NotImplementedException(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Beverage_old/Commands/WhiteRussian.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GoCommando; 3 | 4 | namespace Beverage.Commands 5 | { 6 | [Command("white-russian", group: "duderino")] 7 | [Description("Mixes a White Russian, pouring in milk till full")] 8 | public class WhiteRussian : ICommand 9 | { 10 | [Parameter("vodka")] 11 | [Description("How many cl of vodka?")] 12 | public double Vodka { get; set; } 13 | 14 | [Parameter("kahlua")] 15 | [Description("How many cl of Kahlua?")] 16 | public double Kahlua { get; set; } 17 | 18 | [Parameter("lukewarm", optional: true)] 19 | [Description("Avoid refrigerated ingredients?")] 20 | public bool LukeWarm { get; set; } 21 | 22 | public void Run() 23 | { 24 | Console.WriteLine($"Making a {(LukeWarm ? "luke-warm" : "")} beverage" + 25 | $" with {Vodka:0.#} cl of vodka" + 26 | $" and {Kahlua:0.#} cl of Kahlua"); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Beverage_old/Program.cs: -------------------------------------------------------------------------------- 1 | using GoCommando; 2 | 3 | namespace Beverage 4 | { 5 | [Banner(@"------------------------------ 6 | Beverage Utility 7 | 8 | Copyright (c) 2015 El Duderino 9 | ------------------------------")] 10 | [SupportImpersonation] 11 | class Program 12 | { 13 | static void Main() 14 | { 15 | Go.Run(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Beverage_old/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Beverage")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Beverage")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("324fc1a5-749a-44bf-bdb7-eb093f5dd88f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 0.99.3 4 | * Test release 5 | 6 | -------------------------------------------------------------------------------- /GoCommando.Tests/GoCommando.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /GoCommando.Tests/TestArgParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using GoCommando.Internals; 5 | using NUnit.Framework; 6 | 7 | namespace GoCommando.Tests 8 | { 9 | [TestFixture] 10 | public class TestArgParser 11 | { 12 | [Test] 13 | public void CanReturnSimpleCommand() 14 | { 15 | var arguments = Parse(new[] { "run" }); 16 | 17 | Assert.That(arguments.Command, Is.EqualTo("run")); 18 | } 19 | 20 | [Test] 21 | public void CommandIsNullWhenNoCommandIsGiven() 22 | { 23 | var arguments = Parse(new[] { "-file", @"""C:\temp\file.json""" }); 24 | 25 | Assert.That(arguments.Command, Is.Null); 26 | } 27 | 28 | [Test, Ignore("arguments.Command should just be null")] 29 | public void DoesNotAcceptSwitchAsCommand() 30 | { 31 | var ex = Assert.Throws(() => 32 | { 33 | Parse(new[] { "-file", @"""C:\temp\file.json""" }); 34 | }); 35 | 36 | Console.WriteLine(ex); 37 | } 38 | 39 | [Test] 40 | public void CanParseOrdinaryArguments() 41 | { 42 | var args = @"run 43 | -path 44 | c:\Program Files 45 | -dir 46 | c:\Windows\Microsoft.NET\Framework 47 | -flag 48 | -moreflag".Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); 49 | 50 | var arguments = Parse(args); 51 | 52 | Console.WriteLine(arguments); 53 | 54 | Assert.That(arguments.Command, Is.EqualTo("run")); 55 | Assert.That(arguments.Switches.Count(), Is.EqualTo(4)); 56 | Assert.That(arguments.Get("path"), Is.EqualTo(@"c:\Program Files")); 57 | Assert.That(arguments.Get("dir"), Is.EqualTo(@"c:\Windows\Microsoft.NET\Framework")); 58 | 59 | Assert.That(arguments.Get("flag"), Is.True); 60 | Assert.That(arguments.Get("moreflag"), Is.True); 61 | Assert.That(arguments.Get("flag_not_specified_should_default_to_false"), Is.False); 62 | } 63 | 64 | [TestCase(@"-path:""c:\temp""")] 65 | [TestCase(@"-path=""c:\temp""")] 66 | [TestCase(@"-path""c:\temp""")] 67 | public void SupportsVariousSingleTokenAliases(string alias) 68 | { 69 | var arguments = Parse(new[] { alias }); 70 | 71 | Assert.That(arguments.Switches.Count(), Is.EqualTo(1)); 72 | Assert.That(arguments.Switches.Single().Key, Is.EqualTo("path")); 73 | Assert.That(arguments.Switches.Single().Value, Is.EqualTo(@"c:\temp")); 74 | } 75 | 76 | [TestCase(@"-n23")] 77 | public void SupportsShortFormWithNumber(string alias) 78 | { 79 | var arguments = Parse(new[] { alias }); 80 | 81 | Assert.That(arguments.Switches.Count(), Is.EqualTo(1)); 82 | Assert.That(arguments.Switches.Single().Key, Is.EqualTo("n")); 83 | Assert.That(arguments.Switches.Single().Value, Is.EqualTo(@"23")); 84 | } 85 | 86 | static Arguments Parse(IEnumerable args) 87 | { 88 | return Go.Parse(args, new Settings()); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /GoCommando.Tests/TestCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using GoCommando.Internals; 5 | using NUnit.Framework; 6 | 7 | namespace GoCommando.Tests 8 | { 9 | [TestFixture] 10 | public class TestCommand 11 | { 12 | [TestCase("-switch:value2")] 13 | [TestCase("-switch=value2")] 14 | [TestCase(@"-switch""value2""")] 15 | public void CanCorrectlyHandleDifferentAlternativeSwitchFormatsFoundInOneSingleTokenOnly(string switchText) 16 | { 17 | var settings = new Settings(); 18 | var invoker = new CommandInvoker("bimse", settings, new Bimse()); 19 | var arguments = Go.Parse(new[] { switchText }, settings); 20 | 21 | invoker.Invoke(arguments.Switches, EnvironmentSettings.Empty); 22 | 23 | var bimseInstance = (Bimse)invoker.CommandInstance; 24 | 25 | Assert.That(bimseInstance.Switch, Is.EqualTo("value2")); 26 | } 27 | 28 | [TestCase("-s:value2")] 29 | [TestCase("-s=value2")] 30 | [TestCase(@"-s""value2""")] 31 | public void CanCorrectlyHandleDifferentAlternativeSwitchFormatsFoundInOneSingleTokenOnly_Shortname(string switchText) 32 | { 33 | var settings = new Settings(); 34 | var invoker = new CommandInvoker("bimse", settings, new Bimse()); 35 | var arguments = Go.Parse(new[] { switchText }, settings); 36 | 37 | invoker.Invoke(arguments.Switches, EnvironmentSettings.Empty); 38 | 39 | var bimseInstance = (Bimse)invoker.CommandInstance; 40 | 41 | Assert.That(bimseInstance.Switch, Is.EqualTo("value2")); 42 | } 43 | 44 | [Command("bimse")] 45 | class Bimse : ICommand 46 | { 47 | [Parameter("switch", shortName: "s")] 48 | public string Switch { get; set; } 49 | 50 | public void Run() 51 | { 52 | } 53 | } 54 | 55 | [Test] 56 | public void CanUseSuppliedCommandFactory() 57 | { 58 | var commandFactory = new CustomFactory(); 59 | 60 | var commandInvoker = new CommandInvoker("null", typeof(CreatedByFactory), new Settings(), commandFactory: commandFactory); 61 | 62 | commandInvoker.Invoke(Enumerable.Empty(), new EnvironmentSettings()); 63 | 64 | Assert.That(commandInvoker.CommandInstance, Is.TypeOf()); 65 | 66 | var createdByFactory = (CreatedByFactory)commandInvoker.CommandInstance; 67 | Assert.That(createdByFactory.CtorInjectedValue, Is.EqualTo("ctor!!")); 68 | 69 | Assert.That(commandFactory.WasProperlyReleased, Is.True, "The created command instance was NOT properly released after use!"); 70 | } 71 | 72 | class CustomFactory : ICommandFactory 73 | { 74 | CreatedByFactory _instance; 75 | 76 | public bool WasProperlyReleased { get; set; } 77 | 78 | public ICommand Create(Type type) 79 | { 80 | if (type == typeof(CreatedByFactory)) 81 | { 82 | _instance = new CreatedByFactory("ctor!!"); 83 | return _instance; 84 | } 85 | 86 | throw new ArgumentException($"Unknown command type: {type}"); 87 | } 88 | 89 | public void Release(ICommand command) 90 | { 91 | if (_instance == command) 92 | { 93 | WasProperlyReleased = true; 94 | } 95 | } 96 | } 97 | 98 | class CreatedByFactory : ICommand 99 | { 100 | public string CtorInjectedValue { get; } 101 | 102 | public CreatedByFactory(string ctorInjectedValue) 103 | { 104 | CtorInjectedValue = ctorInjectedValue; 105 | } 106 | 107 | public void Run() 108 | { 109 | } 110 | } 111 | 112 | [Test] 113 | public void CanGetParameterFromAppSettingsAndConnectionStrings() 114 | { 115 | var invoker = new CommandInvoker("null", typeof(CanUseAppSetting), new Settings()); 116 | 117 | var appSettings = new Dictionary 118 | { 119 | {"my-setting", "my-value"} 120 | }; 121 | 122 | var connectionStrings = new Dictionary 123 | { 124 | {"my-conn", "my-value"} 125 | }; 126 | 127 | var environmentVariables = new Dictionary 128 | { 129 | {"my-env", "my-value"} 130 | }; 131 | 132 | invoker.Invoke(Enumerable.Empty(), new EnvironmentSettings(appSettings, connectionStrings, environmentVariables)); 133 | 134 | var instance = (CanUseAppSetting)invoker.CommandInstance; 135 | 136 | Assert.That(instance.AppSetting, Is.EqualTo("my-value")); 137 | Assert.That(instance.ConnectionString, Is.EqualTo("my-value")); 138 | Assert.That(instance.EnvironmentVariable, Is.EqualTo("my-value")); 139 | } 140 | 141 | class CanUseAppSetting : ICommand 142 | { 143 | [Parameter("my-setting", allowAppSetting: true)] 144 | public string AppSetting { get; set; } 145 | 146 | [Parameter("my-conn", allowConnectionString: true)] 147 | public string ConnectionString { get; set; } 148 | 149 | [Parameter("my-env", allowEnvironmentVariable: true)] 150 | public string EnvironmentVariable { get; set; } 151 | 152 | public void Run() 153 | { 154 | 155 | } 156 | } 157 | } 158 | } -------------------------------------------------------------------------------- /GoCommando.Tests_old/GoCommando.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {5B0BCF64-81B6-4A33-8D00-C673A0EF3551} 8 | Library 9 | Properties 10 | GoCommando.Tests 11 | GoCommando.Tests 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\NUnit.2.6.4\lib\nunit.framework.dll 35 | True 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | {2839AA55-B40A-4BB8-BDA0-C5057E5A683F} 57 | GoCommando 58 | 59 | 60 | 61 | 68 | -------------------------------------------------------------------------------- /GoCommando.Tests_old/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("GoCommando.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("GoCommando.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5b0bcf64-81b6-4a33-8d00-c673a0ef3551")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /GoCommando.Tests_old/TestArgParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using GoCommando.Internals; 5 | using NUnit.Framework; 6 | 7 | namespace GoCommando.Tests 8 | { 9 | [TestFixture] 10 | public class TestArgParser 11 | { 12 | [Test] 13 | public void CanReturnSimpleCommand() 14 | { 15 | var arguments = Parse(new[] { "run" }); 16 | 17 | Assert.That(arguments.Command, Is.EqualTo("run")); 18 | } 19 | 20 | [Test] 21 | public void CommandIsNullWhenNoCommandIsGiven() 22 | { 23 | var arguments = Parse(new[] { "-file", @"""C:\temp\file.json""" }); 24 | 25 | Assert.That(arguments.Command, Is.Null); 26 | } 27 | 28 | [Test, Ignore("arguments.Command should just be null")] 29 | public void DoesNotAcceptSwitchAsCommand() 30 | { 31 | var ex = Assert.Throws(() => 32 | { 33 | Parse(new[] { "-file", @"""C:\temp\file.json""" }); 34 | }); 35 | 36 | Console.WriteLine(ex); 37 | } 38 | 39 | [Test] 40 | public void CanParseOrdinaryArguments() 41 | { 42 | var args = @"run 43 | -path 44 | c:\Program Files 45 | -dir 46 | c:\Windows\Microsoft.NET\Framework 47 | -flag 48 | -moreflag".Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); 49 | 50 | var arguments = Parse(args); 51 | 52 | Console.WriteLine(arguments); 53 | 54 | Assert.That(arguments.Command, Is.EqualTo("run")); 55 | Assert.That(arguments.Switches.Count(), Is.EqualTo(4)); 56 | Assert.That(arguments.Get("path"), Is.EqualTo(@"c:\Program Files")); 57 | Assert.That(arguments.Get("dir"), Is.EqualTo(@"c:\Windows\Microsoft.NET\Framework")); 58 | 59 | Assert.That(arguments.Get("flag"), Is.True); 60 | Assert.That(arguments.Get("moreflag"), Is.True); 61 | Assert.That(arguments.Get("flag_not_specified_should_default_to_false"), Is.False); 62 | } 63 | 64 | [TestCase(@"-path:""c:\temp""")] 65 | [TestCase(@"-path=""c:\temp""")] 66 | [TestCase(@"-path""c:\temp""")] 67 | public void SupportsVariousSingleTokenAliases(string alias) 68 | { 69 | var arguments = Parse(new[] { alias }); 70 | 71 | Assert.That(arguments.Switches.Count(), Is.EqualTo(1)); 72 | Assert.That(arguments.Switches.Single().Key, Is.EqualTo("path")); 73 | Assert.That(arguments.Switches.Single().Value, Is.EqualTo(@"c:\temp")); 74 | } 75 | 76 | [TestCase(@"-n23")] 77 | public void SupportsShortFormWithNumber(string alias) 78 | { 79 | var arguments = Parse(new[] { alias }); 80 | 81 | Assert.That(arguments.Switches.Count(), Is.EqualTo(1)); 82 | Assert.That(arguments.Switches.Single().Key, Is.EqualTo("n")); 83 | Assert.That(arguments.Switches.Single().Value, Is.EqualTo(@"23")); 84 | } 85 | 86 | static Arguments Parse(IEnumerable args) 87 | { 88 | return Go.Parse(args, new Settings()); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /GoCommando.Tests_old/TestCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using GoCommando.Internals; 5 | using NUnit.Framework; 6 | 7 | namespace GoCommando.Tests 8 | { 9 | [TestFixture] 10 | public class TestCommand 11 | { 12 | [TestCase("-switch:value2")] 13 | [TestCase("-switch=value2")] 14 | [TestCase(@"-switch""value2""")] 15 | public void CanCorrectlyHandleDifferentAlternativeSwitchFormatsFoundInOneSingleTokenOnly(string switchText) 16 | { 17 | var settings = new Settings(); 18 | var invoker = new CommandInvoker("bimse", settings, new Bimse()); 19 | var arguments = Go.Parse(new[] { switchText }, settings); 20 | 21 | invoker.Invoke(arguments.Switches, EnvironmentSettings.Empty); 22 | 23 | var bimseInstance = (Bimse)invoker.CommandInstance; 24 | 25 | Assert.That(bimseInstance.Switch, Is.EqualTo("value2")); 26 | } 27 | 28 | [TestCase("-s:value2")] 29 | [TestCase("-s=value2")] 30 | [TestCase(@"-s""value2""")] 31 | public void CanCorrectlyHandleDifferentAlternativeSwitchFormatsFoundInOneSingleTokenOnly_Shortname(string switchText) 32 | { 33 | var settings = new Settings(); 34 | var invoker = new CommandInvoker("bimse", settings, new Bimse()); 35 | var arguments = Go.Parse(new[] { switchText }, settings); 36 | 37 | invoker.Invoke(arguments.Switches, EnvironmentSettings.Empty); 38 | 39 | var bimseInstance = (Bimse)invoker.CommandInstance; 40 | 41 | Assert.That(bimseInstance.Switch, Is.EqualTo("value2")); 42 | } 43 | 44 | [Command("bimse")] 45 | class Bimse : ICommand 46 | { 47 | [Parameter("switch", shortName: "s")] 48 | public string Switch { get; set; } 49 | 50 | public void Run() 51 | { 52 | } 53 | } 54 | 55 | [Test] 56 | public void CanUseSuppliedCommandFactory() 57 | { 58 | var commandFactory = new CustomFactory(); 59 | 60 | var commandInvoker = new CommandInvoker("null", typeof(CreatedByFactory), new Settings(), commandFactory: commandFactory); 61 | 62 | commandInvoker.Invoke(Enumerable.Empty(), new EnvironmentSettings()); 63 | 64 | Assert.That(commandInvoker.CommandInstance, Is.TypeOf()); 65 | 66 | var createdByFactory = (CreatedByFactory)commandInvoker.CommandInstance; 67 | Assert.That(createdByFactory.CtorInjectedValue, Is.EqualTo("ctor!!")); 68 | 69 | Assert.That(commandFactory.WasProperlyReleased, Is.True, "The created command instance was NOT properly released after use!"); 70 | } 71 | 72 | class CustomFactory : ICommandFactory 73 | { 74 | CreatedByFactory _instance; 75 | 76 | public bool WasProperlyReleased { get; set; } 77 | 78 | public ICommand Create(Type type) 79 | { 80 | if (type == typeof(CreatedByFactory)) 81 | { 82 | _instance = new CreatedByFactory("ctor!!"); 83 | return _instance; 84 | } 85 | 86 | throw new ArgumentException($"Unknown command type: {type}"); 87 | } 88 | 89 | public void Release(ICommand command) 90 | { 91 | if (_instance == command) 92 | { 93 | WasProperlyReleased = true; 94 | } 95 | } 96 | } 97 | 98 | class CreatedByFactory : ICommand 99 | { 100 | public string CtorInjectedValue { get; } 101 | 102 | public CreatedByFactory(string ctorInjectedValue) 103 | { 104 | CtorInjectedValue = ctorInjectedValue; 105 | } 106 | 107 | public void Run() 108 | { 109 | } 110 | } 111 | 112 | [Test] 113 | public void CanGetParameterFromAppSettingsAndConnectionStrings() 114 | { 115 | var invoker = new CommandInvoker("null", typeof(CanUseAppSetting), new Settings()); 116 | 117 | var appSettings = new Dictionary 118 | { 119 | {"my-setting", "my-value"} 120 | }; 121 | 122 | var connectionStrings = new Dictionary 123 | { 124 | {"my-conn", "my-value"} 125 | }; 126 | 127 | var environmentVariables = new Dictionary 128 | { 129 | {"my-env", "my-value"} 130 | }; 131 | 132 | invoker.Invoke(Enumerable.Empty(), new EnvironmentSettings(appSettings, connectionStrings, environmentVariables)); 133 | 134 | var instance = (CanUseAppSetting)invoker.CommandInstance; 135 | 136 | Assert.That(instance.AppSetting, Is.EqualTo("my-value")); 137 | Assert.That(instance.ConnectionString, Is.EqualTo("my-value")); 138 | Assert.That(instance.EnvironmentVariable, Is.EqualTo("my-value")); 139 | } 140 | 141 | class CanUseAppSetting : ICommand 142 | { 143 | [Parameter("my-setting", allowAppSetting: true)] 144 | public string AppSetting { get; set; } 145 | 146 | [Parameter("my-conn", allowConnectionString: true)] 147 | public string ConnectionString { get; set; } 148 | 149 | [Parameter("my-env", allowEnvironmentVariable: true)] 150 | public string EnvironmentVariable { get; set; } 151 | 152 | public void Run() 153 | { 154 | 155 | } 156 | } 157 | } 158 | } -------------------------------------------------------------------------------- /GoCommando.Tests_old/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /GoCommando.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 16 3 | VisualStudioVersion = 16.0.30330.147 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "stuff", "stuff", "{4777EF91-8FBF-42DC-A31F-2025CC5841F8}" 6 | ProjectSection(SolutionItems) = preProject 7 | CHANGELOG.md = CHANGELOG.md 8 | Package.nuspec = Package.nuspec 9 | README.md = README.md 10 | EndProjectSection 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{94F2785A-49E5-447F-BAFF-BE8F783EC71F}" 13 | EndProject 14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GoCommando", "GoCommando\GoCommando.csproj", "{91A9A887-0298-4B72-9D24-C2438F469192}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GoCommando.Tests", "GoCommando.Tests\GoCommando.Tests.csproj", "{FBD7AE5E-C842-448B-9A6B-81513E60F357}" 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Beverage", "Beverage\Beverage.csproj", "{D7C8D131-E81A-4846-A9EE-9D42A667CA32}" 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Release|Any CPU = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {91A9A887-0298-4B72-9D24-C2438F469192}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {91A9A887-0298-4B72-9D24-C2438F469192}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {91A9A887-0298-4B72-9D24-C2438F469192}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {91A9A887-0298-4B72-9D24-C2438F469192}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {FBD7AE5E-C842-448B-9A6B-81513E60F357}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {FBD7AE5E-C842-448B-9A6B-81513E60F357}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {FBD7AE5E-C842-448B-9A6B-81513E60F357}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {FBD7AE5E-C842-448B-9A6B-81513E60F357}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {D7C8D131-E81A-4846-A9EE-9D42A667CA32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {D7C8D131-E81A-4846-A9EE-9D42A667CA32}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {D7C8D131-E81A-4846-A9EE-9D42A667CA32}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {D7C8D131-E81A-4846-A9EE-9D42A667CA32}.Release|Any CPU.Build.0 = Release|Any CPU 38 | EndGlobalSection 39 | GlobalSection(SolutionProperties) = preSolution 40 | HideSolutionNode = FALSE 41 | EndGlobalSection 42 | GlobalSection(NestedProjects) = preSolution 43 | {D7C8D131-E81A-4846-A9EE-9D42A667CA32} = {94F2785A-49E5-447F-BAFF-BE8F783EC71F} 44 | EndGlobalSection 45 | GlobalSection(ExtensibilityGlobals) = postSolution 46 | SolutionGuid = {F99A8DD1-DE53-43D3-A0E0-BE222C826E90} 47 | EndGlobalSection 48 | EndGlobal 49 | -------------------------------------------------------------------------------- /GoCommando/BannerAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Apply this attribute to the class that has your Main method in order to have a nice banner printed out when the program starts 7 | /// 8 | [AttributeUsage(AttributeTargets.Class)] 9 | public class BannerAttribute : Attribute 10 | { 11 | /// 12 | /// Gets the banner text 13 | /// 14 | public string BannerText { get; } 15 | 16 | /// 17 | /// Constructs the attribute 18 | /// 19 | public BannerAttribute(string bannerText) 20 | { 21 | BannerText = bannerText; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /GoCommando/CommandAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Attribute that can be applied to a class that represents a command. The class must implement 7 | /// 8 | [AttributeUsage(AttributeTargets.Class)] 9 | public class CommandAttribute : Attribute 10 | { 11 | /// 12 | /// Gets the name of the command 13 | /// 14 | public string Command { get; } 15 | 16 | /// 17 | /// Gets the name of the command's group (if any). Grouping commands affects how they are presented when printing 18 | /// help texts 19 | /// 20 | public string Group { get; } 21 | 22 | /// 23 | /// Constructs the attribute 24 | /// 25 | public CommandAttribute(string command, string group = null) 26 | { 27 | Command = command; 28 | Group = group ?? ""; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /GoCommando/DescriptionAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Apply this attribute to a property of a command class (which is also decorated with ) in 7 | /// order to provide a description of the parameter 8 | /// 9 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)] 10 | public class DescriptionAttribute : Attribute 11 | { 12 | /// 13 | /// Gets the description text 14 | /// 15 | public string DescriptionText { get; } 16 | 17 | /// 18 | /// Constructs the attribute 19 | /// 20 | public DescriptionAttribute(string descriptionText) 21 | { 22 | DescriptionText = descriptionText; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /GoCommando/ExampleAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Apply one or more of these to a command property to show examples on how this particular parameter can be used 7 | /// 8 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] 9 | public class ExampleAttribute : Attribute 10 | { 11 | /// 12 | /// Gets the example text 13 | /// 14 | public string ExampleValue { get; } 15 | 16 | /// 17 | /// Constructs the attribute 18 | /// 19 | public ExampleAttribute(string exampleValue) 20 | { 21 | ExampleValue = exampleValue; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /GoCommando/ExitCodeException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace GoCommando 5 | { 6 | /// 7 | /// Exception that can be used to exit the program with a custom exit code 8 | /// 9 | [Serializable] 10 | public class CustomExitCodeException : Exception 11 | { 12 | /// 13 | /// Constructs the exception 14 | /// 15 | protected CustomExitCodeException(SerializationInfo info, StreamingContext context) : base(info, context) 16 | { 17 | } 18 | 19 | /// 20 | /// Constructs the exception 21 | /// 22 | public CustomExitCodeException(int exitCode, string message) : base(message) 23 | { 24 | ExitCode = exitCode; 25 | } 26 | 27 | /// 28 | /// Gets the exit code that the program must exit with 29 | /// 30 | public int ExitCode { get; } 31 | } 32 | } -------------------------------------------------------------------------------- /GoCommando/GoCommando.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | MIT 6 | https://github.com/rebus-org/GoCommando/wiki 7 | https://github.com/rebus-org/GoCommando 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /GoCommando/GoCommandoException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace GoCommando 5 | { 6 | /// 7 | /// Friendly exception that can be thrown in cases where you want the program to exit with 8 | /// a nice, human-readable message. Only the message will be shown. 9 | /// 10 | [Serializable] 11 | public class GoCommandoException : Exception 12 | { 13 | /// 14 | /// Constructs the exception 15 | /// 16 | protected GoCommandoException(SerializationInfo info, StreamingContext context) : base(info, context) 17 | { 18 | } 19 | 20 | /// 21 | /// Constructs the exception 22 | /// 23 | public GoCommandoException(string message) : base(message) 24 | { 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /GoCommando/ICommand.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando 2 | { 3 | /// 4 | /// Implement this interface on each command 5 | /// 6 | public interface ICommand 7 | { 8 | /// 9 | /// Main run method that is invoked by GoCommando 10 | /// 11 | void Run(); 12 | } 13 | } -------------------------------------------------------------------------------- /GoCommando/ICommandFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Can be implemented to supply a custom command factory that will be given a chance to create command instances 7 | /// and dispose of them after use 8 | /// 9 | public interface ICommandFactory 10 | { 11 | /// 12 | /// Should create a new command instance of the given 13 | /// 14 | ICommand Create(Type commandType); 15 | 16 | /// 17 | /// Should release the command instance - probably by disposing it or delegating the disposal to an IoC container 18 | /// 19 | void Release(ICommand command); 20 | } 21 | } -------------------------------------------------------------------------------- /GoCommando/Internals/Arguments.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace GoCommando.Internals 6 | { 7 | class Arguments 8 | { 9 | readonly Settings _settings; 10 | 11 | public Arguments(string command, IEnumerable switches, Settings settings) 12 | { 13 | _settings = settings; 14 | var switchList = switches.ToList(); 15 | var duplicateSwitchKeys = switchList.GroupBy(s => s.Key).Where(g => g.Count() > 1).ToList(); 16 | 17 | if (duplicateSwitchKeys.Any()) 18 | { 19 | var dupes = string.Join(", ", duplicateSwitchKeys.Select(g => $"{settings.SwitchPrefix}{g.Key}")); 20 | 21 | throw new GoCommandoException($"The following switches have been specified more than once: {dupes}"); 22 | } 23 | 24 | Command = command; 25 | Switches = switchList; 26 | } 27 | 28 | public string Command { get; } 29 | 30 | public IEnumerable Switches { get; } 31 | 32 | public TValue Get(string key) 33 | { 34 | var desiredType = typeof(TValue); 35 | 36 | try 37 | { 38 | if (desiredType == typeof(bool)) 39 | { 40 | return (TValue)Convert.ChangeType(Switches.Any(s => s.Key == key), desiredType); 41 | } 42 | 43 | var relevantSwitch = Switches.FirstOrDefault(s => s.Key == key); 44 | 45 | if (relevantSwitch != null) 46 | { 47 | return (TValue)Convert.ChangeType(relevantSwitch.Value, desiredType); 48 | } 49 | 50 | throw new GoCommandoException($"Could not find switch '{key}'"); 51 | } 52 | catch (Exception exception) 53 | { 54 | throw new FormatException($"Could not get switch '{key}' as a {desiredType}", exception); 55 | } } 56 | 57 | public override string ToString() 58 | { 59 | return $@"{Command} 60 | 61 | {string.Join(Environment.NewLine, Switches.Select(s => " " + s))}"; 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /GoCommando/Internals/CommandInvoker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | namespace GoCommando.Internals 7 | { 8 | class CommandInvoker 9 | { 10 | readonly Settings _settings; 11 | readonly ICommand _commandInstance; 12 | readonly Action _releaser; 13 | readonly List _parameters; 14 | 15 | public CommandInvoker(string command, Type type, Settings settings, string @group = null, 16 | ICommandFactory commandFactory = null) 17 | : this(command, settings, CreateInstance(type, GetFactoryMethod(commandFactory)), group, GetReleaseMethod(commandFactory)) 18 | { 19 | } 20 | 21 | public CommandInvoker(string command, Settings settings, ICommand commandInstance, string group = null, Action releaseMethod = null) 22 | { 23 | if (command == null) throw new ArgumentNullException(nameof(command)); 24 | if (settings == null) throw new ArgumentNullException(nameof(settings)); 25 | if (commandInstance == null) throw new ArgumentNullException(nameof(commandInstance)); 26 | 27 | _settings = settings; 28 | _commandInstance = commandInstance; 29 | _releaser = releaseMethod ?? DefaultReleaseMethod; 30 | 31 | Command = command; 32 | Group = group; 33 | 34 | _parameters = GetParameters(Type).ToList(); 35 | } 36 | 37 | static void DefaultReleaseMethod(ICommand command) 38 | { 39 | var disposable = command as IDisposable; 40 | 41 | disposable?.Dispose(); 42 | } 43 | 44 | static Func GetFactoryMethod(ICommandFactory commandFactory) 45 | { 46 | if (commandFactory == null) return null; 47 | 48 | return commandFactory.Create; 49 | } 50 | 51 | static Action GetReleaseMethod(ICommandFactory commandFactory) 52 | { 53 | if (commandFactory == null) return null; 54 | 55 | return commandFactory.Release; 56 | } 57 | 58 | static ICommand CreateInstance(Type type, Func commandFactory = null) 59 | { 60 | try 61 | { 62 | var instance = commandFactory?.Invoke(type) 63 | ?? Activator.CreateInstance(type); 64 | 65 | if (!(instance is ICommand)) 66 | { 67 | throw new ApplicationException($"{instance} does not implement ICommand!"); 68 | } 69 | 70 | return (ICommand)instance; 71 | } 72 | catch (Exception exception) 73 | { 74 | throw new ApplicationException($"Could not use type {type} as a GoCommando command", exception); 75 | } 76 | } 77 | 78 | static IEnumerable GetParameters(Type type) 79 | { 80 | return type 81 | .GetProperties() 82 | .Select(p => new 83 | { 84 | Property = p, 85 | ParameterAttribute = GetSingleAttributeOrNull(p), 86 | DescriptionAttribute = GetSingleAttributeOrNull(p), 87 | ExampleAttributes = p.GetCustomAttributes() 88 | }) 89 | .Where(a => a.ParameterAttribute != null) 90 | .Select(a => new Parameter(a.Property, 91 | a.ParameterAttribute.Name, 92 | a.ParameterAttribute.ShortName, 93 | a.ParameterAttribute.Optional, 94 | a.DescriptionAttribute?.DescriptionText, 95 | a.ExampleAttributes.Select(e => e.ExampleValue), 96 | a.ParameterAttribute.DefaultValue, 97 | a.ParameterAttribute.AllowAppSetting, 98 | a.ParameterAttribute.AllowConnectionString, 99 | a.ParameterAttribute.AllowEnvironmentVariable)) 100 | .ToList(); 101 | } 102 | 103 | static TAttribute GetSingleAttributeOrNull(PropertyInfo p) where TAttribute : Attribute 104 | { 105 | return p.GetCustomAttributes(typeof(TAttribute), false) 106 | .Cast() 107 | .FirstOrDefault(); 108 | } 109 | 110 | public string Group { get; } 111 | 112 | public string Command { get; } 113 | 114 | public Type Type => _commandInstance.GetType(); 115 | 116 | public IEnumerable Parameters => _parameters; 117 | 118 | public string Description => Type.GetCustomAttribute()?.DescriptionText ?? 119 | "(no help text for this command)"; 120 | 121 | public ICommand CommandInstance => _commandInstance; 122 | 123 | public void Invoke(IEnumerable switches, EnvironmentSettings environmentSettings) 124 | { 125 | try 126 | { 127 | InnerInvoke(switches, environmentSettings); 128 | } 129 | finally 130 | { 131 | _releaser(CommandInstance); 132 | } 133 | } 134 | 135 | void InnerInvoke(IEnumerable switches, EnvironmentSettings environmentSettings) 136 | { 137 | var commandInstance = _commandInstance; 138 | 139 | var requiredParametersMissing = Parameters 140 | .Where(p => !p.Optional 141 | && !p.HasDefaultValue 142 | && !CanBeResolvedFromSwitches(switches, p) 143 | && !CanBeResolvedFromEnvironmentSettings(environmentSettings, p)) 144 | .ToList(); 145 | 146 | var optionalParamtersNotSpecified = Parameters 147 | .Where(p => p.Optional 148 | && !CanBeResolvedFromSwitches(switches, p) 149 | && !CanBeResolvedFromEnvironmentSettings(environmentSettings, p)) 150 | .ToList(); 151 | 152 | if (requiredParametersMissing.Any()) 153 | { 154 | var requiredParametersMissingString = string.Join(Environment.NewLine, 155 | requiredParametersMissing.Select(p => $" {_settings.SwitchPrefix}{p.Name} - {p.DescriptionText}")); 156 | 157 | var text = $@"The following required parameters are missing: 158 | 159 | {requiredParametersMissingString}"; 160 | 161 | if (optionalParamtersNotSpecified.Any()) 162 | { 163 | var optionalParamtersNotSpecifiedString = string.Join(Environment.NewLine, 164 | optionalParamtersNotSpecified.Select(p => $" {_settings.SwitchPrefix}{p.Name} - {p.DescriptionText}")); 165 | 166 | var moreText = $@"The following optional parameters are also available: 167 | 168 | {optionalParamtersNotSpecifiedString}"; 169 | 170 | throw new GoCommandoException(string.Concat( 171 | text, 172 | Environment.NewLine, 173 | Environment.NewLine, 174 | moreText 175 | )); 176 | } 177 | 178 | throw new GoCommandoException(text); 179 | } 180 | 181 | var switchesWithoutMathingParameter = switches 182 | .Where(s => !Parameters.Any(p => p.MatchesKey(s.Key))) 183 | .ToList(); 184 | 185 | if (switchesWithoutMathingParameter.Any()) 186 | { 187 | var switchesWithoutMathingParameterString = string.Join(Environment.NewLine, 188 | switchesWithoutMathingParameter.Select(p => p.Value != null 189 | ? $" {_settings.SwitchPrefix}{p.Key} = {p.Value}" 190 | : $" {_settings.SwitchPrefix}{p.Key}")); 191 | 192 | throw new GoCommandoException( 193 | $@"The following switches do not have a corresponding parameter: 194 | 195 | {switchesWithoutMathingParameterString}"); 196 | } 197 | 198 | var setParameters = new HashSet(); 199 | 200 | ResolveParametersFromSwitches(switches, commandInstance, setParameters); 201 | 202 | ResolveParametersFromEnvironmentSettings(environmentSettings, commandInstance, setParameters, Parameters); 203 | 204 | ResolveParametersWithDefaultValues(setParameters, commandInstance); 205 | 206 | commandInstance.Run(); 207 | } 208 | 209 | static void ResolveParametersFromEnvironmentSettings(EnvironmentSettings environmentSettings, ICommand commandInstance, HashSet setParameters, IEnumerable parameters) 210 | { 211 | foreach (var parameter in parameters.Where(p => p.AllowAppSetting && !setParameters.Contains(p))) 212 | { 213 | if (!environmentSettings.HasAppSetting(parameter.Name)) continue; 214 | 215 | var appSettingValue = environmentSettings.GetAppSetting(parameter.Name); 216 | 217 | SetParameter(commandInstance, setParameters, parameter, appSettingValue); 218 | } 219 | 220 | foreach (var parameter in parameters.Where(p => p.AllowConnectionString && !setParameters.Contains(p))) 221 | { 222 | if (!environmentSettings.HasConnectionString(parameter.Name)) continue; 223 | 224 | var appSettingValue = environmentSettings.GetConnectionString(parameter.Name); 225 | 226 | SetParameter(commandInstance, setParameters, parameter, appSettingValue); 227 | } 228 | 229 | foreach (var parameter in parameters.Where(p => p.AllowEnvironmentVariable && !setParameters.Contains(p))) 230 | { 231 | if (!environmentSettings.HasEnvironmentVariable(parameter.Name)) continue; 232 | 233 | var appSettingValue = environmentSettings.GetEnvironmentVariable(parameter.Name); 234 | 235 | SetParameter(commandInstance, setParameters, parameter, appSettingValue); 236 | } 237 | } 238 | 239 | void ResolveParametersWithDefaultValues(IEnumerable setParameters, ICommand commandInstance) 240 | { 241 | foreach (var parameterWithDefaultValue in Parameters.Where(p => p.HasDefaultValue).Except(setParameters)) 242 | { 243 | parameterWithDefaultValue.ApplyDefaultValue(commandInstance); 244 | } 245 | } 246 | 247 | void ResolveParametersFromSwitches(IEnumerable switches, ICommand commandInstance, ISet setParameters) 248 | { 249 | foreach (var switchToSet in switches) 250 | { 251 | var correspondingParameter = Parameters.FirstOrDefault(p => p.MatchesKey(switchToSet.Key)); 252 | 253 | if (correspondingParameter == null) 254 | { 255 | throw new GoCommandoException( 256 | $"The switch {_settings}{switchToSet.Key} does not correspond to a parameter of the '{Command}' command!"); 257 | } 258 | 259 | var value = switchToSet.Value; 260 | 261 | SetParameter(commandInstance, setParameters, correspondingParameter, value); 262 | } 263 | } 264 | 265 | static void SetParameter(ICommand commandInstance, ISet setParameters, Parameter parameter, string value) 266 | { 267 | parameter.SetValue(commandInstance, value); 268 | setParameters.Add(parameter); 269 | } 270 | 271 | static bool CanBeResolvedFromEnvironmentSettings(EnvironmentSettings environmentSettings, Parameter parameter) 272 | { 273 | var name = parameter.Name; 274 | 275 | if (parameter.AllowAppSetting && environmentSettings.HasAppSetting(name)) 276 | { 277 | return true; 278 | } 279 | 280 | if (parameter.AllowConnectionString && environmentSettings.HasConnectionString(name)) 281 | { 282 | return true; 283 | } 284 | 285 | if (parameter.AllowEnvironmentVariable && environmentSettings.HasEnvironmentVariable(name)) 286 | { 287 | return true; 288 | } 289 | 290 | return false; 291 | } 292 | 293 | static bool CanBeResolvedFromSwitches(IEnumerable switches, Parameter p) 294 | { 295 | return switches.Any(s => p.MatchesKey(s.Key)); 296 | } 297 | } 298 | } -------------------------------------------------------------------------------- /GoCommando/Internals/EnvironmentSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace GoCommando.Internals 5 | { 6 | class EnvironmentSettings 7 | { 8 | static readonly IDictionary None = new Dictionary(); 9 | public static readonly EnvironmentSettings Empty = new EnvironmentSettings(None, None); 10 | 11 | readonly IDictionary _appSettings; 12 | readonly IDictionary _connectionStrings; 13 | readonly IDictionary _environmentVariables; 14 | 15 | public EnvironmentSettings(IDictionary appSettings = null, IDictionary connectionStrings = null, IDictionary environmentVariables = null) 16 | { 17 | _environmentVariables = environmentVariables ?? None; 18 | _appSettings = appSettings ?? None; 19 | _connectionStrings = connectionStrings ?? None; 20 | } 21 | 22 | public bool HasAppSetting(string name) 23 | { 24 | return _appSettings.ContainsKey(name); 25 | } 26 | 27 | public bool HasConnectionString(string name) 28 | { 29 | return _connectionStrings.ContainsKey(name); 30 | } 31 | 32 | public bool HasEnvironmentVariable(string name) 33 | { 34 | return _environmentVariables.ContainsKey(name); 35 | } 36 | 37 | public string GetAppSetting(string key) 38 | { 39 | try 40 | { 41 | return _appSettings[key]; 42 | } 43 | catch (Exception exception) 44 | { 45 | throw new KeyNotFoundException($"Could not find appSetting with key '{key}'", exception); 46 | } 47 | } 48 | 49 | public string GetEnvironmentVariable(string name) 50 | { 51 | try 52 | { 53 | return _environmentVariables[name]; 54 | } 55 | catch (Exception exception) 56 | { 57 | throw new KeyNotFoundException($"Could not find environment variable with the name '{name}'", exception); 58 | } 59 | } 60 | 61 | public string GetConnectionString(string name) 62 | { 63 | try 64 | { 65 | return _connectionStrings[name]; 66 | } 67 | catch (Exception exception) 68 | { 69 | throw new KeyNotFoundException($"Could not find connectionString with key '{name}'", exception); 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /GoCommando/Internals/InternalsVisibleTo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("GoCommando.Tests")] -------------------------------------------------------------------------------- /GoCommando/Internals/Parameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | namespace GoCommando.Internals 7 | { 8 | class Parameter : IEquatable 9 | { 10 | public PropertyInfo PropertyInfo { get; } 11 | public string Name { get; } 12 | public string Shortname { get; } 13 | public bool Optional { get; } 14 | public string DescriptionText { get; } 15 | public string DefaultValue { get; } 16 | public bool AllowAppSetting { get; } 17 | public bool AllowConnectionString { get; } 18 | public bool AllowEnvironmentVariable { get; } 19 | public string[] ExampleValues { get; } 20 | 21 | public bool IsFlag => PropertyInfo.PropertyType == typeof(bool); 22 | 23 | public bool HasDefaultValue => DefaultValue != null; 24 | 25 | public Parameter(PropertyInfo propertyInfo, string name, string shortname, bool optional, string descriptionText, IEnumerable exampleValues, string defaultValue, bool allowAppSetting, bool allowConnectionString, bool allowEnvironmentVariable) 26 | { 27 | PropertyInfo = propertyInfo; 28 | Name = name; 29 | Shortname = shortname; 30 | Optional = optional; 31 | DescriptionText = GetText(descriptionText, allowAppSetting, allowConnectionString, allowEnvironmentVariable); 32 | DefaultValue = defaultValue; 33 | AllowAppSetting = allowAppSetting; 34 | AllowConnectionString = allowConnectionString; 35 | AllowEnvironmentVariable = allowEnvironmentVariable; 36 | ExampleValues = exampleValues.ToArray(); 37 | } 38 | 39 | private string GetText(string descriptionText, bool allowAppSetting, bool allowConnectionString, bool allowEnvironmentVariable) 40 | { 41 | if (!allowAppSetting && !allowConnectionString && !allowEnvironmentVariable) 42 | { 43 | return $"{descriptionText ?? ""}"; 44 | } 45 | 46 | var autoBindings = new List(); 47 | 48 | if (allowEnvironmentVariable) 49 | { 50 | autoBindings.Add("ENV"); 51 | } 52 | 53 | if (allowAppSetting) 54 | { 55 | autoBindings.Add("APP"); 56 | } 57 | 58 | if (allowConnectionString) 59 | { 60 | autoBindings.Add("CONN"); 61 | } 62 | 63 | return $"{descriptionText ?? ""} ({string.Join(", ", autoBindings)})"; 64 | } 65 | 66 | public bool MatchesKey(string key) 67 | { 68 | return key == Name 69 | || (Shortname != null && key == Shortname); 70 | } 71 | 72 | public void SetValue(object commandInstance, string value) 73 | { 74 | try 75 | { 76 | var valueInTheRightType = PropertyInfo.PropertyType == typeof(bool) 77 | ? true 78 | : Convert.ChangeType(value, PropertyInfo.PropertyType); 79 | 80 | PropertyInfo.SetValue(commandInstance, valueInTheRightType); 81 | } 82 | catch (Exception exception) 83 | { 84 | throw new FormatException($"Could not set value '{value}' on property named '{PropertyInfo.Name}' on {PropertyInfo.DeclaringType}", exception); 85 | } 86 | } 87 | 88 | public void ApplyDefaultValue(ICommand commandInstance) 89 | { 90 | if (!HasDefaultValue) 91 | { 92 | throw new InvalidOperationException($"Cannot apply default value of '{Name}' parameter because it has no default!"); 93 | } 94 | 95 | SetValue(commandInstance, DefaultValue); 96 | } 97 | 98 | public bool Equals(Parameter other) 99 | { 100 | return Name.Equals(other.Name); 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /GoCommando/Internals/Settings.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando.Internals 2 | { 3 | class Settings 4 | { 5 | public Settings() 6 | { 7 | SwitchPrefix = "-"; 8 | } 9 | 10 | public string SwitchPrefix { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /GoCommando/Internals/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text; 4 | 5 | namespace GoCommando.Internals 6 | { 7 | static class StringExtensions 8 | { 9 | public static string WrappedAt(this string str, int width) 10 | { 11 | var twoLineBreaks = Environment.NewLine + Environment.NewLine; 12 | 13 | var sections = str.Split(new[] { twoLineBreaks }, 14 | StringSplitOptions.RemoveEmptyEntries); 15 | 16 | return string.Join(twoLineBreaks, sections.Select(section => WrapSection(section, width))); 17 | } 18 | 19 | static string WrapSection(string section, int width) 20 | { 21 | var oneLongString = string.Join(" ", 22 | section.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)); 23 | 24 | var words = oneLongString.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); 25 | 26 | var builder = new StringBuilder(); 27 | 28 | var currentLineLength = 0; 29 | 30 | for (var index = 0; index < words.Length; index++) 31 | { 32 | var word = words[index]; 33 | builder.Append(word); 34 | currentLineLength += word.Length; 35 | 36 | if (index < words.Length - 1) 37 | { 38 | var nextWord = words[index]; 39 | 40 | var spaceLeftOnCurrentLine = width - currentLineLength - 1; // -1 to leave room for space... 41 | var nextWordIsTooLong = nextWord.Length > spaceLeftOnCurrentLine; 42 | 43 | if (nextWordIsTooLong) 44 | { 45 | builder.AppendLine(); 46 | currentLineLength = 0; 47 | } 48 | else 49 | { 50 | builder.Append(" "); 51 | currentLineLength++; 52 | } 53 | } 54 | } 55 | 56 | return builder.ToString(); 57 | } 58 | 59 | public static string Indented(this string str, int indent) 60 | { 61 | var indentedLines = str 62 | .Split(new[] { Environment.NewLine }, StringSplitOptions.None) 63 | .Select(line => string.Concat(new string(' ', indent), line)); 64 | 65 | return string.Join(Environment.NewLine, indentedLines); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /GoCommando/Internals/Switch.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable LoopCanBeConvertedToQuery 2 | namespace GoCommando.Internals 3 | { 4 | class Switch 5 | { 6 | static readonly char[] AcceptedQuoteCharacters = { '"', '\'' }; 7 | 8 | public static Switch KeyValue(string key, string value) 9 | { 10 | return new Switch(key, value); 11 | } 12 | 13 | public static Switch Flag(string key) 14 | { 15 | return new Switch(key, null); 16 | } 17 | 18 | Switch(string key, string value) 19 | { 20 | Key = key; 21 | Value = Unquote(value); 22 | } 23 | 24 | static string Unquote(string value) 25 | { 26 | if (value == null) return null; 27 | 28 | // can't be quoted 29 | if (value.Length < 2) return value; 30 | 31 | foreach (var quoteChar in AcceptedQuoteCharacters) 32 | { 33 | var quote = quoteChar.ToString(); 34 | 35 | if (value.StartsWith(quote) 36 | && value.EndsWith(quote)) 37 | { 38 | return value.Substring(1, value.Length - 2); 39 | } 40 | } 41 | 42 | return value; 43 | } 44 | 45 | public string Key { get; } 46 | public string Value { get; } 47 | 48 | public override string ToString() 49 | { 50 | return Value == null 51 | ? Key 52 | : $"{Key} = {Value}"; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /GoCommando/ParameterAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Apply this attribute to a property of a command class (i.e. one that implements ) 7 | /// 8 | [AttributeUsage(AttributeTargets.Property)] 9 | public class ParameterAttribute : Attribute 10 | { 11 | /// 12 | /// Gets the primary parameter name 13 | /// 14 | public string Name { get; } 15 | 16 | /// 17 | /// Gets a shorthand for the parameter (or null if none has been specified) 18 | /// 19 | public string ShortName { get; } 20 | 21 | /// 22 | /// Gets whether this parameter is optional 23 | /// 24 | public bool Optional { get; } 25 | 26 | /// 27 | /// Gets a default value for the parameter (or null if none has been specified) 28 | /// 29 | public string DefaultValue { get; } 30 | 31 | /// 32 | /// Gets whether this parameter can have its value resolved from the <appSettings> section of the application configuration file. 33 | /// If the value is provided with a command-line switch, the provided value takes precedence. 34 | /// 35 | public bool AllowAppSetting { get; } 36 | 37 | /// 38 | /// Gets whether this parameter can have its value resolved from the <connectionStrings> section of the application configuration file. 39 | /// If the value is provided with a command-line switch, the provided value takes precedence. 40 | /// 41 | public bool AllowConnectionString { get; } 42 | 43 | /// 44 | /// Gets whether this parameter can have its value resolved from an environment variable with the same name as specified by 45 | /// If the value is provided with a command-line switch, the provided value takes precedence. 46 | /// 47 | public bool AllowEnvironmentVariable { get; } 48 | 49 | /// 50 | /// Constructs the parameter attribute 51 | /// 52 | /// Primary name of the parameter 53 | /// Optional shorthand of the parameter 54 | /// Indicates whether the parameter MUST be specified or can be omitted 55 | /// Provides a default value to use when other values could not be found 56 | /// 57 | /// Indicates whether parameter value resolution can go and look in the <appSettings> section of 58 | /// the current application configuration file for a value. Will look for the key specified by 59 | /// 60 | /// 61 | /// Indicates whether parameter value resolution can go and look in the <connectionStrings> section of 62 | /// the current application configuration file for a value. Will look for the name specified by 63 | /// 64 | /// 65 | /// Indicates whether parameter value resolution can go and look for an environment variable for a value. 66 | /// Will look for the name specified by 67 | /// 68 | public ParameterAttribute(string name, string shortName = null, bool optional = false, string defaultValue = null, bool allowAppSetting = false, bool allowConnectionString = false, bool allowEnvironmentVariable = false) 69 | { 70 | Name = name; 71 | ShortName = shortName; 72 | Optional = optional; 73 | DefaultValue = defaultValue; 74 | AllowAppSetting = allowAppSetting; 75 | AllowConnectionString = allowConnectionString; 76 | AllowEnvironmentVariable = allowEnvironmentVariable; 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /GoCommando/SupportImpersonationAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Apply this attribute to the class that has your Main method in order to support impersonation 7 | /// 8 | [AttributeUsage(AttributeTargets.Class)] 9 | public class SupportImpersonationAttribute : Attribute 10 | { 11 | } 12 | } -------------------------------------------------------------------------------- /GoCommando_old/BannerAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Apply this attribute to the class that has your Main method in order to have a nice banner printed out when the program starts 7 | /// 8 | [AttributeUsage(AttributeTargets.Class)] 9 | public class BannerAttribute : Attribute 10 | { 11 | /// 12 | /// Gets the banner text 13 | /// 14 | public string BannerText { get; } 15 | 16 | /// 17 | /// Constructs the attribute 18 | /// 19 | public BannerAttribute(string bannerText) 20 | { 21 | BannerText = bannerText; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /GoCommando_old/CommandAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Attribute that can be applied to a class that represents a command. The class must implement 7 | /// 8 | [AttributeUsage(AttributeTargets.Class)] 9 | public class CommandAttribute : Attribute 10 | { 11 | /// 12 | /// Gets the name of the command 13 | /// 14 | public string Command { get; } 15 | 16 | /// 17 | /// Gets the name of the command's group (if any). Grouping commands affects how they are presented when printing 18 | /// help texts 19 | /// 20 | public string Group { get; } 21 | 22 | /// 23 | /// Constructs the attribute 24 | /// 25 | public CommandAttribute(string command, string group = null) 26 | { 27 | Command = command; 28 | Group = group ?? ""; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /GoCommando_old/DescriptionAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Apply this attribute to a property of a command class (which is also decorated with ) in 7 | /// order to provide a description of the parameter 8 | /// 9 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)] 10 | public class DescriptionAttribute : Attribute 11 | { 12 | /// 13 | /// Gets the description text 14 | /// 15 | public string DescriptionText { get; } 16 | 17 | /// 18 | /// Constructs the attribute 19 | /// 20 | public DescriptionAttribute(string descriptionText) 21 | { 22 | DescriptionText = descriptionText; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /GoCommando_old/ExampleAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Apply one or more of these to a command property to show examples on how this particular parameter can be used 7 | /// 8 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] 9 | public class ExampleAttribute : Attribute 10 | { 11 | /// 12 | /// Gets the example text 13 | /// 14 | public string ExampleValue { get; } 15 | 16 | /// 17 | /// Constructs the attribute 18 | /// 19 | public ExampleAttribute(string exampleValue) 20 | { 21 | ExampleValue = exampleValue; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /GoCommando_old/ExitCodeException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace GoCommando 5 | { 6 | /// 7 | /// Exception that can be used to exit the program with a custom exit code 8 | /// 9 | [Serializable] 10 | public class CustomExitCodeException : Exception 11 | { 12 | /// 13 | /// Constructs the exception 14 | /// 15 | protected CustomExitCodeException(SerializationInfo info, StreamingContext context) : base(info, context) 16 | { 17 | } 18 | 19 | /// 20 | /// Constructs the exception 21 | /// 22 | public CustomExitCodeException(int exitCode, string message) : base(message) 23 | { 24 | ExitCode = exitCode; 25 | } 26 | 27 | /// 28 | /// Gets the exit code that the program must exit with 29 | /// 30 | public int ExitCode { get; } 31 | } 32 | } -------------------------------------------------------------------------------- /GoCommando_old/GoCommando.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2839AA55-B40A-4BB8-BDA0-C5057E5A683F} 8 | Library 9 | Properties 10 | GoCommando 11 | GoCommando 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | bin\Release\GoCommando.XML 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 76 | -------------------------------------------------------------------------------- /GoCommando_old/GoCommandoException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace GoCommando 5 | { 6 | /// 7 | /// Friendly exception that can be thrown in cases where you want the program to exit with 8 | /// a nice, human-readable message. Only the message will be shown. 9 | /// 10 | [Serializable] 11 | public class GoCommandoException : Exception 12 | { 13 | /// 14 | /// Constructs the exception 15 | /// 16 | protected GoCommandoException(SerializationInfo info, StreamingContext context) : base(info, context) 17 | { 18 | } 19 | 20 | /// 21 | /// Constructs the exception 22 | /// 23 | public GoCommandoException(string message) : base(message) 24 | { 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /GoCommando_old/ICommand.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando 2 | { 3 | /// 4 | /// Implement this interface on each command 5 | /// 6 | public interface ICommand 7 | { 8 | /// 9 | /// Main run method that is invoked by GoCommando 10 | /// 11 | void Run(); 12 | } 13 | } -------------------------------------------------------------------------------- /GoCommando_old/ICommandFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Can be implemented to supply a custom command factory that will be given a chance to create command instances 7 | /// and dispose of them after use 8 | /// 9 | public interface ICommandFactory 10 | { 11 | /// 12 | /// Should create a new command instance of the given 13 | /// 14 | ICommand Create(Type commandType); 15 | 16 | /// 17 | /// Should release the command instance - probably by disposing it or delegating the disposal to an IoC container 18 | /// 19 | void Release(ICommand command); 20 | } 21 | } -------------------------------------------------------------------------------- /GoCommando_old/Internals/Arguments.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace GoCommando.Internals 6 | { 7 | class Arguments 8 | { 9 | readonly Settings _settings; 10 | 11 | public Arguments(string command, IEnumerable switches, Settings settings) 12 | { 13 | _settings = settings; 14 | var switchList = switches.ToList(); 15 | var duplicateSwitchKeys = switchList.GroupBy(s => s.Key).Where(g => g.Count() > 1).ToList(); 16 | 17 | if (duplicateSwitchKeys.Any()) 18 | { 19 | var dupes = string.Join(", ", duplicateSwitchKeys.Select(g => $"{settings.SwitchPrefix}{g.Key}")); 20 | 21 | throw new GoCommandoException($"The following switches have been specified more than once: {dupes}"); 22 | } 23 | 24 | Command = command; 25 | Switches = switchList; 26 | } 27 | 28 | public string Command { get; } 29 | 30 | public IEnumerable Switches { get; } 31 | 32 | public TValue Get(string key) 33 | { 34 | var desiredType = typeof(TValue); 35 | 36 | try 37 | { 38 | if (desiredType == typeof(bool)) 39 | { 40 | return (TValue)Convert.ChangeType(Switches.Any(s => s.Key == key), desiredType); 41 | } 42 | 43 | var relevantSwitch = Switches.FirstOrDefault(s => s.Key == key); 44 | 45 | if (relevantSwitch != null) 46 | { 47 | return (TValue)Convert.ChangeType(relevantSwitch.Value, desiredType); 48 | } 49 | 50 | throw new GoCommandoException($"Could not find switch '{key}'"); 51 | } 52 | catch (Exception exception) 53 | { 54 | throw new FormatException($"Could not get switch '{key}' as a {desiredType}", exception); 55 | } } 56 | 57 | public override string ToString() 58 | { 59 | return $@"{Command} 60 | 61 | {string.Join(Environment.NewLine, Switches.Select(s => " " + s))}"; 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /GoCommando_old/Internals/CommandInvoker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | namespace GoCommando.Internals 7 | { 8 | class CommandInvoker 9 | { 10 | readonly Settings _settings; 11 | readonly ICommand _commandInstance; 12 | readonly Action _releaser; 13 | readonly List _parameters; 14 | 15 | public CommandInvoker(string command, Type type, Settings settings, string @group = null, 16 | ICommandFactory commandFactory = null) 17 | : this(command, settings, CreateInstance(type, GetFactoryMethod(commandFactory)), group, GetReleaseMethod(commandFactory)) 18 | { 19 | } 20 | 21 | public CommandInvoker(string command, Settings settings, ICommand commandInstance, string group = null, Action releaseMethod = null) 22 | { 23 | if (command == null) throw new ArgumentNullException(nameof(command)); 24 | if (settings == null) throw new ArgumentNullException(nameof(settings)); 25 | if (commandInstance == null) throw new ArgumentNullException(nameof(commandInstance)); 26 | 27 | _settings = settings; 28 | _commandInstance = commandInstance; 29 | _releaser = releaseMethod ?? DefaultReleaseMethod; 30 | 31 | Command = command; 32 | Group = group; 33 | 34 | _parameters = GetParameters(Type).ToList(); 35 | } 36 | 37 | static void DefaultReleaseMethod(ICommand command) 38 | { 39 | var disposable = command as IDisposable; 40 | 41 | disposable?.Dispose(); 42 | } 43 | 44 | static Func GetFactoryMethod(ICommandFactory commandFactory) 45 | { 46 | if (commandFactory == null) return null; 47 | 48 | return commandFactory.Create; 49 | } 50 | 51 | static Action GetReleaseMethod(ICommandFactory commandFactory) 52 | { 53 | if (commandFactory == null) return null; 54 | 55 | return commandFactory.Release; 56 | } 57 | 58 | static ICommand CreateInstance(Type type, Func commandFactory = null) 59 | { 60 | try 61 | { 62 | var instance = commandFactory?.Invoke(type) 63 | ?? Activator.CreateInstance(type); 64 | 65 | if (!(instance is ICommand)) 66 | { 67 | throw new ApplicationException($"{instance} does not implement ICommand!"); 68 | } 69 | 70 | return (ICommand)instance; 71 | } 72 | catch (Exception exception) 73 | { 74 | throw new ApplicationException($"Could not use type {type} as a GoCommando command", exception); 75 | } 76 | } 77 | 78 | static IEnumerable GetParameters(Type type) 79 | { 80 | return type 81 | .GetProperties() 82 | .Select(p => new 83 | { 84 | Property = p, 85 | ParameterAttribute = GetSingleAttributeOrNull(p), 86 | DescriptionAttribute = GetSingleAttributeOrNull(p), 87 | ExampleAttributes = p.GetCustomAttributes() 88 | }) 89 | .Where(a => a.ParameterAttribute != null) 90 | .Select(a => new Parameter(a.Property, 91 | a.ParameterAttribute.Name, 92 | a.ParameterAttribute.ShortName, 93 | a.ParameterAttribute.Optional, 94 | a.DescriptionAttribute?.DescriptionText, 95 | a.ExampleAttributes.Select(e => e.ExampleValue), 96 | a.ParameterAttribute.DefaultValue, 97 | a.ParameterAttribute.AllowAppSetting, 98 | a.ParameterAttribute.AllowConnectionString, 99 | a.ParameterAttribute.AllowEnvironmentVariable)) 100 | .ToList(); 101 | } 102 | 103 | static TAttribute GetSingleAttributeOrNull(PropertyInfo p) where TAttribute : Attribute 104 | { 105 | return p.GetCustomAttributes(typeof(TAttribute), false) 106 | .Cast() 107 | .FirstOrDefault(); 108 | } 109 | 110 | public string Group { get; } 111 | 112 | public string Command { get; } 113 | 114 | public Type Type => _commandInstance.GetType(); 115 | 116 | public IEnumerable Parameters => _parameters; 117 | 118 | public string Description => Type.GetCustomAttribute()?.DescriptionText ?? 119 | "(no help text for this command)"; 120 | 121 | public ICommand CommandInstance => _commandInstance; 122 | 123 | public void Invoke(IEnumerable switches, EnvironmentSettings environmentSettings) 124 | { 125 | try 126 | { 127 | InnerInvoke(switches, environmentSettings); 128 | } 129 | finally 130 | { 131 | _releaser(CommandInstance); 132 | } 133 | } 134 | 135 | void InnerInvoke(IEnumerable switches, EnvironmentSettings environmentSettings) 136 | { 137 | var commandInstance = _commandInstance; 138 | 139 | var requiredParametersMissing = Parameters 140 | .Where(p => !p.Optional 141 | && !p.HasDefaultValue 142 | && !CanBeResolvedFromSwitches(switches, p) 143 | && !CanBeResolvedFromEnvironmentSettings(environmentSettings, p)) 144 | .ToList(); 145 | 146 | var optionalParamtersNotSpecified = Parameters 147 | .Where(p => p.Optional 148 | && !CanBeResolvedFromSwitches(switches, p) 149 | && !CanBeResolvedFromEnvironmentSettings(environmentSettings, p)) 150 | .ToList(); 151 | 152 | if (requiredParametersMissing.Any()) 153 | { 154 | var requiredParametersMissingString = string.Join(Environment.NewLine, 155 | requiredParametersMissing.Select(p => $" {_settings.SwitchPrefix}{p.Name} - {p.DescriptionText}")); 156 | 157 | var text = $@"The following required parameters are missing: 158 | 159 | {requiredParametersMissingString}"; 160 | 161 | if (optionalParamtersNotSpecified.Any()) 162 | { 163 | var optionalParamtersNotSpecifiedString = string.Join(Environment.NewLine, 164 | optionalParamtersNotSpecified.Select(p => $" {_settings.SwitchPrefix}{p.Name} - {p.DescriptionText}")); 165 | 166 | var moreText = $@"The following optional parameters are also available: 167 | 168 | {optionalParamtersNotSpecifiedString}"; 169 | 170 | throw new GoCommandoException(string.Concat( 171 | text, 172 | Environment.NewLine, 173 | Environment.NewLine, 174 | moreText 175 | )); 176 | } 177 | 178 | throw new GoCommandoException(text); 179 | } 180 | 181 | var switchesWithoutMathingParameter = switches 182 | .Where(s => !Parameters.Any(p => p.MatchesKey(s.Key))) 183 | .ToList(); 184 | 185 | if (switchesWithoutMathingParameter.Any()) 186 | { 187 | var switchesWithoutMathingParameterString = string.Join(Environment.NewLine, 188 | switchesWithoutMathingParameter.Select(p => p.Value != null 189 | ? $" {_settings.SwitchPrefix}{p.Key} = {p.Value}" 190 | : $" {_settings.SwitchPrefix}{p.Key}")); 191 | 192 | throw new GoCommandoException( 193 | $@"The following switches do not have a corresponding parameter: 194 | 195 | {switchesWithoutMathingParameterString}"); 196 | } 197 | 198 | var setParameters = new HashSet(); 199 | 200 | ResolveParametersFromSwitches(switches, commandInstance, setParameters); 201 | 202 | ResolveParametersFromEnvironmentSettings(environmentSettings, commandInstance, setParameters, Parameters); 203 | 204 | ResolveParametersWithDefaultValues(setParameters, commandInstance); 205 | 206 | commandInstance.Run(); 207 | } 208 | 209 | static void ResolveParametersFromEnvironmentSettings(EnvironmentSettings environmentSettings, ICommand commandInstance, HashSet setParameters, IEnumerable parameters) 210 | { 211 | foreach (var parameter in parameters.Where(p => p.AllowAppSetting && !setParameters.Contains(p))) 212 | { 213 | if (!environmentSettings.HasAppSetting(parameter.Name)) continue; 214 | 215 | var appSettingValue = environmentSettings.GetAppSetting(parameter.Name); 216 | 217 | SetParameter(commandInstance, setParameters, parameter, appSettingValue); 218 | } 219 | 220 | foreach (var parameter in parameters.Where(p => p.AllowConnectionString && !setParameters.Contains(p))) 221 | { 222 | if (!environmentSettings.HasConnectionString(parameter.Name)) continue; 223 | 224 | var appSettingValue = environmentSettings.GetConnectionString(parameter.Name); 225 | 226 | SetParameter(commandInstance, setParameters, parameter, appSettingValue); 227 | } 228 | 229 | foreach (var parameter in parameters.Where(p => p.AllowEnvironmentVariable && !setParameters.Contains(p))) 230 | { 231 | if (!environmentSettings.HasEnvironmentVariable(parameter.Name)) continue; 232 | 233 | var appSettingValue = environmentSettings.GetEnvironmentVariable(parameter.Name); 234 | 235 | SetParameter(commandInstance, setParameters, parameter, appSettingValue); 236 | } 237 | } 238 | 239 | void ResolveParametersWithDefaultValues(IEnumerable setParameters, ICommand commandInstance) 240 | { 241 | foreach (var parameterWithDefaultValue in Parameters.Where(p => p.HasDefaultValue).Except(setParameters)) 242 | { 243 | parameterWithDefaultValue.ApplyDefaultValue(commandInstance); 244 | } 245 | } 246 | 247 | void ResolveParametersFromSwitches(IEnumerable switches, ICommand commandInstance, ISet setParameters) 248 | { 249 | foreach (var switchToSet in switches) 250 | { 251 | var correspondingParameter = Parameters.FirstOrDefault(p => p.MatchesKey(switchToSet.Key)); 252 | 253 | if (correspondingParameter == null) 254 | { 255 | throw new GoCommandoException( 256 | $"The switch {_settings}{switchToSet.Key} does not correspond to a parameter of the '{Command}' command!"); 257 | } 258 | 259 | var value = switchToSet.Value; 260 | 261 | SetParameter(commandInstance, setParameters, correspondingParameter, value); 262 | } 263 | } 264 | 265 | static void SetParameter(ICommand commandInstance, ISet setParameters, Parameter parameter, string value) 266 | { 267 | parameter.SetValue(commandInstance, value); 268 | setParameters.Add(parameter); 269 | } 270 | 271 | static bool CanBeResolvedFromEnvironmentSettings(EnvironmentSettings environmentSettings, Parameter parameter) 272 | { 273 | var name = parameter.Name; 274 | 275 | if (parameter.AllowAppSetting && environmentSettings.HasAppSetting(name)) 276 | { 277 | return true; 278 | } 279 | 280 | if (parameter.AllowConnectionString && environmentSettings.HasConnectionString(name)) 281 | { 282 | return true; 283 | } 284 | 285 | if (parameter.AllowEnvironmentVariable && environmentSettings.HasEnvironmentVariable(name)) 286 | { 287 | return true; 288 | } 289 | 290 | return false; 291 | } 292 | 293 | static bool CanBeResolvedFromSwitches(IEnumerable switches, Parameter p) 294 | { 295 | return switches.Any(s => p.MatchesKey(s.Key)); 296 | } 297 | } 298 | } -------------------------------------------------------------------------------- /GoCommando_old/Internals/EnvironmentSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace GoCommando.Internals 5 | { 6 | class EnvironmentSettings 7 | { 8 | static readonly IDictionary None = new Dictionary(); 9 | public static readonly EnvironmentSettings Empty = new EnvironmentSettings(None, None); 10 | 11 | readonly IDictionary _appSettings; 12 | readonly IDictionary _connectionStrings; 13 | readonly IDictionary _environmentVariables; 14 | 15 | public EnvironmentSettings(IDictionary appSettings = null, IDictionary connectionStrings = null, IDictionary environmentVariables = null) 16 | { 17 | _environmentVariables = environmentVariables ?? None; 18 | _appSettings = appSettings ?? None; 19 | _connectionStrings = connectionStrings ?? None; 20 | } 21 | 22 | public bool HasAppSetting(string name) 23 | { 24 | return _appSettings.ContainsKey(name); 25 | } 26 | 27 | public bool HasConnectionString(string name) 28 | { 29 | return _connectionStrings.ContainsKey(name); 30 | } 31 | 32 | public bool HasEnvironmentVariable(string name) 33 | { 34 | return _environmentVariables.ContainsKey(name); 35 | } 36 | 37 | public string GetAppSetting(string key) 38 | { 39 | try 40 | { 41 | return _appSettings[key]; 42 | } 43 | catch (Exception exception) 44 | { 45 | throw new KeyNotFoundException($"Could not find appSetting with key '{key}'", exception); 46 | } 47 | } 48 | 49 | public string GetEnvironmentVariable(string name) 50 | { 51 | try 52 | { 53 | return _environmentVariables[name]; 54 | } 55 | catch (Exception exception) 56 | { 57 | throw new KeyNotFoundException($"Could not find environment variable with the name '{name}'", exception); 58 | } 59 | } 60 | 61 | public string GetConnectionString(string name) 62 | { 63 | try 64 | { 65 | return _connectionStrings[name]; 66 | } 67 | catch (Exception exception) 68 | { 69 | throw new KeyNotFoundException($"Could not find connectionString with key '{name}'", exception); 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /GoCommando_old/Internals/Parameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | namespace GoCommando.Internals 7 | { 8 | class Parameter : IEquatable 9 | { 10 | public PropertyInfo PropertyInfo { get; } 11 | public string Name { get; } 12 | public string Shortname { get; } 13 | public bool Optional { get; } 14 | public string DescriptionText { get; } 15 | public string DefaultValue { get; } 16 | public bool AllowAppSetting { get; } 17 | public bool AllowConnectionString { get; } 18 | public bool AllowEnvironmentVariable { get; } 19 | public string[] ExampleValues { get; } 20 | 21 | public bool IsFlag => PropertyInfo.PropertyType == typeof(bool); 22 | 23 | public bool HasDefaultValue => DefaultValue != null; 24 | 25 | public Parameter(PropertyInfo propertyInfo, string name, string shortname, bool optional, string descriptionText, IEnumerable exampleValues, string defaultValue, bool allowAppSetting, bool allowConnectionString, bool allowEnvironmentVariable) 26 | { 27 | PropertyInfo = propertyInfo; 28 | Name = name; 29 | Shortname = shortname; 30 | Optional = optional; 31 | DescriptionText = GetText(descriptionText, allowAppSetting, allowConnectionString, allowEnvironmentVariable); 32 | DefaultValue = defaultValue; 33 | AllowAppSetting = allowAppSetting; 34 | AllowConnectionString = allowConnectionString; 35 | AllowEnvironmentVariable = allowEnvironmentVariable; 36 | ExampleValues = exampleValues.ToArray(); 37 | } 38 | 39 | private string GetText(string descriptionText, bool allowAppSetting, bool allowConnectionString, bool allowEnvironmentVariable) 40 | { 41 | if (!allowAppSetting && !allowConnectionString && !allowEnvironmentVariable) 42 | { 43 | return $"{descriptionText ?? ""}"; 44 | } 45 | 46 | var autoBindings = new List(); 47 | 48 | if (allowEnvironmentVariable) 49 | { 50 | autoBindings.Add("ENV"); 51 | } 52 | 53 | if (allowAppSetting) 54 | { 55 | autoBindings.Add("APP"); 56 | } 57 | 58 | if (allowConnectionString) 59 | { 60 | autoBindings.Add("CONN"); 61 | } 62 | 63 | return $"{descriptionText ?? ""} ({string.Join(", ", autoBindings)})"; 64 | } 65 | 66 | public bool MatchesKey(string key) 67 | { 68 | return key == Name 69 | || (Shortname != null && key == Shortname); 70 | } 71 | 72 | public void SetValue(object commandInstance, string value) 73 | { 74 | try 75 | { 76 | var valueInTheRightType = PropertyInfo.PropertyType == typeof(bool) 77 | ? true 78 | : Convert.ChangeType(value, PropertyInfo.PropertyType); 79 | 80 | PropertyInfo.SetValue(commandInstance, valueInTheRightType); 81 | } 82 | catch (Exception exception) 83 | { 84 | throw new FormatException($"Could not set value '{value}' on property named '{PropertyInfo.Name}' on {PropertyInfo.DeclaringType}", exception); 85 | } 86 | } 87 | 88 | public void ApplyDefaultValue(ICommand commandInstance) 89 | { 90 | if (!HasDefaultValue) 91 | { 92 | throw new InvalidOperationException($"Cannot apply default value of '{Name}' parameter because it has no default!"); 93 | } 94 | 95 | SetValue(commandInstance, DefaultValue); 96 | } 97 | 98 | public bool Equals(Parameter other) 99 | { 100 | return Name.Equals(other.Name); 101 | } 102 | } 103 | } -------------------------------------------------------------------------------- /GoCommando_old/Internals/Settings.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando.Internals 2 | { 3 | class Settings 4 | { 5 | public Settings() 6 | { 7 | SwitchPrefix = "-"; 8 | } 9 | 10 | public string SwitchPrefix { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /GoCommando_old/Internals/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Text; 4 | 5 | namespace GoCommando.Internals 6 | { 7 | static class StringExtensions 8 | { 9 | public static string WrappedAt(this string str, int width) 10 | { 11 | var twoLineBreaks = Environment.NewLine + Environment.NewLine; 12 | 13 | var sections = str.Split(new[] { twoLineBreaks }, 14 | StringSplitOptions.RemoveEmptyEntries); 15 | 16 | return string.Join(twoLineBreaks, sections.Select(section => WrapSection(section, width))); 17 | } 18 | 19 | static string WrapSection(string section, int width) 20 | { 21 | var oneLongString = string.Join(" ", 22 | section.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)); 23 | 24 | var words = oneLongString.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries); 25 | 26 | var builder = new StringBuilder(); 27 | 28 | var currentLineLength = 0; 29 | 30 | for (var index = 0; index < words.Length; index++) 31 | { 32 | var word = words[index]; 33 | builder.Append(word); 34 | currentLineLength += word.Length; 35 | 36 | if (index < words.Length - 1) 37 | { 38 | var nextWord = words[index]; 39 | 40 | var spaceLeftOnCurrentLine = width - currentLineLength - 1; // -1 to leave room for space... 41 | var nextWordIsTooLong = nextWord.Length > spaceLeftOnCurrentLine; 42 | 43 | if (nextWordIsTooLong) 44 | { 45 | builder.AppendLine(); 46 | currentLineLength = 0; 47 | } 48 | else 49 | { 50 | builder.Append(" "); 51 | currentLineLength++; 52 | } 53 | } 54 | } 55 | 56 | return builder.ToString(); 57 | } 58 | 59 | public static string Indented(this string str, int indent) 60 | { 61 | var indentedLines = str 62 | .Split(new[] { Environment.NewLine }, StringSplitOptions.None) 63 | .Select(line => string.Concat(new string(' ', indent), line)); 64 | 65 | return string.Join(Environment.NewLine, indentedLines); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /GoCommando_old/Internals/Switch.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable LoopCanBeConvertedToQuery 2 | namespace GoCommando.Internals 3 | { 4 | class Switch 5 | { 6 | static readonly char[] AcceptedQuoteCharacters = { '"', '\'' }; 7 | 8 | public static Switch KeyValue(string key, string value) 9 | { 10 | return new Switch(key, value); 11 | } 12 | 13 | public static Switch Flag(string key) 14 | { 15 | return new Switch(key, null); 16 | } 17 | 18 | Switch(string key, string value) 19 | { 20 | Key = key; 21 | Value = Unquote(value); 22 | } 23 | 24 | static string Unquote(string value) 25 | { 26 | if (value == null) return null; 27 | 28 | // can't be quoted 29 | if (value.Length < 2) return value; 30 | 31 | foreach (var quoteChar in AcceptedQuoteCharacters) 32 | { 33 | var quote = quoteChar.ToString(); 34 | 35 | if (value.StartsWith(quote) 36 | && value.EndsWith(quote)) 37 | { 38 | return value.Substring(1, value.Length - 2); 39 | } 40 | } 41 | 42 | return value; 43 | } 44 | 45 | public string Key { get; } 46 | public string Value { get; } 47 | 48 | public override string ToString() 49 | { 50 | return Value == null 51 | ? Key 52 | : $"{Key} = {Value}"; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /GoCommando_old/ParameterAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Apply this attribute to a property of a command class (i.e. one that implements ) 7 | /// 8 | [AttributeUsage(AttributeTargets.Property)] 9 | public class ParameterAttribute : Attribute 10 | { 11 | /// 12 | /// Gets the primary parameter name 13 | /// 14 | public string Name { get; } 15 | 16 | /// 17 | /// Gets a shorthand for the parameter (or null if none has been specified) 18 | /// 19 | public string ShortName { get; } 20 | 21 | /// 22 | /// Gets whether this parameter is optional 23 | /// 24 | public bool Optional { get; } 25 | 26 | /// 27 | /// Gets a default value for the parameter (or null if none has been specified) 28 | /// 29 | public string DefaultValue { get; } 30 | 31 | /// 32 | /// Gets whether this parameter can have its value resolved from the <appSettings> section of the application configuration file. 33 | /// If the value is provided with a command-line switch, the provided value takes precedence. 34 | /// 35 | public bool AllowAppSetting { get; } 36 | 37 | /// 38 | /// Gets whether this parameter can have its value resolved from the <connectionStrings> section of the application configuration file. 39 | /// If the value is provided with a command-line switch, the provided value takes precedence. 40 | /// 41 | public bool AllowConnectionString { get; } 42 | 43 | /// 44 | /// Gets whether this parameter can have its value resolved from an environment variable with the same name as specified by 45 | /// If the value is provided with a command-line switch, the provided value takes precedence. 46 | /// 47 | public bool AllowEnvironmentVariable { get; } 48 | 49 | /// 50 | /// Constructs the parameter attribute 51 | /// 52 | /// Primary name of the parameter 53 | /// Optional shorthand of the parameter 54 | /// Indicates whether the parameter MUST be specified or can be omitted 55 | /// Provides a default value to use when other values could not be found 56 | /// 57 | /// Indicates whether parameter value resolution can go and look in the <appSettings> section of 58 | /// the current application configuration file for a value. Will look for the key specified by 59 | /// 60 | /// 61 | /// Indicates whether parameter value resolution can go and look in the <connectionStrings> section of 62 | /// the current application configuration file for a value. Will look for the name specified by 63 | /// 64 | /// 65 | /// Indicates whether parameter value resolution can go and look for an environment variable for a value. 66 | /// Will look for the name specified by 67 | /// 68 | public ParameterAttribute(string name, string shortName = null, bool optional = false, string defaultValue = null, bool allowAppSetting = false, bool allowConnectionString = false, bool allowEnvironmentVariable = false) 69 | { 70 | Name = name; 71 | ShortName = shortName; 72 | Optional = optional; 73 | DefaultValue = defaultValue; 74 | AllowAppSetting = allowAppSetting; 75 | AllowConnectionString = allowConnectionString; 76 | AllowEnvironmentVariable = allowEnvironmentVariable; 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /GoCommando_old/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("GoCommando")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("GoCommando")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("2839aa55-b40a-4bb8-bda0-c5057e5a683f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | [assembly: InternalsVisibleTo("GoCommando.Tests")] -------------------------------------------------------------------------------- /GoCommando_old/SupportImpersonationAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | /// 6 | /// Apply this attribute to the class that has your Main method in order to support impersonation 7 | /// 8 | [AttributeUsage(AttributeTargets.Class)] 9 | public class SupportImpersonationAttribute : Attribute 10 | { 11 | } 12 | } -------------------------------------------------------------------------------- /Package.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | GoCommando 5 | $version$ 6 | Mogens Heller Grabe 7 | Mogens Heller Grabe 8 | http://en.wikipedia.org/wiki/Beerware 9 | http://mookid.dk/oncode/gocommando 10 | GoCommando is a small command line utility helper that does the boring work when creating command line utilities in .NET. 11 | Copyright 2015 12 | command-line go-commando 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | What? 2 | ==== 3 | 4 | GoCommando is a small command line utility helper that does the boring work when creating command line utilities in .NET. 5 | 6 | More info coming soon at http://mookid.dk/gocommando 7 | 8 | One day, maybe I'll tweet something as well... [@mookid8000][2] 9 | 10 | How? 11 | ==== 12 | 13 | Create a new console application. `Install-Package GoCommando` to get the DLL, and then `Go.Run()` in the `Main` method. 14 | 15 | And then you add some classes that implement `ICommand` and you decorate them with `[Command]` and 16 | then you add properties to those classes, and then you decorate those with `[Parameter]`. 17 | 18 | And then you decorate the command class and the parameter properties with `[Description]`. 19 | 20 | And then you add a couple of `[Example]` to some of the parameter properties, just to be nice. 21 | 22 | Example! 23 | ==== 24 | 25 | This is the `white-russian` command in a fictive Beverage utility: 26 | 27 | 28 | [Command("white-russian")] 29 | [Description("Mixes a White Russian, pouring in milk till full")] 30 | public class WhiteRussian : ICommand 31 | { 32 | [Parameter("vodka")] 33 | [Description("How many cl of vodka?")] 34 | public double Vodka { get; set; } 35 | 36 | [Parameter("kahlua")] 37 | [Description("How many cl of Kahlua?")] 38 | public double Kahlua { get; set; } 39 | 40 | [Parameter("lukewarm", optional: true)] 41 | [Description("Avoid refrigerated ingredients?")] 42 | public bool LukeWarm { get; set; } 43 | 44 | public void Run() 45 | { 46 | Console.WriteLine($"Making a {(LukeWarm ? "luke-warm" : "")} beverage" + 47 | $" with {Vodka:0.#} cl of vodka" + 48 | $" and {Kahlua:0.#} cl of Kahlua"); 49 | } 50 | } 51 | 52 | If you invoke it without its command, it will print out the available commands: 53 | 54 | C:\> beverage.exe 55 | 56 | ------------------------------ 57 | Beverage Utility 58 | 59 | Copyright (c) 2015 El Duderino 60 | ------------------------------ 61 | Please invoke with a command - the following commands are available: 62 | 63 | white-russian - Mixes a White Russian, pouring in milk till full 64 | 65 | Invoke with -help to get help for each command. 66 | 67 | Exit code: -1 68 | 69 | and then, if you add `-help white-russian` as an argument, you'll get detailed help for that command: 70 | 71 | C:\> beverage.exe -help white-russian 72 | 73 | ------------------------------ 74 | Beverage Utility 75 | 76 | Copyright (c) 2015 El Duderino 77 | ------------------------------ 78 | Mixes a White Russian, pouring in milk till full 79 | 80 | Type 81 | 82 | Beverage.exe white-russian 83 | 84 | where can consist of the following parameters: 85 | 86 | -vodka 87 | How many cl of vodka? 88 | 89 | -kahlua 90 | How many cl of Kahlua? 91 | 92 | -lukewarm (flag/optional) 93 | Avoid refrigerated ingredients? 94 | 95 | If you try to invoke a command, and one or more of the arguments are missing, you'll know: 96 | 97 | C:\> beverage white-russian -vodka 1 98 | 99 | ------------------------------ 100 | Beverage Utility 101 | 102 | Copyright (c) 2015 El Duderino 103 | ------------------------------ 104 | The following required parameters are missing: 105 | 106 | -kahlua - How many cl of Kahlua? 107 | 108 | Invoke with -help to get help for each command. 109 | 110 | Exit code: -1 111 | 112 | and then, when you finally invoke the command with the right arguments, it'll run as you would probably expect: 113 | 114 | C:\> beverage white-russian -vodka 2 -kahlua 2 115 | 116 | ------------------------------ 117 | Beverage Utility 118 | 119 | Copyright (c) 2015 El Duderino 120 | ------------------------------ 121 | Making a beverage with 2 cl of vodka and 2 cl of Kahlua 122 | 123 | Neat. 124 | 125 | License 126 | ==== 127 | 128 | GoCommando is [Beer-ware][1]. 129 | 130 | [1]: http://en.wikipedia.org/wiki/Beerware 131 | [2]: http://twitter.com/mookid8000 132 | -------------------------------------------------------------------------------- /TestApp2_old/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /TestApp2_old/ElCommandante.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GoCommando; 3 | 4 | namespace TestApp2 5 | { 6 | [Command("el-commandante")] 7 | public class ElCommandante : ICommand 8 | { 9 | public ElCommandante(string text) 10 | { 11 | Text = text; 12 | } 13 | 14 | public string Text { get; } 15 | 16 | public void Run() 17 | { 18 | Console.WriteLine($"hoy!: {Text}"); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /TestApp2_old/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GoCommando; 3 | 4 | namespace TestApp2 5 | { 6 | class Program 7 | { 8 | static void Main() 9 | { 10 | Go.Run(); 11 | } 12 | } 13 | 14 | class CustomFactory : ICommandFactory 15 | { 16 | public ICommand Create(Type commandType) 17 | { 18 | if (commandType == typeof(ElCommandante)) 19 | { 20 | return new ElCommandante("che!"); 21 | } 22 | 23 | throw new ArgumentException($"Unknown command type: {commandType}"); 24 | } 25 | 26 | public void Release(ICommand command) 27 | { 28 | Console.WriteLine($"imonna let you go: {command}"); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /TestApp2_old/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestApp2")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestApp2")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("07010b53-b1cb-4696-8bb4-dca2943b6b59")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /TestApp2_old/TestApp2.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {07010B53-B1CB-4696-8BB4-DCA2943B6B59} 8 | Exe 9 | Properties 10 | TestApp2 11 | TestApp2 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 60 | -------------------------------------------------------------------------------- /TestApp_old/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /TestApp_old/Commands/NewCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GoCommando; 3 | 4 | namespace TestApp.Commands 5 | { 6 | [Command("new")] 7 | [Description("Does something new")] 8 | public class NewCommand : ICommand 9 | { 10 | [Parameter("qid")] 11 | public string QueryId { get; set; } 12 | 13 | public void Run() 14 | { 15 | Console.WriteLine($"QueryId {QueryId}"); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /TestApp_old/Commands/RunCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GoCommando; 3 | 4 | namespace TestApp.Commands 5 | { 6 | [Command("run")] 7 | [Description("Runs the program")] 8 | public class RunCommand : ICommand 9 | { 10 | [Description("Specifies the path with which stuff is to be done")] 11 | [Parameter("path", shortName: "p")] 12 | [Example(@"c:\temp\somefile.json")] 13 | public string Path { get; set; } 14 | 15 | [Parameter("dir")] 16 | [Example(@"C:\temp")] 17 | [Example(@"C:\windows\microsoft.net")] 18 | [Example(@"C:\windows\system32")] 19 | public string Dir { get; set; } 20 | 21 | [Parameter("flag")] 22 | public bool Flag { get; set; } 23 | 24 | [Parameter("moreflag", shortName: "m")] 25 | public bool MoreFlag { get; set; } 26 | 27 | [Parameter("optionalFlag", optional: true)] 28 | public bool OptionalFlag { get; set; } 29 | 30 | public void Run() 31 | { 32 | Console.WriteLine($@"Running! 33 | 34 | Path: {Path} 35 | Dir: {Dir} 36 | Flag: {Flag} 37 | MFlag: {MoreFlag}, 38 | OFlag: {OptionalFlag}"); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /TestApp_old/Commands/StopCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GoCommando; 3 | 4 | namespace TestApp.Commands 5 | { 6 | [Command("stop")] 7 | public class StopCommand : ICommand 8 | { 9 | [Parameter("bimse", defaultValue: "default_value")] 10 | public string Bimse { get; set; } 11 | 12 | public void Run() 13 | { 14 | Console.WriteLine("BIMSE: {0}", Bimse); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /TestApp_old/Commands/TestAppConfigBinding.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GoCommando; 3 | 4 | namespace TestApp.Commands 5 | { 6 | [Command("appconfig")] 7 | public class TestAppConfigBinding : ICommand 8 | { 9 | [Parameter("appSettingsKey", allowAppSetting: true)] 10 | [Description("Demonstrates how an appSetting can be automatically bound")] 11 | public string AppSetting { get; set; } 12 | 13 | [Parameter("connectionStringsName", allowConnectionString: true)] 14 | [Description("Demonstrates how a connectionString can be automatically bound")] 15 | public string ConnectionString { get; set; } 16 | 17 | [Parameter("windir", allowEnvironmentVariable: true)] 18 | [Description("Demonstrates how an environment variable can be automatically bound")] 19 | public string EnvironmentVariable { get; set; } 20 | 21 | public void Run() 22 | { 23 | Console.WriteLine($@"AppSetting: {AppSetting} 24 | 25 | ConnectionString: {ConnectionString} 26 | 27 | EnvironmentVariable: {EnvironmentVariable}"); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /TestApp_old/Program.cs: -------------------------------------------------------------------------------- 1 | using GoCommando; 2 | 3 | namespace TestApp 4 | { 5 | [Banner(@"------------------------ 6 | Welcome to GoCommando v2 7 | ------------------------")] 8 | class Program 9 | { 10 | static void Main() 11 | { 12 | Go.Run(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /TestApp_old/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TestApp")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestApp")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("1dc7365e-e01d-477a-82f7-2bc5efc51640")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /TestApp_old/TestApp.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {1DC7365E-E01D-477A-82F7-2BC5EFC51640} 8 | Exe 9 | Properties 10 | TestApp 11 | TestApp 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 64 | -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | echo GoCommand build thing. 4 | echo. 5 | 6 | set buildVersion=%1 7 | 8 | set outputPath="%~dp0\deploy" 9 | 10 | if exist "%outputPath%" ( 11 | rd "%outputPath%" /s/q 12 | ) 13 | 14 | mkdir "%outputPath%" 15 | 16 | if "%buildVersion%"=="" ( 17 | echo. 18 | echo Please specify which version to build as an argument 19 | echo. 20 | goto exit 21 | ) 22 | 23 | echo Building version %buildVersion%... 24 | 25 | msbuild GoCommando\GoCommando.csproj -P:Configuration=Release 26 | 27 | echo Tagging... 28 | 29 | git tag %buildVersion% 30 | 31 | echo Packing... 32 | 33 | nuget\nuget pack Package.nuspec -out %outputPath% -version %buildVersion% 34 | 35 | echo Pushing... 36 | 37 | git push 38 | git push --tags 39 | 40 | :exit 41 | -------------------------------------------------------------------------------- /nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rebus-org/GoCommando/e56e6f896f0794a6072756d358d7aeea493563d4/nuget/NuGet.exe -------------------------------------------------------------------------------- /old/.gitignore: -------------------------------------------------------------------------------- 1 | obj 2 | bin 3 | deploy 4 | deploy/* 5 | _ReSharper.* 6 | *.csproj.user 7 | *.resharper.user 8 | *.resharper 9 | *.suo 10 | *.cache 11 | ~$* -------------------------------------------------------------------------------- /old/Package.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | GoCommando 5 | 0.2 6 | Mogens Heller Grabe 7 | Mogens Heller Grabe 8 | http://en.wikipedia.org/wiki/Beerware 9 | http://mookid.dk/oncode/gocommando 10 | GoCommando is a small command line utility helper that does the boring work when creating command line utilities in .NET. 11 | Copyright 2011 12 | command-line 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /old/README.md: -------------------------------------------------------------------------------- 1 | What? 2 | ==== 3 | 4 | GoCommando is a small command line utility helper that does the boring work when creating command line utilities in .NET. 5 | 6 | More info coming soon at http://mookid.dk/oncode/gocommando 7 | 8 | One day, maybe I'll tweet something as well... [@mookid8000][2] 9 | 10 | How? 11 | ==== 12 | 13 | Create a new console application. `Install-Package GoCommando` to get the DLL, and then `Go.Run(args)` in the `Main` method. 14 | 15 | License 16 | ==== 17 | 18 | GoCommando is [Beer-ware][1]. 19 | 20 | [1]: http://en.wikipedia.org/wiki/Beerware 21 | [2]: http://twitter.com/#!/mookid8000 -------------------------------------------------------------------------------- /old/build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | msbuild scripts\build.proj -------------------------------------------------------------------------------- /old/lib/nunit/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rebus-org/GoCommando/e56e6f896f0794a6072756d358d7aeea493563d4/old/lib/nunit/nunit.framework.dll -------------------------------------------------------------------------------- /old/lib/rhino/Rhino.Mocks.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rebus-org/GoCommando/e56e6f896f0794a6072756d358d7aeea493563d4/old/lib/rhino/Rhino.Mocks.dll -------------------------------------------------------------------------------- /old/scripts/build.proj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ..\deploy 8 | ..\tools 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /old/src/GoCommando.ConsoleApplication/GoCommando.ConsoleApplication.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {8F0347E7-51AF-42F8-A259-F5DE19C6D858} 9 | Exe 10 | Properties 11 | GoCommando.ConsoleApplication 12 | GoCommando.ConsoleApplication 13 | v3.5 14 | 512 15 | 16 | 17 | 3.5 18 | 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | 3.5 41 | 42 | 43 | 3.5 44 | 45 | 46 | 3.5 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {83A32DB4-90CF-4707-9463-2E0589F80EFD} 58 | GoCommando 59 | 60 | 61 | 62 | 69 | -------------------------------------------------------------------------------- /old/src/GoCommando.ConsoleApplication/Program.cs: -------------------------------------------------------------------------------- 1 | using GoCommando.Api; 2 | using GoCommando.Attributes; 3 | 4 | namespace GoCommando.ConsoleApplication 5 | { 6 | [Banner(@"This is a sample command line app 7 | 8 | (c) Some Dude 2010")] 9 | class Program : ICommando 10 | { 11 | [PositionalArgument] 12 | [Description("The path to the file you wish to do stuff to")] 13 | [Example("c:\\temp\\somefile.txt")] 14 | [Example("c:\\temp\\anotherfile.txt")] 15 | public string Path { get; set; } 16 | 17 | [PositionalArgument] 18 | [Description("The value of something")] 19 | [Example("59")] 20 | public double Value { get; set; } 21 | 22 | [NamedArgument("someflag", "sf")] 23 | [Description("Extra-special flag")] 24 | public bool SomeFlag { get; set; } 25 | 26 | [NamedArgument("anotherflag", "af")] 27 | [Description("Pretty important flag")] 28 | public bool AnotherFlag { get; set; } 29 | 30 | [NamedArgument("someValue", "sv")] 31 | [Description("An integer value specifying something important")] 32 | [Example("1"), Example("2"), Example("3")] 33 | public int SomeValue { get; set; } 34 | 35 | [NamedArgument("anotherValue", "av")] 36 | public string AnotherValue { get; set; } 37 | 38 | static void Main(string[] args) 39 | { 40 | Go.Run(args); 41 | } 42 | 43 | public void Run() 44 | { 45 | // Console.WriteLine(@"Path: {0} (expected: c:\program files\somepath\somefile.txt) 46 | //Value: {1} (expected 34.67) 47 | //Some flag: {2} (expected True) 48 | //Some value: {3} (expected 23)) 49 | //Another value: {4} (expected bim) 50 | //Another flag: {5} (expected False)", 51 | // Path, 52 | // Value, 53 | // SomeFlag, 54 | // SomeValue, 55 | // AnotherValue, 56 | // AnotherFlag); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /old/src/GoCommando.ConsoleApplication/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("GoCommando.ConsoleApplication")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("GoCommando.ConsoleApplication")] 12 | [assembly: AssemblyCopyright("Copyright © 2010")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("298263a2-6fac-4412-a9a8-c4d20d06cc4e")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /old/src/GoCommando.Tests/FixtureBase.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | 3 | namespace GoCommando.Tests 4 | { 5 | public abstract class FixtureBase 6 | { 7 | [SetUp] 8 | public void SetUp() 9 | { 10 | DoSetUp(); 11 | } 12 | 13 | protected virtual void DoSetUp() 14 | { 15 | } 16 | 17 | [TearDown] 18 | public void TearDown() 19 | { 20 | DoTearDown(); 21 | } 22 | 23 | protected virtual void DoTearDown() 24 | { 25 | } 26 | 27 | [TestFixtureSetUp] 28 | public void TestFixtureSetUp() 29 | { 30 | DoTestFixtureSetUp(); 31 | } 32 | 33 | protected virtual void DoTestFixtureSetUp() 34 | { 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /old/src/GoCommando.Tests/GoCommando.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {12BCC57F-5D0B-496E-B47A-BD2A85190D48} 9 | Library 10 | Properties 11 | GoCommando.Tests 12 | GoCommando.Tests 13 | v3.5 14 | 512 15 | 16 | 17 | 3.5 18 | 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | False 40 | ..\..\lib\nunit\nunit.framework.dll 41 | 42 | 43 | 44 | 3.5 45 | 46 | 47 | 3.5 48 | 49 | 50 | 3.5 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | {83A32DB4-90CF-4707-9463-2E0589F80EFD} 66 | GoCommando 67 | 68 | 69 | 70 | 71 | 72 | 73 | 80 | -------------------------------------------------------------------------------- /old/src/GoCommando.Tests/Helpers/TestArgParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Timers; 4 | using GoCommando.Helpers; 5 | using GoCommando.Parameters; 6 | using NUnit.Framework; 7 | 8 | namespace GoCommando.Tests.Helpers 9 | { 10 | [TestFixture] 11 | public class TestArgParser : FixtureBase 12 | { 13 | ArgParser parser; 14 | 15 | protected override void DoSetUp() 16 | { 17 | parser = new ArgParser(); 18 | } 19 | 20 | [Test] 21 | public void CanParseParameterWithAbsolutePath() 22 | { 23 | var parameter = parser.Parse(new[]{"-path:c:\\temp\\someFile.txt"}) 24 | .Cast().Single(); 25 | 26 | Assert.AreEqual("path", parameter.Name); 27 | Assert.AreEqual("c:\\temp\\someFile.txt", parameter.Value); 28 | } 29 | 30 | [Test] 31 | public void IndexIsOneBased() 32 | { 33 | var parameters = parser.Parse(new[]{"firstArg", "secondArg"}) 34 | .Cast().ToList(); 35 | 36 | Assert.AreEqual(1, parameters[0].Index); 37 | Assert.AreEqual(2, parameters[1].Index); 38 | } 39 | 40 | [Test] 41 | public void EmptyArrayYieldsNoArguments() 42 | { 43 | var timer = new Timer(); 44 | timer.Elapsed += (_, __) => Console.WriteLine("hej"); 45 | timer.Start(); 46 | 47 | var args1 = new string[0]; 48 | var args2 = new[]{"", " ", ""}; 49 | AssertYieldsNoParameters(args1); 50 | AssertYieldsNoParameters(args2); 51 | } 52 | 53 | [Test] 54 | public void DoesNotThrowIfItsAFlag() 55 | { 56 | var parameter = parser.Parse(new[]{"-param"}).Cast().Single(); 57 | Assert.AreEqual("param", parameter.Name); 58 | Assert.AreEqual("True", parameter.Value); 59 | } 60 | 61 | [Test] 62 | public void CanParseArrayOfArguments() 63 | { 64 | var args = new []{"some.assembly", "another.assembly", "-param2:bimmelim", "-param1:boom"}; 65 | var parameters = parser.Parse(args); 66 | 67 | Assert.AreEqual(4, parameters.Count); 68 | 69 | var p1 = parameters[0]; 70 | var p2 = parameters[1]; 71 | var p3 = parameters[2]; 72 | var p4 = parameters[3]; 73 | Assert.AreEqual("some.assembly", p1.Value); 74 | Assert.AreEqual("another.assembly", p2.Value); 75 | Assert.AreEqual("bimmelim", p3.Value); 76 | Assert.AreEqual("boom", p4.Value); 77 | } 78 | 79 | [Test] 80 | public void ThrowsIfPositionalParametersAreMixedWithNamedParameters() 81 | { 82 | Assert.Throws(() => parser.Parse(new[] {"-named:parameter", "positional.parameter"})); 83 | Assert.Throws(() => parser.Parse(new[] {"-named.flag", "positional.parameter"})); 84 | } 85 | 86 | [Test] 87 | public void AcceptsSlashAsPositionalParameter() 88 | { 89 | var args = new []{"/src/somepath", "/src/anotherpath"}; 90 | var parameters = parser.Parse(args); 91 | 92 | Assert.AreEqual(2, parameters.Count); 93 | Assert.IsTrue(parameters[0] is PositionalCommandLineParameter); 94 | Assert.IsTrue(parameters[1] is PositionalCommandLineParameter); 95 | } 96 | 97 | void AssertYieldsNoParameters(string[] args) 98 | { 99 | var parameters = parser.Parse(args); 100 | var argsAsString = string.Join(", ", args.Select(s => string.Format(@"""{0}""", s)).ToArray()); 101 | 102 | Assert.AreEqual(0, parameters.Count, "Expected 0 parameters yielded from parsing {0}", 103 | argsAsString); 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /old/src/GoCommando.Tests/Helpers/TestBinder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using GoCommando.Attributes; 4 | using GoCommando.Helpers; 5 | using GoCommando.Parameters; 6 | using NUnit.Framework; 7 | 8 | namespace GoCommando.Tests.Helpers 9 | { 10 | [TestFixture] 11 | public class TestBinder : FixtureBase 12 | { 13 | Binder binder; 14 | 15 | protected override void DoSetUp() 16 | { 17 | binder = new Binder(); 18 | } 19 | 20 | [Test] 21 | public void UsesDefaultIfSpecified() 22 | { 23 | var target = new HasDefaultParameters(); 24 | 25 | binder.Bind(target, ListWith()); 26 | 27 | Assert.AreEqual("hello!", target.Something1); 28 | Assert.IsNull(target.Something2); 29 | } 30 | 31 | class HasDefaultParameters 32 | { 33 | [NamedArgument("something1", "s1", Default = "hello!")] 34 | public string Something1 { get; set; } 35 | 36 | [NamedArgument("something2", "s2")] 37 | public string Something2 { get; set; } 38 | } 39 | 40 | [Test] 41 | public void GeneratesReportOfUnboundParameters() 42 | { 43 | var target = new HasProperties(); 44 | 45 | var report = binder.Bind(target, ListWith()); 46 | 47 | Assert.AreEqual(4, report.PropertiesNotBound.Count); 48 | Assert.AreEqual(0, report.PropertiesBound.Count); 49 | } 50 | 51 | [Test] 52 | public void GeneratesReportOfBoundParameters() 53 | { 54 | var target = new HasProperties(); 55 | 56 | var report = binder.Bind(target, ListWith(PositionalParameter(1, "1"), 57 | PositionalParameter(2, "2"), 58 | NamedParameter("bim1", "3"), 59 | NamedParameter("bim2", "4"))); 60 | 61 | Assert.AreEqual(0, report.PropertiesNotBound.Count); 62 | Assert.AreEqual(4, report.PropertiesBound.Count); 63 | } 64 | 65 | [Test] 66 | public void CanBindSimpleIntegerParameter() 67 | { 68 | var target = new HasPrimitiveTypes(); 69 | 70 | binder.Bind(target, ListWith(NamedParameter("int", "23"))); 71 | 72 | Assert.AreEqual(23, target.IntValue); 73 | } 74 | 75 | [Test] 76 | public void CanBindSimpleStringParameter() 77 | { 78 | var target = new HasPrimitiveTypes(); 79 | 80 | binder.Bind(target, ListWith(NamedParameter("string", "yo!"))); 81 | 82 | Assert.AreEqual("yo!", target.StringValue); 83 | } 84 | 85 | [Test] 86 | public void CanBindSimpleDoubleParameter() 87 | { 88 | var target = new HasPrimitiveTypes(); 89 | 90 | binder.Bind(target, ListWith(NamedParameter("double", "23,5"))); 91 | 92 | Assert.AreEqual(23.5, target.DoubleValue); 93 | } 94 | 95 | class HasProperties 96 | { 97 | [PositionalArgument] 98 | public string Arg1 { get; set; } 99 | 100 | [PositionalArgument] 101 | public string Arg2 { get; set; } 102 | 103 | [NamedArgument("bim1", "b1")] 104 | public string Arg3 { get; set; } 105 | 106 | [NamedArgument("bim2", "b2")] 107 | public string Arg4 { get; set; } 108 | } 109 | 110 | class HasPrimitiveTypes 111 | { 112 | [NamedArgument("int", "i")] 113 | public int IntValue { get; set; } 114 | 115 | [NamedArgument("double", "d")] 116 | public double DoubleValue { get; set; } 117 | 118 | [NamedArgument("string", "s")] 119 | public string StringValue { get; set; } 120 | } 121 | 122 | IEnumerable ListWith(params CommandLineParameter[] parameters) 123 | { 124 | return parameters.ToList(); 125 | } 126 | 127 | CommandLineParameter NamedParameter(string name, string value) 128 | { 129 | return new NamedCommandLineParameter(name, value); 130 | } 131 | 132 | CommandLineParameter PositionalParameter(int index, string value) 133 | { 134 | return new PositionalCommandLineParameter(index, value); 135 | } 136 | } 137 | } -------------------------------------------------------------------------------- /old/src/GoCommando.Tests/Helpers/TestHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using GoCommando.Attributes; 4 | using GoCommando.Helpers; 5 | using NUnit.Framework; 6 | namespace GoCommando.Tests.Helpers 7 | { 8 | [TestFixture] 9 | public class TestHelper : FixtureBase 10 | { 11 | Helper helper; 12 | 13 | protected override void DoSetUp() 14 | { 15 | helper = new Helper(); 16 | } 17 | 18 | [Test] 19 | public void CanRepresentParametersAndDescriptionsAsExpected() 20 | { 21 | var parameters = helper.GetParameters(new SomeClass()); 22 | 23 | AssertPositionalParameter(parameters[0], "hello there!", 1, "FirstPositional", "ex1", "ex2"); 24 | AssertPositionalParameter(parameters[1], "hello there!", 2, "SecondPositional", "yet another lengthy example"); 25 | AssertNamedParameter(parameters[2], "hello again! there!", "AnotherString", "name", "nm"); 26 | } 27 | 28 | void AssertPositionalParameter(Parameter parameter, string expectedDescription, int expectedPosition, string expectedPropertyName, params string[] expectedExamples) 29 | { 30 | AssertParameter(expectedDescription, parameter, expectedPropertyName); 31 | Assert.AreEqual(expectedPosition, parameter.Position); 32 | Assert.IsTrue(parameter.ArgumentAttribute is PositionalArgumentAttribute, "Expected PositionalArgumentAttribute, was {0}", parameter.ArgumentAttribute.GetType().Name); 33 | AssertExamples(parameter, expectedExamples); 34 | } 35 | 36 | void AssertNamedParameter(Parameter parameter, string expectedDescription, string expectedPropertyName, string expectedArgumentName, string expectedArgumentShorthand, params string[] expectedExamples) 37 | { 38 | AssertParameter(expectedDescription, parameter, expectedPropertyName); 39 | Assert.IsTrue(parameter.ArgumentAttribute is NamedArgumentAttribute, "Expected NamedArgumentAttribute, was {0}", parameter.ArgumentAttribute.GetType().Name); 40 | Assert.AreEqual(expectedArgumentName, ((NamedArgumentAttribute)parameter.ArgumentAttribute).Name); 41 | Assert.AreEqual(expectedArgumentShorthand, ((NamedArgumentAttribute) parameter.ArgumentAttribute).ShortHand); 42 | AssertExamples(parameter, expectedExamples); 43 | } 44 | 45 | void AssertExamples(Parameter parameter, IEnumerable examples) 46 | { 47 | Assert.IsTrue(parameter.Examples.OrderBy(e => e.Text).Select(e => e.Text).SequenceEqual(examples.OrderBy(s => s))); 48 | } 49 | 50 | void AssertParameter(string expectedDescription, Parameter para, string expectedPropertyName) 51 | { 52 | Assert.AreEqual(expectedDescription, para.Description); 53 | Assert.AreEqual(expectedPropertyName, para.PropertyInfo.Name); 54 | } 55 | 56 | class SomeClass 57 | { 58 | public string ShouldNotBeIncluded { get; set; } 59 | 60 | [PositionalArgument] 61 | [Attributes.Description("hello there!")] 62 | [Example("ex1")] 63 | [Example("ex2")] 64 | public string FirstPositional { get; set; } 65 | 66 | [PositionalArgument] 67 | [Attributes.Description("hello there!")] 68 | [Example("yet another lengthy example")] 69 | public string SecondPositional { get; set; } 70 | 71 | [NamedArgument("name", "nm")] 72 | [Attributes.Description("hello again! there!")] 73 | public string AnotherString { get; set; } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /old/src/GoCommando.Tests/Integration/ErrorTestCases.cs: -------------------------------------------------------------------------------- 1 | using GoCommando.Api; 2 | using GoCommando.Attributes; 3 | using NUnit.Framework; 4 | using DescriptionAttribute = NUnit.Framework.DescriptionAttribute; 5 | 6 | namespace GoCommando.Tests.Integration 7 | { 8 | [TestFixture] 9 | public class ErrorTestCases 10 | { 11 | [SetUp] 12 | public void SetUp() 13 | { 14 | CommandoWithTwoArguments.SomePathStatic = null; 15 | CommandoWithTwoArguments.AnotherPathStatic = null; 16 | } 17 | 18 | [Test, Description("This error was due to named argument syntax using slash, thus resulting in arguments with forward slash (e.g. an URL) being interpreted as such")] 19 | public void ReproduceError() 20 | { 21 | var errorCode = Go.Run(new[] {"/src/somepath", "/src/anotherpath"}); 22 | 23 | Assert.AreEqual(0, errorCode); 24 | Assert.AreEqual("/src/somepath", CommandoWithTwoArguments.SomePathStatic); 25 | Assert.AreEqual("/src/anotherpath", CommandoWithTwoArguments.AnotherPathStatic); 26 | } 27 | 28 | class CommandoWithTwoArguments : ICommando 29 | { 30 | [PositionalArgument] 31 | public string SomePath { get; set; } 32 | 33 | [PositionalArgument] 34 | public string AnotherPath { get; set; } 35 | 36 | public void Run() 37 | { 38 | SomePathStatic = SomePath; 39 | AnotherPathStatic = AnotherPath; 40 | } 41 | 42 | public static string SomePathStatic { get; set; } 43 | public static string AnotherPathStatic { get; set; } 44 | } 45 | 46 | [Test, Description("This was the actual parameters resulting in an error")] 47 | public void HowAboutThis() 48 | { 49 | var errorCode = Go.Run(new[] 50 | { 51 | @"src\Noder.Test\bin\Debug\Noder.Test.dll", 52 | @"src\Noder.Test\Features\00_basics.feature" 53 | }); 54 | 55 | Assert.AreEqual(0, errorCode); 56 | Assert.AreEqual(@"src\Noder.Test\bin\Debug\Noder.Test.dll", CommandoWithThreeArguments.SomePathStatic); 57 | Assert.AreEqual(@"src\Noder.Test\Features\00_basics.feature", CommandoWithThreeArguments.AnotherPathStatic); 58 | Assert.IsFalse(CommandoWithThreeArguments.SomeFlagStatic); 59 | } 60 | 61 | class CommandoWithThreeArguments : ICommando 62 | { 63 | [PositionalArgument] 64 | public string SomePath { get; set; } 65 | 66 | [PositionalArgument] 67 | public string AnotherPath { get; set; } 68 | 69 | [NamedArgument("flag", "f")] 70 | public bool SomeFlag { get; set; } 71 | 72 | public void Run() 73 | { 74 | SomePathStatic = SomePath; 75 | AnotherPathStatic = AnotherPath; 76 | SomeFlagStatic = SomeFlag; 77 | } 78 | 79 | public static string SomePathStatic { get; set; } 80 | public static string AnotherPathStatic { get; set; } 81 | public static bool SomeFlagStatic { get; set; } 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /old/src/GoCommando.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("GoCommando.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("GoCommando.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2010")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d5030759-2ba3-411f-98c7-e5d85395a2a2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /old/src/GoCommando.Tests/todo.txt: -------------------------------------------------------------------------------- 1 | * add ability to specify and bind default values for named arguments 2 | * add ability to run user-supplied instance of ICommando 3 | -------------------------------------------------------------------------------- /old/src/GoCommando.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{3903DEE6-D83F-4328-B15D-129FA4658AA9}" 5 | ProjectSection(SolutionItems) = preProject 6 | ..\build.bat = ..\build.bat 7 | ..\scripts\build.proj = ..\scripts\build.proj 8 | GoCommando\GoCommando.nuspec = GoCommando\GoCommando.nuspec 9 | ..\README = ..\README 10 | EndProjectSection 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GoCommando", "GoCommando\GoCommando.csproj", "{83A32DB4-90CF-4707-9463-2E0589F80EFD}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GoCommando.Tests", "GoCommando.Tests\GoCommando.Tests.csproj", "{12BCC57F-5D0B-496E-B47A-BD2A85190D48}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GoCommando.ConsoleApplication", "GoCommando.ConsoleApplication\GoCommando.ConsoleApplication.csproj", "{8F0347E7-51AF-42F8-A259-F5DE19C6D858}" 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Any CPU = Debug|Any CPU 21 | Release|Any CPU = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {83A32DB4-90CF-4707-9463-2E0589F80EFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {83A32DB4-90CF-4707-9463-2E0589F80EFD}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {83A32DB4-90CF-4707-9463-2E0589F80EFD}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {83A32DB4-90CF-4707-9463-2E0589F80EFD}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {12BCC57F-5D0B-496E-B47A-BD2A85190D48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {12BCC57F-5D0B-496E-B47A-BD2A85190D48}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {12BCC57F-5D0B-496E-B47A-BD2A85190D48}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {12BCC57F-5D0B-496E-B47A-BD2A85190D48}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {8F0347E7-51AF-42F8-A259-F5DE19C6D858}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {8F0347E7-51AF-42F8-A259-F5DE19C6D858}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {8F0347E7-51AF-42F8-A259-F5DE19C6D858}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {8F0347E7-51AF-42F8-A259-F5DE19C6D858}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /old/src/GoCommando/Api/ICommando.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando.Api 2 | { 3 | public interface ICommando 4 | { 5 | void Run(); 6 | } 7 | } -------------------------------------------------------------------------------- /old/src/GoCommando/ArgumentAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | public abstract class ArgumentAttribute : Attribute 6 | { 7 | public bool Required { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Attributes/ArgumentAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando.Attributes 4 | { 5 | public abstract class ArgumentAttribute : Attribute 6 | { 7 | public bool Required { get; protected set; } 8 | } 9 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Attributes/BannerAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando.Attributes 4 | { 5 | [AttributeUsage(AttributeTargets.Class)] 6 | public class BannerAttribute : Attribute 7 | { 8 | public string Text { get; set; } 9 | 10 | public BannerAttribute(string text) 11 | { 12 | Text = text; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Attributes/DescriptionAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando.Attributes 4 | { 5 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 6 | public class DescriptionAttribute : Attribute 7 | { 8 | readonly string text; 9 | 10 | public DescriptionAttribute(string text) 11 | { 12 | this.text = text; 13 | } 14 | 15 | public string Text 16 | { 17 | get { return text; } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Attributes/ExampleAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando.Attributes 4 | { 5 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)] 6 | public class ExampleAttribute : Attribute 7 | { 8 | readonly string text; 9 | 10 | public ExampleAttribute(string text) 11 | { 12 | this.text = text; 13 | } 14 | 15 | public string Text 16 | { 17 | get { return text; } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Attributes/NamedArgumentAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando.Attributes 4 | { 5 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 6 | public class NamedArgumentAttribute : ArgumentAttribute 7 | { 8 | public string Name { get; private set; } 9 | public string ShortHand { get; private set; } 10 | public string Default { get; set; } 11 | 12 | public NamedArgumentAttribute(string name, string shortHand) 13 | { 14 | Name = name; 15 | ShortHand = shortHand; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Attributes/PositionalArgumentAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando.Attributes 4 | { 5 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 6 | public class PositionalArgumentAttribute : ArgumentAttribute 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /old/src/GoCommando/BannerAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | [AttributeUsage(AttributeTargets.Class)] 6 | public class BannerAttribute : Attribute 7 | { 8 | public string Text { get; set; } 9 | 10 | public BannerAttribute(string text) 11 | { 12 | Text = text; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /old/src/GoCommando/CommandLineParameter.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando 2 | { 3 | public abstract class CommandLineParameter 4 | { 5 | protected CommandLineParameter(string value) 6 | { 7 | Value = value; 8 | } 9 | 10 | public string Value { get; private set; } 11 | } 12 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Exceptions/CommandoException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando.Exceptions 4 | { 5 | public class CommandoException : ApplicationException 6 | { 7 | public CommandoException(string message, params object[] objs) 8 | : base(string.Format(message, objs)) 9 | { 10 | } 11 | 12 | public CommandoException(Exception innerException, string message, params object[] objs) 13 | : base(string.Format(message, objs), innerException) 14 | { 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Extensions/AttributeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | namespace GoCommando.Extensions 7 | { 8 | public static class AttributeExtensions 9 | { 10 | public static void WithAttributes(this ICustomAttributeProvider customAttributeProvider, Action handleAttribute) 11 | { 12 | GetAttributes(customAttributeProvider) 13 | .ToList() 14 | .ForEach(handleAttribute); 15 | } 16 | 17 | public static IList GetAttributes(this ICustomAttributeProvider customAttributeProvider) 18 | { 19 | return customAttributeProvider.GetCustomAttributes(typeof (TAttribute), false) 20 | .Cast() 21 | .ToList(); 22 | } 23 | 24 | public static bool HasAttribute(this ICustomAttributeProvider customAttributeProvider) 25 | { 26 | return GetAttributes(customAttributeProvider).Any(); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Go.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using GoCommando.Api; 6 | using GoCommando.Attributes; 7 | using GoCommando.Exceptions; 8 | using GoCommando.Extensions; 9 | using GoCommando.Helpers; 10 | using GoCommando.Parameters; 11 | using Binder = GoCommando.Helpers.Binder; 12 | 13 | namespace GoCommando 14 | { 15 | public static class Go 16 | { 17 | /// 18 | /// Runs the specified type, GoCommando style. What this means is that: 19 | /// * if type is decorated with [Banner(...)], that banner will be output 20 | /// * args will be bound to public properties decorated with [PositionalArgument] and [NamedArgument] 21 | /// * validation (if any) will be run 22 | /// * help text will be shown where appropriate 23 | /// 24 | /// GoCommando will use the default -powered way of creating 25 | /// the instance when it is needed. 26 | /// 27 | public static int Run(string[] args) where TCommando : ICommando 28 | { 29 | Func defaultCommandoFactoryMethod = 30 | () => (TCommando) Activator.CreateInstance(typeof (TCommando)); 31 | 32 | return Run(args, defaultCommandoFactoryMethod); 33 | } 34 | 35 | /// 36 | /// Runs the specified type, GoCommando style. What this means is that: 37 | /// * if type is decorated with [Banner(...)], that banner will be output 38 | /// * args will be bound to public properties decorated with [PositionalArgument] and [NamedArgument] 39 | /// * validation (if any) will be run 40 | /// * help text will be shown where appropriate 41 | /// 42 | /// The specified factory method will be used to obtain the instance 43 | /// when it is needed. 44 | /// 45 | public static int Run(string[] args, Func factoryMethod) where TCommando : ICommando 46 | { 47 | try 48 | { 49 | var instance = factoryMethod(); 50 | 51 | PossiblyShowBanner(instance); 52 | 53 | if (ShouldShowHelpText(args)) 54 | { 55 | ShowHelpText(instance); 56 | return 0; 57 | } 58 | 59 | var parameters = GetParameters(args); 60 | 61 | var bindingReport = PopulateProperties(parameters, instance); 62 | 63 | if (RequiredParameterMissing(bindingReport)) 64 | { 65 | ShowMissingParameters(bindingReport); 66 | 67 | return 1; 68 | } 69 | 70 | Execute(instance); 71 | 72 | return 0; 73 | } 74 | catch (CommandoException e) 75 | { 76 | Write(e.Message); 77 | 78 | WriteHelpInstructions(); 79 | 80 | return 2; 81 | } 82 | catch (Exception e) 83 | { 84 | Write(e.ToString()); 85 | 86 | return 1; 87 | } 88 | } 89 | 90 | static void ShowMissingParameters(BindingReport report) 91 | { 92 | Write("One or more required arguments are missing!"); 93 | Write(); 94 | 95 | var context = new BindingContext(); 96 | 97 | foreach (var parameter in report.PropertiesNotBound.Select(p => new Parameter(p, context)).Where(p => p.Position > 0)) 98 | { 99 | WritePositionalParameter(parameter, ExampleOutputSettings.DontShowExamples); 100 | } 101 | 102 | WriteHelpInstructions(); 103 | } 104 | 105 | static void WriteHelpInstructions() 106 | { 107 | Write(); 108 | Write("Invoke with -? for detailed help."); 109 | } 110 | 111 | class BindingContext : IHasPositionerCounter 112 | { 113 | public BindingContext() 114 | { 115 | Position = 1; 116 | } 117 | 118 | public int Position { get; set; } 119 | } 120 | 121 | static bool RequiredParameterMissing(BindingReport bindingReport) 122 | { 123 | return bindingReport.RequiredPropertiesNotBound.Any(); 124 | } 125 | 126 | static void ShowHelpText(ICommando commando) 127 | { 128 | var helper = new Helper(); 129 | var parameters = helper.GetParameters(commando); 130 | 131 | var exeName = Assembly.GetEntryAssembly().GetName().Name + ".exe"; 132 | var parameterList = string.Join(" ", parameters.Where(p => p.Position > 0) 133 | .Select(p => string.Format("[{0}]", p.Position)) 134 | .ToArray()); 135 | 136 | var thereAreRequiredArguments = parameters.Any(p => p.Position > 0); 137 | var thereAreOptionalArguments = parameters.Any(p => p.Position == 0); 138 | 139 | Write("Usage:"); 140 | Write(); 141 | Write("\t{0} {1}{2}{3}", 142 | exeName, 143 | parameterList, 144 | parameterList.Length > 0 ? " " : "", 145 | thereAreOptionalArguments ? "[args]" : ""); 146 | 147 | if (thereAreRequiredArguments) 148 | { 149 | Write(); 150 | Write(); 151 | Write("Required arguments:"); 152 | 153 | foreach (var parameter in parameters.Where(p => p.Position > 0)) 154 | { 155 | Write(); 156 | 157 | WritePositionalParameter(parameter, ExampleOutputSettings.ShowExamples); 158 | } 159 | } 160 | 161 | if (thereAreOptionalArguments) 162 | { 163 | Write(); 164 | Write(); 165 | Write("Additional arguments:"); 166 | 167 | foreach (var parameter in parameters.Where(p => p.Position == 0)) 168 | { 169 | Write(); 170 | 171 | Write("\t-{0}\t{1}", parameter.Name, parameter.Description); 172 | 173 | PossibleWriteExamples(parameter); 174 | } 175 | } 176 | } 177 | 178 | enum ExampleOutputSettings 179 | { 180 | ShowExamples, 181 | DontShowExamples, 182 | } 183 | 184 | static void WritePositionalParameter(Parameter parameter, ExampleOutputSettings outputExamples) 185 | { 186 | Write("\t[{0}] {1}", parameter.Position, parameter.Description); 187 | 188 | if (outputExamples == ExampleOutputSettings.ShowExamples) 189 | { 190 | PossibleWriteExamples(parameter); 191 | } 192 | } 193 | 194 | static void PossibleWriteExamples(Parameter parameter) 195 | { 196 | var examples = parameter.Examples; 197 | 198 | if (!examples.Any()) return; 199 | 200 | var headline = examples.Count > 1 ? "Examples" : "Example"; 201 | var maxLength = examples.Max(e => e.Text.Length); 202 | var printExamplesOnMultipleLines = maxLength > 7; 203 | var separator = printExamplesOnMultipleLines ? (Environment.NewLine + "\t\t\t") : ", "; 204 | 205 | Write("\t\t{0}: {1}{2}", 206 | headline, 207 | printExamplesOnMultipleLines ? separator : "", 208 | string.Join(separator, examples.Select(e => e.Text).ToArray())); 209 | } 210 | 211 | static bool ShouldShowHelpText(string[] strings) 212 | { 213 | return strings.Length == 1 214 | && new List {"-h", "--h", "/h", "-?", "/?", "?"}.Contains(strings[0].ToLowerInvariant()); 215 | } 216 | 217 | static void PossiblyShowBanner(object obj) 218 | { 219 | var type = obj.GetType(); 220 | type.WithAttributes(a => ShowBanner(a, type.Assembly)); 221 | Write(); 222 | } 223 | 224 | static void ShowBanner(BannerAttribute attribute, Assembly assembly) 225 | { 226 | Write(attribute.Text.Replace("{assemblyVersion}", assembly.GetName().Version.ToString())); 227 | } 228 | 229 | static void Write() 230 | { 231 | Console.WriteLine(); 232 | } 233 | 234 | static void Write(string text, params object[] objs) 235 | { 236 | Console.WriteLine(text, objs); 237 | } 238 | 239 | static List GetParameters(string[] args) 240 | { 241 | var parser = new ArgParser(); 242 | return parser.Parse(args); 243 | } 244 | 245 | static BindingReport PopulateProperties(IEnumerable parameters, ICommando instance) 246 | { 247 | var binder = new Binder(); 248 | var report = binder.Bind(instance, parameters); 249 | return report; 250 | } 251 | 252 | static void Execute(ICommando instance) 253 | { 254 | instance.Run(); 255 | } 256 | } 257 | } -------------------------------------------------------------------------------- /old/src/GoCommando/GoCommando.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace GoCommando 6 | { 7 | public static class Go 8 | { 9 | public static int Run(string[] args) where TGoCommando : IGoCommando 10 | { 11 | try 12 | { 13 | PossiblyShowBanner(typeof(TGoCommando)); 14 | var instance = (IGoCommando)Activator.CreateInstance(typeof(TGoCommando)); 15 | PopulateInstanceParameters(instance, args); 16 | instance.Run(); 17 | return 0; 18 | } 19 | catch (CommandoException e) 20 | { 21 | Write(e.Message); 22 | 23 | return 2; 24 | } 25 | catch (Exception e) 26 | { 27 | Write(e.ToString()); 28 | 29 | return 1; 30 | } 31 | } 32 | 33 | static void PossiblyShowBanner(Type type) 34 | { 35 | type.WithAttributes(ShowBanner); 36 | } 37 | 38 | static void ShowBanner(BannerAttribute attribute) 39 | { 40 | Write(attribute.Text); 41 | } 42 | 43 | static void PopulateInstanceParameters(IGoCommando commando, string[] args) 44 | { 45 | var parser = new ArgParser(); 46 | var parameters = parser.Parse(args); 47 | var matches = Match(parameters, commando.GetType().GetAttributes()); 48 | 49 | } 50 | 51 | static List Match(List parameters, IEnumerable attributes) 52 | { 53 | var positionalAttributes = attributes.Where(a => a is PositionalArgumentAttribute).Cast(); 54 | var otherAttributes = attributes.Where(a => a is NamedArgumentAttribute).Cast(); 55 | var positionalParameters = parameters.Where(p => p is PositionalCommandLineParameter).Cast(); 56 | var otherParameters = parameters.Where(p => p is NamedCommandLineParameter).Cast(); 57 | var matches = new List(); 58 | 59 | //drop alt det med positional args!! 60 | 61 | return matches; 62 | } 63 | 64 | static void Write(string text) 65 | { 66 | Console.WriteLine(text); 67 | } 68 | } 69 | 70 | public class ArgumentMatch 71 | { 72 | } 73 | } -------------------------------------------------------------------------------- /old/src/GoCommando/GoCommando.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {83A32DB4-90CF-4707-9463-2E0589F80EFD} 9 | Library 10 | Properties 11 | GoCommando 12 | GoCommando 13 | v3.5 14 | 512 15 | 16 | 17 | 3.5 18 | 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | 3.5 41 | 42 | 43 | 3.5 44 | 45 | 46 | 3.5 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 81 | -------------------------------------------------------------------------------- /old/src/GoCommando/GoCommando.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | http://en.wikipedia.org/wiki/Beerware 10 | http://mookid.dk/oncode/gocommando 11 | false 12 | $description$ 13 | Copyright 2011 14 | command-line 15 | 16 | -------------------------------------------------------------------------------- /old/src/GoCommando/Helpers/ArgParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using GoCommando.Parameters; 5 | 6 | namespace GoCommando.Helpers 7 | { 8 | public class ArgParser 9 | { 10 | class ParserContext 11 | { 12 | public ParserContext() 13 | { 14 | ParsingPositionalParameters = true; 15 | Index = 1; 16 | } 17 | 18 | public int Index { get; set; } 19 | public bool ParsingPositionalParameters { get; set; } 20 | } 21 | 22 | public List Parse(string[] args) 23 | { 24 | var context = new ParserContext(); 25 | 26 | return args 27 | .Where(s => s != null && s.Trim() != "") 28 | .Select(arg => ToCommandLineParameter(arg, context)).ToList(); 29 | } 30 | 31 | CommandLineParameter ToCommandLineParameter(string arg, ParserContext context) 32 | { 33 | return 34 | !arg.StartsWith("-") 35 | ? CreatePositionalCommandLineParameter(arg, context) 36 | : CreateNamedCommandLineParameter(arg, context); 37 | } 38 | 39 | PositionalCommandLineParameter CreatePositionalCommandLineParameter(string arg, ParserContext context) 40 | { 41 | if (!context.ParsingPositionalParameters) 42 | { 43 | throw new FormatException(string.Format("Named parameters cannot be followed by positional parameters")); 44 | } 45 | 46 | return new PositionalCommandLineParameter(context.Index++, arg); 47 | } 48 | 49 | CommandLineParameter CreateNamedCommandLineParameter(string arg, ParserContext context) 50 | { 51 | context.ParsingPositionalParameters = false; 52 | 53 | // trim - 54 | arg = arg.Substring(1); 55 | 56 | var separatorIndex = arg.IndexOf(':'); 57 | 58 | return separatorIndex == -1 59 | ? new NamedCommandLineParameter(arg, "True") 60 | : new NamedCommandLineParameter(arg.Substring(0, separatorIndex), arg.Substring(separatorIndex + 1)); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Helpers/Binder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using GoCommando.Attributes; 6 | using GoCommando.Exceptions; 7 | using GoCommando.Parameters; 8 | 9 | namespace GoCommando.Helpers 10 | { 11 | public class Binder 12 | { 13 | public BindingReport Bind(object targetObjectWithAttributes, IEnumerable parametersToBind) 14 | { 15 | var context = new BindingContext(); 16 | var helper = new Helper(); 17 | var parameters = helper.GetParameters(targetObjectWithAttributes); 18 | 19 | foreach (var parameter in parameters) 20 | { 21 | Bind(targetObjectWithAttributes, parameter.PropertyInfo, parametersToBind.ToList(), 22 | parameter.ArgumentAttribute, 23 | context); 24 | } 25 | 26 | return context.Report; 27 | } 28 | 29 | class BindingContext 30 | { 31 | public BindingContext() 32 | { 33 | Position = 1; 34 | } 35 | 36 | readonly BindingReport report = new BindingReport(); 37 | 38 | public int Position { get; private set; } 39 | 40 | public void IncrementPosition() 41 | { 42 | Position++; 43 | } 44 | 45 | public BindingReport Report 46 | { 47 | get { return report; } 48 | } 49 | } 50 | 51 | void Bind(object commando, PropertyInfo property, List parameters, ArgumentAttribute attribute, BindingContext context) 52 | { 53 | if (attribute is PositionalArgumentAttribute) 54 | { 55 | BindPositional(commando, property, parameters, (PositionalArgumentAttribute) attribute, context); 56 | } 57 | else if (attribute is NamedArgumentAttribute) 58 | { 59 | BindNamed(commando, property, parameters, (NamedArgumentAttribute) attribute, context); 60 | } 61 | else 62 | { 63 | throw Ex("Don't know the attribute type {0}", attribute.GetType().Name); 64 | } 65 | } 66 | 67 | void BindNamed(object commando, PropertyInfo property, List parameters, NamedArgumentAttribute attribute, BindingContext context) 68 | { 69 | var name = attribute.Name; 70 | var shortHand = attribute.ShortHand; 71 | var parameter = parameters.Where(p => p is NamedCommandLineParameter) 72 | .Cast() 73 | .SingleOrDefault(p => p.Name == name || p.Name == shortHand); 74 | 75 | var value = parameter != null 76 | ? Mutate(parameter, property) 77 | : attribute.Default != null 78 | ? Mutate(attribute.Default, property) 79 | : null; 80 | 81 | if (value == null) 82 | { 83 | context.Report.PropertiesNotBound.Add(property); 84 | 85 | if (!attribute.Required) return; 86 | 87 | throw Ex("Could not find parameter matching required parameter named {0}", name); 88 | } 89 | 90 | property.SetValue(commando, value, null); 91 | 92 | context.Report.PropertiesBound.Add(property); 93 | } 94 | 95 | void BindPositional(object commando, PropertyInfo property, List parameters, PositionalArgumentAttribute attribute, BindingContext context) 96 | { 97 | var parameter = parameters 98 | .Where(p => p is PositionalCommandLineParameter) 99 | .Cast() 100 | .SingleOrDefault(p => p.Index == context.Position); 101 | 102 | if (parameter == null) 103 | { 104 | context.Report.PropertiesNotBound.Add(property); 105 | context.Report.RequiredPropertiesNotBound.Add(property); 106 | 107 | if (!attribute.Required) return; 108 | 109 | throw Ex("Could not find parameter matching required positional parameter at index {0}", context.Position); 110 | } 111 | 112 | property.SetValue(commando, Mutate(parameter, property), null); 113 | 114 | context.Report.PropertiesBound.Add(property); 115 | context.IncrementPosition(); 116 | } 117 | 118 | object Mutate(CommandLineParameter parameter, PropertyInfo property) 119 | { 120 | return Mutate(parameter.Value, property); 121 | } 122 | 123 | object Mutate(string value, PropertyInfo property) 124 | { 125 | var propertyType = property.PropertyType; 126 | 127 | try 128 | { 129 | return Convert.ChangeType(value, propertyType); 130 | } 131 | catch(Exception) 132 | { 133 | throw Ex("Could not automatically turn '{0}' into a value of type {1}", value, 134 | propertyType.Name); 135 | } 136 | } 137 | 138 | CommandoException Ex(string message, params object[] objs) 139 | { 140 | return new CommandoException(message, objs); 141 | } 142 | } 143 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Helpers/BindingReport.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Reflection; 3 | 4 | namespace GoCommando.Helpers 5 | { 6 | public class BindingReport 7 | { 8 | readonly List requiredPropertiesNotBound = new List(); 9 | readonly List propertiesNotBound = new List(); 10 | readonly List propertiesBound = new List(); 11 | 12 | public List PropertiesNotBound 13 | { 14 | get { return propertiesNotBound; } 15 | } 16 | 17 | public List PropertiesBound 18 | { 19 | get { return propertiesBound; } 20 | } 21 | 22 | public List RequiredPropertiesNotBound 23 | { 24 | get { return requiredPropertiesNotBound; } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Helpers/Helper.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Reflection; 4 | using GoCommando.Attributes; 5 | using GoCommando.Extensions; 6 | 7 | namespace GoCommando.Helpers 8 | { 9 | public class Helper 10 | { 11 | class HelperContext : IHasPositionerCounter 12 | { 13 | public HelperContext() 14 | { 15 | Position = 1; 16 | } 17 | 18 | public int Position { get; set; } 19 | } 20 | 21 | public List GetParameters(object obj) 22 | { 23 | var context = new HelperContext(); 24 | 25 | return obj.GetType().GetProperties() 26 | .Where(ShouldBeIncluded) 27 | .Select(p => new Parameter(p, context)) 28 | .ToList(); 29 | } 30 | 31 | bool ShouldBeIncluded(PropertyInfo info) 32 | { 33 | return info.HasAttribute(); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Helpers/IHasPositionerCounter.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando.Helpers 2 | { 3 | public interface IHasPositionerCounter 4 | { 5 | int Position { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Helpers/Parameter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Reflection; 4 | using GoCommando.Attributes; 5 | using GoCommando.Extensions; 6 | 7 | namespace GoCommando.Helpers 8 | { 9 | public class Parameter 10 | { 11 | public Parameter(PropertyInfo propertyInfo, IHasPositionerCounter context) 12 | { 13 | Examples = new List(); 14 | 15 | var attributes = propertyInfo.GetAttributes(); 16 | 17 | if (attributes.Count == 1) 18 | { 19 | Description = attributes[0].Text; 20 | } 21 | 22 | var argumentAttribute = propertyInfo.GetAttributes().Single(); 23 | 24 | if (argumentAttribute is NamedArgumentAttribute) 25 | { 26 | var namedArgumentAttribute = (NamedArgumentAttribute)argumentAttribute; 27 | Shorthand = namedArgumentAttribute.ShortHand; 28 | Name = namedArgumentAttribute.Name; 29 | } 30 | else if (argumentAttribute is PositionalArgumentAttribute) 31 | { 32 | Position = context.Position++; 33 | } 34 | 35 | PropertyInfo = propertyInfo; 36 | ArgumentAttribute = argumentAttribute; 37 | 38 | foreach (var example in propertyInfo.GetAttributes()) 39 | { 40 | Examples.Add(example); 41 | } 42 | 43 | } 44 | 45 | public string Description { get; set; } 46 | 47 | public string Name { get; set; } 48 | public string Shorthand { get; set; } 49 | 50 | public int Position { get; set; } 51 | 52 | public PropertyInfo PropertyInfo { get; set; } 53 | public ArgumentAttribute ArgumentAttribute { get; set; } 54 | 55 | public List Examples { get; set; } 56 | } 57 | } -------------------------------------------------------------------------------- /old/src/GoCommando/IGoCommando.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando 2 | { 3 | public interface IGoCommando 4 | { 5 | void Run(); 6 | } 7 | } -------------------------------------------------------------------------------- /old/src/GoCommando/NamedArgumentAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 6 | public class NamedArgumentAttribute : ArgumentAttribute 7 | { 8 | public string Name { get; set; } 9 | public string ShortHand { get; set; } 10 | 11 | public NamedArgumentAttribute(string name, string shortHand) 12 | { 13 | Name = name; 14 | ShortHand = shortHand; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /old/src/GoCommando/NamedCommandLineParameter.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando 2 | { 3 | public class NamedCommandLineParameter : CommandLineParameter 4 | { 5 | public NamedCommandLineParameter(string name, string value) : base(value) 6 | { 7 | Name = name; 8 | } 9 | 10 | public string Name { get; set; } 11 | 12 | public override string ToString() 13 | { 14 | return string.Format("/{0}:{1}", Name, Value); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /old/src/GoCommando/NamedFlagCommandLineParameter.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando 2 | { 3 | //public class NamedFlagCommandLineParameter : CommandLineParameter 4 | //{ 5 | // public NamedFlagCommandLineParameter(string value) : base(value) 6 | // { 7 | // } 8 | 9 | // public override string ToString() 10 | // { 11 | // return string.Format("/{0}", Value); 12 | // } 13 | //} 14 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Parameters/CommandLineParameter.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando.Parameters 2 | { 3 | public abstract class CommandLineParameter 4 | { 5 | protected CommandLineParameter(string value) 6 | { 7 | Value = value; 8 | } 9 | 10 | public string Value { get; private set; } 11 | } 12 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Parameters/NamedCommandLineParameter.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando.Parameters 2 | { 3 | public class NamedCommandLineParameter : CommandLineParameter 4 | { 5 | public NamedCommandLineParameter(string name, string value) : base(value) 6 | { 7 | Name = name; 8 | } 9 | 10 | public string Name { get; set; } 11 | 12 | public override string ToString() 13 | { 14 | return string.Format("/{0}:{1}", Name, Value); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Parameters/PositionalCommandLineParameter.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando.Parameters 2 | { 3 | public class PositionalCommandLineParameter : CommandLineParameter 4 | { 5 | public PositionalCommandLineParameter(int index, string value) : base(value) 6 | { 7 | Index = index; 8 | } 9 | 10 | public int Index { get; set; } 11 | 12 | public override string ToString() 13 | { 14 | return string.Format("[{0}]: {1}", Index, Value); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /old/src/GoCommando/PositionalArgumentAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GoCommando 4 | { 5 | [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 6 | public class PositionalArgumentAttribute : ArgumentAttribute 7 | { 8 | public int Index { get; set; } 9 | 10 | public PositionalArgumentAttribute(int index) 11 | { 12 | Index = index; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /old/src/GoCommando/PositionalCommandLineParameter.cs: -------------------------------------------------------------------------------- 1 | namespace GoCommando 2 | { 3 | class PositionalCommandLineParameter : CommandLineParameter 4 | { 5 | public PositionalCommandLineParameter(int index, string value) : base(value) 6 | { 7 | Index = index; 8 | } 9 | 10 | public int Index { get; set; } 11 | 12 | public override string ToString() 13 | { 14 | return string.Format("[{0}]: {1}", Index, Value); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /old/src/GoCommando/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("GoCommando")] 5 | [assembly: AssemblyDescription("GoCommando is a small command line utility helper that does the boring work when creating command line utilities in .NET.")] 6 | [assembly: AssemblyCompany("Mogens Heller Grabe")] 7 | [assembly: AssemblyProduct("GoCommando")] 8 | [assembly: AssemblyCopyright("Copyright © 2011")] 9 | [assembly: AssemblyTrademark("")] 10 | [assembly: AssemblyCulture("")] 11 | 12 | #if DEBUG 13 | [assembly: AssemblyConfiguration("Debug")] 14 | #else 15 | [assembly: AssemblyConfiguration("Release")] 16 | #endif 17 | 18 | [assembly: ComVisible(false)] 19 | 20 | [assembly: Guid("a4168feb-47c2-4fcc-93f8-e14172192ec3")] 21 | 22 | [assembly: AssemblyVersion("0.3.0.0")] 23 | [assembly: AssemblyFileVersion("0.3.0.0")] 24 | -------------------------------------------------------------------------------- /old/tools/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rebus-org/GoCommando/e56e6f896f0794a6072756d358d7aeea493563d4/old/tools/NuGet.exe -------------------------------------------------------------------------------- /packages/NUnit.2.6.4/NUnit.2.6.4.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rebus-org/GoCommando/e56e6f896f0794a6072756d358d7aeea493563d4/packages/NUnit.2.6.4/NUnit.2.6.4.nupkg -------------------------------------------------------------------------------- /packages/NUnit.2.6.4/lib/nunit.framework.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rebus-org/GoCommando/e56e6f896f0794a6072756d358d7aeea493563d4/packages/NUnit.2.6.4/lib/nunit.framework.dll -------------------------------------------------------------------------------- /packages/NUnit.2.6.4/license.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rebus-org/GoCommando/e56e6f896f0794a6072756d358d7aeea493563d4/packages/NUnit.2.6.4/license.txt -------------------------------------------------------------------------------- /scripts/build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set scriptsdir=%~dp0 4 | set root=%scriptsdir%\.. 5 | set project=%1 6 | set version=%2 7 | 8 | if "%project%"=="" ( 9 | echo Please invoke the build script with a project name as its first argument. 10 | echo. 11 | goto exit_fail 12 | ) 13 | 14 | if "%version%"=="" ( 15 | echo Please invoke the build script with a version as its second argument. 16 | echo. 17 | goto exit_fail 18 | ) 19 | 20 | set Version=%version% 21 | 22 | pushd %root% 23 | 24 | dotnet restore 25 | if %ERRORLEVEL% neq 0 ( 26 | popd 27 | goto exit_fail 28 | ) 29 | 30 | dotnet build "%root%\%project%" -c Release 31 | if %ERRORLEVEL% neq 0 ( 32 | popd 33 | goto exit_fail 34 | ) 35 | 36 | popd 37 | 38 | 39 | 40 | 41 | 42 | 43 | goto exit_success 44 | :exit_fail 45 | exit /b 1 46 | :exit_success -------------------------------------------------------------------------------- /scripts/patch_assemblyinfo.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set reporoot=%~dp0\.. 4 | set aversion=%reporoot%\tools\aversion\aversion 5 | set projectdir=%1 6 | 7 | if "%version%"=="" ( 8 | "%aversion%" patch -ver 1.0.0 -in %projectdir%\Properties\AssemblyInfo.cs -out %projectdir%\Properties\AssemblyInfo_Patch.cs -token $version$ 9 | ) else ( 10 | "%aversion%" patch -ver %version% -in %projectdir%\Properties\AssemblyInfo.cs -out %projectdir%\Properties\AssemblyInfo_Patch.cs -token $version$ 11 | ) 12 | 13 | -------------------------------------------------------------------------------- /scripts/push.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set version=%1 4 | 5 | if "%version%"=="" ( 6 | echo Please remember to specify which version to push as an argument. 7 | goto exit_fail 8 | ) 9 | 10 | set reporoot=%~dp0\.. 11 | set destination=%reporoot%\deploy 12 | 13 | if not exist "%destination%" ( 14 | echo Could not find %destination% 15 | echo. 16 | echo Did you remember to build the packages before running this script? 17 | ) 18 | 19 | set nuget=%reporoot%\tools\NuGet\NuGet.exe 20 | 21 | if not exist "%nuget%" ( 22 | echo Could not find NuGet here: 23 | echo. 24 | echo "%nuget%" 25 | echo. 26 | goto exit_fail 27 | ) 28 | 29 | 30 | "%nuget%" push "%destination%\*.%version%.nupkg" -Source https://www.nuget.org/api/v2/package 31 | if %ERRORLEVEL% neq 0 ( 32 | echo NuGet push failed. 33 | goto exit_fail 34 | ) 35 | 36 | 37 | 38 | 39 | 40 | 41 | goto exit_success 42 | :exit_fail 43 | exit /b 1 44 | :exit_success 45 | -------------------------------------------------------------------------------- /scripts/release.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set scriptsdir=%~dp0 4 | set root=%scriptsdir%\.. 5 | set deploydir=%root%\deploy 6 | set project=%1 7 | set version=%2 8 | 9 | if "%project%"=="" ( 10 | echo Please invoke the build script with a project name as its first argument. 11 | echo. 12 | goto exit_fail 13 | ) 14 | 15 | if "%version%"=="" ( 16 | echo Please invoke the build script with a version as its second argument. 17 | echo. 18 | goto exit_fail 19 | ) 20 | 21 | set Version=%version% 22 | 23 | if exist "%deploydir%" ( 24 | rd "%deploydir%" /s/q 25 | ) 26 | 27 | pushd %root% 28 | 29 | dotnet restore 30 | if %ERRORLEVEL% neq 0 ( 31 | popd 32 | goto exit_fail 33 | ) 34 | 35 | dotnet pack "%root%/%project%" -c Release -o "%deploydir%" /p:PackageVersion=%version% 36 | if %ERRORLEVEL% neq 0 ( 37 | popd 38 | goto exit_fail 39 | ) 40 | 41 | call scripts\push.cmd "%version%" 42 | 43 | popd 44 | 45 | 46 | 47 | 48 | 49 | 50 | goto exit_success 51 | :exit_fail 52 | exit /b 1 53 | :exit_success -------------------------------------------------------------------------------- /tools/NuGet/nuget.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rebus-org/GoCommando/e56e6f896f0794a6072756d358d7aeea493563d4/tools/NuGet/nuget.exe --------------------------------------------------------------------------------