diff --git a/README.md b/README.md index a14a1b274d..334618c4e6 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,6 @@ This repository contains the code for the System.CommandLine libraries and the ` Package | Version | Description ---------------------------------| ------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- `System.CommandLine` | [![Nuget](https://img.shields.io/nuget/v/System.CommandLine.svg)](https://nuget.org/packages/System.CommandLine) | Command line parser, model binding, invocation, shell completions -`System.CommandLine.DragonFruit` | [![Nuget](https://img.shields.io/nuget/v/System.CommandLine.DragonFruit.svg)](https://nuget.org/packages/System.CommandLine.DragonFruit) | Build command-line apps by convention with a strongly-typed `Main` method -`System.CommandLine.Hosting` | [![Nuget](https://img.shields.io/nuget/v/System.CommandLine.Hosting.svg)](https://nuget.org/packages/System.CommandLine.Hosting) | support for using System.CommandLine with [Microsoft.Extensions.Hosting](https://www.nuget.org/packages/Microsoft.Extensions.Hosting/) `dotnet-suggest` | [![Nuget](https://img.shields.io/nuget/v/dotnet-suggest.svg)](https://nuget.org/packages/dotnet-suggest) | A command-line tool to provide shell completions for apps built using `System.CommandLine`. ### Daily Builds diff --git a/System.CommandLine.sln b/System.CommandLine.sln index 2b4452b1d5..9e5fb55777 100644 --- a/System.CommandLine.sln +++ b/System.CommandLine.sln @@ -29,36 +29,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CommandLine", "src\S EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CommandLine.Tests", "src\System.CommandLine.Tests\System.CommandLine.Tests.csproj", "{F843CCCA-4CC9-422C-A881-3AE6A998B53F}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{6749FB3E-39DE-4321-A39E-525278E9408D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DragonFruit", "samples\DragonFruit\DragonFruit.csproj", "{8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CommandLine.DragonFruit", "src\System.CommandLine.DragonFruit\System.CommandLine.DragonFruit.csproj", "{EEC30462-078F-45EB-AA70-12E3170CD51E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CommandLine.DragonFruit.Tests", "src\System.CommandLine.DragonFruit.Tests\System.CommandLine.DragonFruit.Tests.csproj", "{1F4B2074-F651-4A02-A860-7DDA74B2CC5F}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-suggest", "src\System.CommandLine.Suggest\dotnet-suggest.csproj", "{E23C760E-B826-4B4F-BE76-916D86BAD2DB}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-suggest.Tests", "src\System.CommandLine.Suggest.Tests\dotnet-suggest.Tests.csproj", "{E41F0471-B14D-4FA0-9D8B-1E7750695AE9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RenderingPlayground", "samples\RenderingPlayground\RenderingPlayground.csproj", "{8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CommandLine.Rendering", "src\System.CommandLine.Rendering\System.CommandLine.Rendering.csproj", "{27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CommandLine.Rendering.Tests", "src\System.CommandLine.Rendering.Tests\System.CommandLine.Rendering.Tests.csproj", "{9E574595-A9CD-441A-9328-1D4DD5B531E8}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CommandLine.Hosting", "src\System.CommandLine.Hosting\System.CommandLine.Hosting.csproj", "{644C4B4A-4A32-4307-9F71-C3BF901FFB66}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CommandLine.Hosting.Tests", "src\System.CommandLine.Hosting.Tests\System.CommandLine.Hosting.Tests.csproj", "{39483140-BC26-4CAD-BBAE-3DC76C2F16CF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HostingPlayground", "samples\HostingPlayground\HostingPlayground.csproj", "{0BF6958D-9EE3-4623-B3D6-4DA77EAC1906}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CommandLine.Generator.CommandHandler", "src\System.CommandLine.Generator.CommandHandler\System.CommandLine.Generator.CommandHandler.csproj", "{591EF370-7AD7-4624-8B9D-FD15010CA657}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CommandLine.NamingConventionBinder", "src\System.CommandLine.NamingConventionBinder\System.CommandLine.NamingConventionBinder.csproj", "{10DFE204-B027-49DA-BD77-08ECA18DD357}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CommandLine.NamingConventionBinder.Tests", "src\System.CommandLine.NamingConventionBinder.Tests\System.CommandLine.NamingConventionBinder.Tests.csproj", "{789A05F2-5EF6-4FE8-9609-4706207E047E}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.CommandLine.ApiCompatibility.Tests", "src\System.CommandLine.ApiCompatibility.Tests\System.CommandLine.ApiCompatibility.Tests.csproj", "{A54EE328-D456-4BAF-A180-84E77E6409AC}" EndProject Global @@ -95,42 +71,6 @@ Global {F843CCCA-4CC9-422C-A881-3AE6A998B53F}.Release|x64.Build.0 = Release|Any CPU {F843CCCA-4CC9-422C-A881-3AE6A998B53F}.Release|x86.ActiveCfg = Release|Any CPU {F843CCCA-4CC9-422C-A881-3AE6A998B53F}.Release|x86.Build.0 = Release|Any CPU - {8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00}.Debug|x64.ActiveCfg = Debug|Any CPU - {8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00}.Debug|x64.Build.0 = Debug|Any CPU - {8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00}.Debug|x86.ActiveCfg = Debug|Any CPU - {8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00}.Debug|x86.Build.0 = Debug|Any CPU - {8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00}.Release|Any CPU.Build.0 = Release|Any CPU - {8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00}.Release|x64.ActiveCfg = Release|Any CPU - {8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00}.Release|x64.Build.0 = Release|Any CPU - {8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00}.Release|x86.ActiveCfg = Release|Any CPU - {8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00}.Release|x86.Build.0 = Release|Any CPU - {EEC30462-078F-45EB-AA70-12E3170CD51E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EEC30462-078F-45EB-AA70-12E3170CD51E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EEC30462-078F-45EB-AA70-12E3170CD51E}.Debug|x64.ActiveCfg = Debug|Any CPU - {EEC30462-078F-45EB-AA70-12E3170CD51E}.Debug|x64.Build.0 = Debug|Any CPU - {EEC30462-078F-45EB-AA70-12E3170CD51E}.Debug|x86.ActiveCfg = Debug|Any CPU - {EEC30462-078F-45EB-AA70-12E3170CD51E}.Debug|x86.Build.0 = Debug|Any CPU - {EEC30462-078F-45EB-AA70-12E3170CD51E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EEC30462-078F-45EB-AA70-12E3170CD51E}.Release|Any CPU.Build.0 = Release|Any CPU - {EEC30462-078F-45EB-AA70-12E3170CD51E}.Release|x64.ActiveCfg = Release|Any CPU - {EEC30462-078F-45EB-AA70-12E3170CD51E}.Release|x64.Build.0 = Release|Any CPU - {EEC30462-078F-45EB-AA70-12E3170CD51E}.Release|x86.ActiveCfg = Release|Any CPU - {EEC30462-078F-45EB-AA70-12E3170CD51E}.Release|x86.Build.0 = Release|Any CPU - {1F4B2074-F651-4A02-A860-7DDA74B2CC5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1F4B2074-F651-4A02-A860-7DDA74B2CC5F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1F4B2074-F651-4A02-A860-7DDA74B2CC5F}.Debug|x64.ActiveCfg = Debug|Any CPU - {1F4B2074-F651-4A02-A860-7DDA74B2CC5F}.Debug|x64.Build.0 = Debug|Any CPU - {1F4B2074-F651-4A02-A860-7DDA74B2CC5F}.Debug|x86.ActiveCfg = Debug|Any CPU - {1F4B2074-F651-4A02-A860-7DDA74B2CC5F}.Debug|x86.Build.0 = Debug|Any CPU - {1F4B2074-F651-4A02-A860-7DDA74B2CC5F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1F4B2074-F651-4A02-A860-7DDA74B2CC5F}.Release|Any CPU.Build.0 = Release|Any CPU - {1F4B2074-F651-4A02-A860-7DDA74B2CC5F}.Release|x64.ActiveCfg = Release|Any CPU - {1F4B2074-F651-4A02-A860-7DDA74B2CC5F}.Release|x64.Build.0 = Release|Any CPU - {1F4B2074-F651-4A02-A860-7DDA74B2CC5F}.Release|x86.ActiveCfg = Release|Any CPU - {1F4B2074-F651-4A02-A860-7DDA74B2CC5F}.Release|x86.Build.0 = Release|Any CPU {E23C760E-B826-4B4F-BE76-916D86BAD2DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E23C760E-B826-4B4F-BE76-916D86BAD2DB}.Debug|Any CPU.Build.0 = Debug|Any CPU {E23C760E-B826-4B4F-BE76-916D86BAD2DB}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -155,78 +95,6 @@ Global {E41F0471-B14D-4FA0-9D8B-1E7750695AE9}.Release|x64.Build.0 = Release|Any CPU {E41F0471-B14D-4FA0-9D8B-1E7750695AE9}.Release|x86.ActiveCfg = Release|Any CPU {E41F0471-B14D-4FA0-9D8B-1E7750695AE9}.Release|x86.Build.0 = Release|Any CPU - {8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E}.Debug|x64.ActiveCfg = Debug|Any CPU - {8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E}.Debug|x64.Build.0 = Debug|Any CPU - {8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E}.Debug|x86.ActiveCfg = Debug|Any CPU - {8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E}.Debug|x86.Build.0 = Debug|Any CPU - {8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E}.Release|Any CPU.Build.0 = Release|Any CPU - {8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E}.Release|x64.ActiveCfg = Release|Any CPU - {8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E}.Release|x64.Build.0 = Release|Any CPU - {8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E}.Release|x86.ActiveCfg = Release|Any CPU - {8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E}.Release|x86.Build.0 = Release|Any CPU - {27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E}.Debug|x64.ActiveCfg = Debug|Any CPU - {27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E}.Debug|x64.Build.0 = Debug|Any CPU - {27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E}.Debug|x86.ActiveCfg = Debug|Any CPU - {27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E}.Debug|x86.Build.0 = Debug|Any CPU - {27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E}.Release|Any CPU.Build.0 = Release|Any CPU - {27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E}.Release|x64.ActiveCfg = Release|Any CPU - {27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E}.Release|x64.Build.0 = Release|Any CPU - {27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E}.Release|x86.ActiveCfg = Release|Any CPU - {27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E}.Release|x86.Build.0 = Release|Any CPU - {9E574595-A9CD-441A-9328-1D4DD5B531E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9E574595-A9CD-441A-9328-1D4DD5B531E8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9E574595-A9CD-441A-9328-1D4DD5B531E8}.Debug|x64.ActiveCfg = Debug|Any CPU - {9E574595-A9CD-441A-9328-1D4DD5B531E8}.Debug|x64.Build.0 = Debug|Any CPU - {9E574595-A9CD-441A-9328-1D4DD5B531E8}.Debug|x86.ActiveCfg = Debug|Any CPU - {9E574595-A9CD-441A-9328-1D4DD5B531E8}.Debug|x86.Build.0 = Debug|Any CPU - {9E574595-A9CD-441A-9328-1D4DD5B531E8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9E574595-A9CD-441A-9328-1D4DD5B531E8}.Release|Any CPU.Build.0 = Release|Any CPU - {9E574595-A9CD-441A-9328-1D4DD5B531E8}.Release|x64.ActiveCfg = Release|Any CPU - {9E574595-A9CD-441A-9328-1D4DD5B531E8}.Release|x64.Build.0 = Release|Any CPU - {9E574595-A9CD-441A-9328-1D4DD5B531E8}.Release|x86.ActiveCfg = Release|Any CPU - {9E574595-A9CD-441A-9328-1D4DD5B531E8}.Release|x86.Build.0 = Release|Any CPU - {644C4B4A-4A32-4307-9F71-C3BF901FFB66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {644C4B4A-4A32-4307-9F71-C3BF901FFB66}.Debug|Any CPU.Build.0 = Debug|Any CPU - {644C4B4A-4A32-4307-9F71-C3BF901FFB66}.Debug|x64.ActiveCfg = Debug|Any CPU - {644C4B4A-4A32-4307-9F71-C3BF901FFB66}.Debug|x64.Build.0 = Debug|Any CPU - {644C4B4A-4A32-4307-9F71-C3BF901FFB66}.Debug|x86.ActiveCfg = Debug|Any CPU - {644C4B4A-4A32-4307-9F71-C3BF901FFB66}.Debug|x86.Build.0 = Debug|Any CPU - {644C4B4A-4A32-4307-9F71-C3BF901FFB66}.Release|Any CPU.ActiveCfg = Release|Any CPU - {644C4B4A-4A32-4307-9F71-C3BF901FFB66}.Release|Any CPU.Build.0 = Release|Any CPU - {644C4B4A-4A32-4307-9F71-C3BF901FFB66}.Release|x64.ActiveCfg = Release|Any CPU - {644C4B4A-4A32-4307-9F71-C3BF901FFB66}.Release|x64.Build.0 = Release|Any CPU - {644C4B4A-4A32-4307-9F71-C3BF901FFB66}.Release|x86.ActiveCfg = Release|Any CPU - {644C4B4A-4A32-4307-9F71-C3BF901FFB66}.Release|x86.Build.0 = Release|Any CPU - {39483140-BC26-4CAD-BBAE-3DC76C2F16CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {39483140-BC26-4CAD-BBAE-3DC76C2F16CF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {39483140-BC26-4CAD-BBAE-3DC76C2F16CF}.Debug|x64.ActiveCfg = Debug|Any CPU - {39483140-BC26-4CAD-BBAE-3DC76C2F16CF}.Debug|x64.Build.0 = Debug|Any CPU - {39483140-BC26-4CAD-BBAE-3DC76C2F16CF}.Debug|x86.ActiveCfg = Debug|Any CPU - {39483140-BC26-4CAD-BBAE-3DC76C2F16CF}.Debug|x86.Build.0 = Debug|Any CPU - {39483140-BC26-4CAD-BBAE-3DC76C2F16CF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {39483140-BC26-4CAD-BBAE-3DC76C2F16CF}.Release|Any CPU.Build.0 = Release|Any CPU - {39483140-BC26-4CAD-BBAE-3DC76C2F16CF}.Release|x64.ActiveCfg = Release|Any CPU - {39483140-BC26-4CAD-BBAE-3DC76C2F16CF}.Release|x64.Build.0 = Release|Any CPU - {39483140-BC26-4CAD-BBAE-3DC76C2F16CF}.Release|x86.ActiveCfg = Release|Any CPU - {39483140-BC26-4CAD-BBAE-3DC76C2F16CF}.Release|x86.Build.0 = Release|Any CPU - {0BF6958D-9EE3-4623-B3D6-4DA77EAC1906}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0BF6958D-9EE3-4623-B3D6-4DA77EAC1906}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0BF6958D-9EE3-4623-B3D6-4DA77EAC1906}.Debug|x64.ActiveCfg = Debug|Any CPU - {0BF6958D-9EE3-4623-B3D6-4DA77EAC1906}.Debug|x64.Build.0 = Debug|Any CPU - {0BF6958D-9EE3-4623-B3D6-4DA77EAC1906}.Debug|x86.ActiveCfg = Debug|Any CPU - {0BF6958D-9EE3-4623-B3D6-4DA77EAC1906}.Debug|x86.Build.0 = Debug|Any CPU - {0BF6958D-9EE3-4623-B3D6-4DA77EAC1906}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0BF6958D-9EE3-4623-B3D6-4DA77EAC1906}.Release|Any CPU.Build.0 = Release|Any CPU - {0BF6958D-9EE3-4623-B3D6-4DA77EAC1906}.Release|x64.ActiveCfg = Release|Any CPU - {0BF6958D-9EE3-4623-B3D6-4DA77EAC1906}.Release|x64.Build.0 = Release|Any CPU - {0BF6958D-9EE3-4623-B3D6-4DA77EAC1906}.Release|x86.ActiveCfg = Release|Any CPU - {0BF6958D-9EE3-4623-B3D6-4DA77EAC1906}.Release|x86.Build.0 = Release|Any CPU {591EF370-7AD7-4624-8B9D-FD15010CA657}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {591EF370-7AD7-4624-8B9D-FD15010CA657}.Debug|Any CPU.Build.0 = Debug|Any CPU {591EF370-7AD7-4624-8B9D-FD15010CA657}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -239,30 +107,6 @@ Global {591EF370-7AD7-4624-8B9D-FD15010CA657}.Release|x64.Build.0 = Release|Any CPU {591EF370-7AD7-4624-8B9D-FD15010CA657}.Release|x86.ActiveCfg = Release|Any CPU {591EF370-7AD7-4624-8B9D-FD15010CA657}.Release|x86.Build.0 = Release|Any CPU - {10DFE204-B027-49DA-BD77-08ECA18DD357}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {10DFE204-B027-49DA-BD77-08ECA18DD357}.Debug|Any CPU.Build.0 = Debug|Any CPU - {10DFE204-B027-49DA-BD77-08ECA18DD357}.Debug|x64.ActiveCfg = Debug|Any CPU - {10DFE204-B027-49DA-BD77-08ECA18DD357}.Debug|x64.Build.0 = Debug|Any CPU - {10DFE204-B027-49DA-BD77-08ECA18DD357}.Debug|x86.ActiveCfg = Debug|Any CPU - {10DFE204-B027-49DA-BD77-08ECA18DD357}.Debug|x86.Build.0 = Debug|Any CPU - {10DFE204-B027-49DA-BD77-08ECA18DD357}.Release|Any CPU.ActiveCfg = Release|Any CPU - {10DFE204-B027-49DA-BD77-08ECA18DD357}.Release|Any CPU.Build.0 = Release|Any CPU - {10DFE204-B027-49DA-BD77-08ECA18DD357}.Release|x64.ActiveCfg = Release|Any CPU - {10DFE204-B027-49DA-BD77-08ECA18DD357}.Release|x64.Build.0 = Release|Any CPU - {10DFE204-B027-49DA-BD77-08ECA18DD357}.Release|x86.ActiveCfg = Release|Any CPU - {10DFE204-B027-49DA-BD77-08ECA18DD357}.Release|x86.Build.0 = Release|Any CPU - {789A05F2-5EF6-4FE8-9609-4706207E047E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {789A05F2-5EF6-4FE8-9609-4706207E047E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {789A05F2-5EF6-4FE8-9609-4706207E047E}.Debug|x64.ActiveCfg = Debug|Any CPU - {789A05F2-5EF6-4FE8-9609-4706207E047E}.Debug|x64.Build.0 = Debug|Any CPU - {789A05F2-5EF6-4FE8-9609-4706207E047E}.Debug|x86.ActiveCfg = Debug|Any CPU - {789A05F2-5EF6-4FE8-9609-4706207E047E}.Debug|x86.Build.0 = Debug|Any CPU - {789A05F2-5EF6-4FE8-9609-4706207E047E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {789A05F2-5EF6-4FE8-9609-4706207E047E}.Release|Any CPU.Build.0 = Release|Any CPU - {789A05F2-5EF6-4FE8-9609-4706207E047E}.Release|x64.ActiveCfg = Release|Any CPU - {789A05F2-5EF6-4FE8-9609-4706207E047E}.Release|x64.Build.0 = Release|Any CPU - {789A05F2-5EF6-4FE8-9609-4706207E047E}.Release|x86.ActiveCfg = Release|Any CPU - {789A05F2-5EF6-4FE8-9609-4706207E047E}.Release|x86.Build.0 = Release|Any CPU {A54EE328-D456-4BAF-A180-84E77E6409AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A54EE328-D456-4BAF-A180-84E77E6409AC}.Debug|Any CPU.Build.0 = Debug|Any CPU {A54EE328-D456-4BAF-A180-84E77E6409AC}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -282,20 +126,9 @@ Global GlobalSection(NestedProjects) = preSolution {0BE8E56E-7580-4526-BE24-D304E1779724} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} {F843CCCA-4CC9-422C-A881-3AE6A998B53F} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} - {8A592CB0-5FB9-4E70-A68A-BE5B5BE23C00} = {6749FB3E-39DE-4321-A39E-525278E9408D} - {EEC30462-078F-45EB-AA70-12E3170CD51E} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} - {1F4B2074-F651-4A02-A860-7DDA74B2CC5F} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} {E23C760E-B826-4B4F-BE76-916D86BAD2DB} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} {E41F0471-B14D-4FA0-9D8B-1E7750695AE9} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} - {8D9A8DCB-DC74-4B3A-B1C6-046C9C4F458E} = {6749FB3E-39DE-4321-A39E-525278E9408D} - {27E3BFFC-4412-4E4C-A656-B9D35B8A0F3E} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} - {9E574595-A9CD-441A-9328-1D4DD5B531E8} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} - {644C4B4A-4A32-4307-9F71-C3BF901FFB66} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} - {39483140-BC26-4CAD-BBAE-3DC76C2F16CF} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} - {0BF6958D-9EE3-4623-B3D6-4DA77EAC1906} = {6749FB3E-39DE-4321-A39E-525278E9408D} {591EF370-7AD7-4624-8B9D-FD15010CA657} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} - {10DFE204-B027-49DA-BD77-08ECA18DD357} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} - {789A05F2-5EF6-4FE8-9609-4706207E047E} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} {A54EE328-D456-4BAF-A180-84E77E6409AC} = {E5B1EC71-0FC4-4FAA-9C65-32D5016FBC45} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/core.slnf b/core.slnf index 394aa1bc1c..7657ecb700 100644 --- a/core.slnf +++ b/core.slnf @@ -3,9 +3,6 @@ "path": "System.CommandLine.sln", "projects": [ "src\\System.CommandLine.ApiCompatibility.Tests\\System.CommandLine.ApiCompatibility.Tests.csproj", - "src\\System.CommandLine.DragonFruit\\System.CommandLine.DragonFruit.csproj", - "src\\System.CommandLine.NamingConventionBinder.Tests\\System.CommandLine.NamingConventionBinder.Tests.csproj", - "src\\System.CommandLine.NamingConventionBinder\\System.CommandLine.NamingConventionBinder.csproj", "src\\System.CommandLine.Tests\\System.CommandLine.Tests.csproj", "src\\System.CommandLine\\System.CommandLine.csproj" ] diff --git a/docs/DragonFruit-overview.md b/docs/DragonFruit-overview.md deleted file mode 100644 index e0e7f30dc2..0000000000 --- a/docs/DragonFruit-overview.md +++ /dev/null @@ -1,109 +0,0 @@ -# What is DragonFruit? - -The entry point for a normal .NET console application looks like this: - -```csharp -static void Main(string[] args) -{ - Console.WriteLine("Hello World!"); -} -``` - -Interpreting the `string[]` arguments into behaviors has been left as a task for the developer. Did the user ask for help? Did they pass invalid input? Can the input be converted to the types that you need if they're not `string`? These problems are not solved for you. - -What if you could declare a strongly-typed `Main` method? This was the question that led to the creation of the experimental app model called "DragonFruit", which allows you to create an entry point with multiple parameters of various types and using default values, like this: - -```csharp -static void Main(int intOption = 42, bool boolOption = false, FileInfo fileOption = null) -{ - Console.WriteLine($"The value of intOption is: {intOption}"); - Console.WriteLine($"The value of boolOption is: {boolOption}"); - Console.WriteLine($"The value of fileOption is: {fileOption?.FullName ?? "null"}"); -} -``` - -DragonFruit handles help requests, parsing errors, argument binding, and more for you. - -```console -> ./myapp # or: > dotnet run -The value of intOption is: 42 -The value of boolOption is: False -The value of fileOption is: null -``` - -You don't need to write any special code to get help support. - -```console -> ./myapp -h # or: dotnet run -- -h -Usage: - myapp [options] - -Options: - --int-option intOption - --bool-option boolOption - --file-option fileOption -``` - -If you want more informative help, you can add it using standard XML comments: - -```csharp -/// -/// My example app -/// -/// An option whose argument will bind to an int -/// An option whose argument will bind to a bool -/// An option whose argument will bind to a FileInfo -static void Main(int intOption = 42, bool boolOption = false, FileInfo fileOption = null) -{ - Console.WriteLine($"The value of intOption is: {intOption}"); - Console.WriteLine($"The value of boolOption is: {boolOption}"); - Console.WriteLine($"The value of fileOption is: {fileOption?.FullName ?? "null"}"); -} -``` - -The text of those comments will be shown when a user requests help. - -```console -> dotnet run -- -h -Usage: - myapp [options] - -Options: - --int-option An option whose argument will bind to an int - --bool-option An option whose argument will bind to a bool - --file-option An option whose argument will bind to a FileInfo -``` - -## Arguments - -In addition to [options](Syntax-Concepts-and-Parser.md#Options) as shown in the examples above, DragonFruit also supports [arguments](Syntax-Concepts-and-Parser.md#Arguments). By convention, if you name a parameter in the `Main` method `args`, `argument`, or `arguments`, it will be exposed as an argument rather than an option. - -```csharp -static void Main(int intOption = 42, string[] args = null) -{ - Console.WriteLine($"The value of intOption is: {intOption}"); - - foreach (var arg in args) - { - Console.WriteLine(arg); - } -} -``` - -```console -> myapp -h -Usage: - myapp [options] - -Arguments: - - -Options: - --int-option intOption - --version Display version information -``` - -The argument follows the same conventions for arity as described in [arguments](Syntax-Concepts-and-Parser.md#Arguments-and-arity). - -You can try out DragonFruit by installing the latest preview [package](https://www.nuget.org/packages/System.CommandLine.DragonFruit). - diff --git a/docs/Your-first-app-with-System-CommandLine-DragonFruit.md b/docs/Your-first-app-with-System-CommandLine-DragonFruit.md deleted file mode 100644 index 54f19b0e85..0000000000 --- a/docs/Your-first-app-with-System-CommandLine-DragonFruit.md +++ /dev/null @@ -1,65 +0,0 @@ -# Building your first app with System.CommandLine.DragonFruit - -This walkthrough will show you how to get started using the System.CommandLine.DragonFruit app model to build a command line application. - -## Create a new console app - -Open a new console and run the following commands: - -```console -> dotnet new console -o myApp -> cd myApp -``` - -## Install the System.CommandLine.DragonFruit package - -[![Nuget](https://img.shields.io/nuget/v/System.CommandLine.DragonFruit.svg)](https://nuget.org/packages/System.CommandLine.DragonFruit) - -## Add some code - -Open `Program.cs`. You'll see that your `Main` method looks like this: - -```csharp -static void Main(string[] args) -{ - Console.WriteLine("Hello World!"); -} -``` - -If you run it, you'll see this: - -```console -> ./myapp # or: > dotnet run -Hello World! -``` - -The default main only takes `string` arguments as an array. With DragonFruit, you can accept named arguments of various types and specify default values. Change your `Main` method to this: - -```csharp -class Program -{ - /// An option whose argument is parsed as an int - /// An option whose argument is parsed as a bool - /// An option whose argument is parsed as a FileInfo - static void Main(int intOption = 42, bool boolOption = false, FileInfo fileOption = null) - { - Console.WriteLine($"The value for --int-option is: {intOption}"); - Console.WriteLine($"The value for --bool-option is: {boolOption}"); - Console.WriteLine($"The value for --file-option is: {fileOption?.FullName ?? "null"}"); - } -} -``` - -You're ready to run your program. - -```console -> dotnet run -- --int-option 123 -The value for --int-option is: 123 -The value for --bool-option is: False -The value for --file-option is: null -``` - -This program is equivalent to the one demonstrated in [Your first app with System.CommandLine](Your-first-app-with-System-CommandLine.md). - -To explore its features, take a look at [Features: overview](Features-overview.md) - diff --git a/docs/model-binding.md b/docs/model-binding.md deleted file mode 100644 index f6d8529b98..0000000000 --- a/docs/model-binding.md +++ /dev/null @@ -1,238 +0,0 @@ -# Model Binding - -_**This document describes System.CommandLine Beta 1. Some of the functionality described here now requires a separate package, [System.CommandLine.NamingConventionBinder](https://www.nuget.org/packages/System.CommandLine.NamingConventionBinder). For more details, please see [the Beta 2 announcement](https://github.com/dotnet/command-line-api/issues/1537).**_ - -Parsing command line arguments is a means to an end. You probably don't really want to think about parsing the command line. You just want some arguments passed to a method, based on some command line arguments. - -In C#, the application entry point method has always looked something like this: - -```cs -static void Main(string[] args) -{ -} -``` - -The goal of every command line parsing library is to turn the string array passed to `Main` into something more useful. You might ultimately want to call a method that looks like this: - -```cs -void Handle(int anInt) -{ -} -``` - -So for example, you might want an input `123` from the command line to be converted into an `int` with the value `123`. This conversion of command line input into variables or arguments that you can use in your code is called "binding." The term "model binding" refers to binding simple types as well as more complex types in order to pass the values to a method. - -# Binding parameters to a command handler - -The simplest way to bind command line input is to set the `Handler` property on a `Command`. The `System.CommandLine` model binder will look at the options and arguments for the command and attempt to match them to the parameters of the specified handler method. The default convention is that parameters are matched by name, so in the following example, option `--an-int` matches the parameter named `anInt`. Matching ignores hyphens (and other option prefixes, such as `'/'`) and is case insensitive. - -``` cs --source-file ./src/Binding/HandlerBindingSample.cs --project ./src/Binding/Binding.csproj --region MultipleArgs --session MultipleArgs -var command = new RootCommand - { - new Option("--a-string"), - new Option("--an-int") - }; - -command.Handler = CommandHandler.Create( - (string aString, int anInt) => - { - Console.WriteLine(aString); - Console.WriteLine(anInt); - }); - -await command.InvokeAsync("--an-int 123 --a-string \"Hello world!\" "); -``` - -``` console --session MultipleArgs -Hello world! -123 - -``` - -## Booleans (flags) - -If `true` or `false` is passed for an option having a `bool` argument, it is parsed and bound as expected. But an option whose argument type is `bool` doesn't require an argument to be specified. The presence of the option token on the command line, with no argument following it, results in a value of `true`. You can see various examples here: - -``` cs --source-file ./src/Binding/HandlerBindingSample.cs --project ./src/Binding/Binding.csproj --region Bool --session Bool -var command = new RootCommand - { - new Option("--a-bool") - }; - -command.Handler = CommandHandler.Create( - (bool aBool) => Console.WriteLine(aBool)); - -await command.InvokeAsync(""); -await command.InvokeAsync("--a-bool"); -await command.InvokeAsync("--a-bool false"); -await command.InvokeAsync("--a-bool true"); -``` - -``` console --session Bool -False -True -False -True - -``` - -## Enums - -You can bind `enum` types as well. The values are bound by name, and the binding is case insensitive: - -``` cs --source-file ./src/Binding/HandlerBindingSample.cs --project ./src/Binding/Binding.csproj --region Enum --session Enum -var command = new RootCommand - { - new Option("--an-enum") - }; - -command.Handler = CommandHandler.Create( - (FileAccess anEnum) => Console.WriteLine(anEnum)); - -await command.InvokeAsync("--an-enum Read"); -await command.InvokeAsync("--an-enum READ"); -``` - -``` console --session Enum -Read -Read - -``` - -## Arrays, lists, and other enumerable types - -Arguments having various enumerable types can be bound. A number of common types implementing `IEnumerable` are supported. In the next example, try changing the type of the `--items` `Option`'s `Argument` property to `Argument>` or `Argument>`. - -``` cs --source-file ./src/Binding/HandlerBindingSample.cs --project ./src/Binding/Binding.csproj --region Enumerables --session Enumerables -var command = new RootCommand - { - new Option("--items") - }; - -command.Handler = CommandHandler.Create( - (IEnumerable items) => - { - Console.WriteLine(items.GetType()); - - foreach (var item in items) - { - Console.WriteLine(item); - } - }); - -await command.InvokeAsync("--items one two three"); -``` - -``` console --session Enumerables -System.String[] -one -two -three - -``` - -## File system types - -Since command line applications very often have to work with the file system, `FileInfo` and `DirectoryInfo` are clearly important for binding to support. Run the following code, then try changing the generic type argument to `DirectoryInfo` and running it again. - -``` cs --source-file ./src/Binding/HandlerBindingSample.cs --project ./src/Binding/Binding.csproj --region FileSystemTypes --session FileSystemTypes -var command = new RootCommand - { - new Option("-f").ExistingOnly() - }; - -command.Handler = CommandHandler.Create( - (FileSystemInfo f) => - { - Console.WriteLine($"{f.GetType()}: {f}"); - }); - -await command.InvokeAsync("-f /path/to/something"); -``` - -``` console --session FileSystemTypes -Usage: - Binding [options] - -Options: - -f - --version Show version information - -?, -h, --help Show help and usage information - - -``` - -## Anything with a string constructor - -But `FileInfo` and `DirectoryInfo` are not special cases. Any type having a constructor that takes a single string parameter can be bound in this way. Go back to the previous example and try using a `Uri` instead. - -## More complex types - -Binding also supports creating instances of more complex types. If you have a large number of options, this can be cleaner than adding more parameters to your handler. `System.CommandLine` has the default convention of binding `Option` arguments to either properties or constructor parameters by name. The name matching uses the same strategies that are used when matching parameters on a handler method. - -In the next sample, the handler accepts an instance of `ComplexType`. Try removing its setters and uncommenting the constructor. Try adding properties, or changing the types or names of its properties. - -``` cs --source-file ./src/Binding/HandlerBindingSample.cs --project ./src/Binding/Binding.csproj --region ComplexTypes --session ComplexTypes -public static async Task ComplexTypes() -{ - var command = new Command("the-command") - { - new Option("--an-int"), - new Option("--a-string") - }; - - command.Handler = CommandHandler.Create( - (ComplexType complexType) => - { - Console.WriteLine(Format(complexType)); - }); - - await command.InvokeAsync("--an-int 123 --a-string 456"); - - return 0; -} - -public class ComplexType -{ - // public ComplexType(int anInt, string aString) - // { - // AnInt = anInt; - // AString = aString; - // } - public int AnInt { get; set; } - public string AString { get; set; } -} -``` - -``` console --session ComplexTypes -AnInt: 123 (System.Int32) -AString: 456 (System.String) - - -``` - -## System.CommandLine types - -Not everything you might want passed to your handler will necessarily come from parsed command line input. There are a number of types provided by `System.CommandLine` that you can bind to. The following example demonstratres injection of `ParseResult` and `IConsole`. Other types can be passed this way as well. - -``` cs --source-file ./src/Binding/HandlerBindingSample.cs --project ./src/Binding/Binding.csproj --region DependencyInjection --session DependencyInjection -var command = new RootCommand - { - new Option("--a-string"), - new Option("--an-int"), - new Option("--an-enum"), - }; - -command.Handler = CommandHandler.Create( - (ParseResult parseResult, IConsole console) => - { - console.Out.WriteLine($"{parseResult}"); - }); - -await command.InvokeAsync("--an-int 123 --a-string \"Hello world!\" --an-enum compressed"); -``` - -``` console --session DependencyInjection -ParseResult: [ Binding [ --an-int <123> ] [ --a-string ] [ --an-enum ] ] - -``` diff --git a/samples/DragonFruit/Directory.Build.props b/samples/DragonFruit/Directory.Build.props deleted file mode 100644 index e8d29aba95..0000000000 --- a/samples/DragonFruit/Directory.Build.props +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/samples/DragonFruit/Directory.Build.targets b/samples/DragonFruit/Directory.Build.targets deleted file mode 100644 index 11cba5d2e0..0000000000 --- a/samples/DragonFruit/Directory.Build.targets +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/samples/DragonFruit/DragonFruit.csproj b/samples/DragonFruit/DragonFruit.csproj deleted file mode 100644 index 573fefc2b8..0000000000 --- a/samples/DragonFruit/DragonFruit.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - Exe - $(TargetFrameworkForNETSDK) - true - - - - - - - diff --git a/samples/DragonFruit/Program.cs b/samples/DragonFruit/Program.cs deleted file mode 100644 index 0e6d2e432d..0000000000 --- a/samples/DragonFruit/Program.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; - -namespace DragonFruit -{ - class Program - { - /// - /// DragonFruit simple example program - /// - /// Show verbose output - /// Which flavor to use - /// How many smoothies? - static int Main( - bool verbose, - string flavor = "chocolate", - int count = 1) - { - if (verbose) - { - Console.WriteLine("Running in verbose mode"); - } - Console.WriteLine($"Creating {count} banana {(count == 1 ? "smoothie" : "smoothies")} with {flavor}"); - return 0; - } - } -} diff --git a/samples/HostingPlayground/Greeter.cs b/samples/HostingPlayground/Greeter.cs deleted file mode 100644 index 9dc6f335b9..0000000000 --- a/samples/HostingPlayground/Greeter.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace HostingPlayground -{ - public class Greeter : IGreeter - { - - } -} diff --git a/samples/HostingPlayground/GreeterOptions.cs b/samples/HostingPlayground/GreeterOptions.cs deleted file mode 100644 index ba56d27dfc..0000000000 --- a/samples/HostingPlayground/GreeterOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace HostingPlayground -{ - public class GreeterOptions - { - public string Name { get; } - - public GreeterOptions(string name) - { - Name = name; - } - } -} diff --git a/samples/HostingPlayground/HostingPlayground.csproj b/samples/HostingPlayground/HostingPlayground.csproj deleted file mode 100644 index 7781469899..0000000000 --- a/samples/HostingPlayground/HostingPlayground.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - Exe - $(TargetFrameworkForNETSDK) - true - $(NoWarn);CS1591 - - - - - - - - - diff --git a/samples/HostingPlayground/HostingPlaygroundLogEvents.cs b/samples/HostingPlayground/HostingPlaygroundLogEvents.cs deleted file mode 100644 index de4a513d6b..0000000000 --- a/samples/HostingPlayground/HostingPlaygroundLogEvents.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace HostingPlayground -{ - public class HostingPlaygroundLogEvents - { - public const int GreetEvent = 1000; - } -} diff --git a/samples/HostingPlayground/IGreeter.cs b/samples/HostingPlayground/IGreeter.cs deleted file mode 100644 index b5d737ee6e..0000000000 --- a/samples/HostingPlayground/IGreeter.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace HostingPlayground -{ - interface IGreeter - { - void Greet(string name) => Console.WriteLine($"Hello, {name ?? "anonymous"}"); - } -} diff --git a/samples/HostingPlayground/Program.cs b/samples/HostingPlayground/Program.cs deleted file mode 100644 index 4356ecb619..0000000000 --- a/samples/HostingPlayground/Program.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.CommandLine; -using System.CommandLine.Hosting; -using System.CommandLine.NamingConventionBinder; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using static HostingPlayground.HostingPlaygroundLogEvents; - -namespace HostingPlayground -{ - class Program - { - static Task Main(string[] args) => BuildCommandLine() - .UseHost(_ => Host.CreateDefaultBuilder(), - host => - { - host.ConfigureServices(services => - { - services.AddSingleton(); - }); - }) - .InvokeAsync(args); - - private static CommandLineConfiguration BuildCommandLine() - { - var root = new RootCommand(@"$ dotnet run --name 'Joe'"){ - new Option("--name"){ - Required = true - } - }; - root.Action = CommandHandler.Create(Run); - return new CommandLineConfiguration(root); - } - - private static void Run(GreeterOptions options, IHost host) - { - var serviceProvider = host.Services; - var greeter = serviceProvider.GetRequiredService(); - var loggerFactory = serviceProvider.GetRequiredService(); - var logger = loggerFactory.CreateLogger(typeof(Program)); - - var name = options.Name; - logger.LogInformation(GreetEvent, "Greeting was requested for: {name}", name); - greeter.Greet(name); - } - } -} diff --git a/samples/HostingPlayground/appsettings.json b/samples/HostingPlayground/appsettings.json deleted file mode 100644 index 7cb2ee756f..0000000000 --- a/samples/HostingPlayground/appsettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning" - } - } -} diff --git a/samples/RenderingPlayground/Colorizer.cs b/samples/RenderingPlayground/Colorizer.cs deleted file mode 100644 index c0d035975d..0000000000 --- a/samples/RenderingPlayground/Colorizer.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.CommandLine.Rendering; - -namespace RenderingPlayground -{ - internal static class Colorizer - { - public static TextSpan Underline(this string value) => - new ContainerSpan(StyleSpan.UnderlinedOn(), - new ContentSpan(value), - StyleSpan.UnderlinedOff()); - - - public static TextSpan Rgb(this string value, byte r, byte g, byte b) => - new ContainerSpan(ForegroundColorSpan.Rgb(r, g, b), - new ContentSpan(value), - ForegroundColorSpan.Reset()); - - public static TextSpan LightGreen(this string value) => - new ContainerSpan(ForegroundColorSpan.LightGreen(), - new ContentSpan(value), - ForegroundColorSpan.Reset()); - - public static TextSpan White(this string value) => - new ContainerSpan(ForegroundColorSpan.White(), - new ContentSpan(value), - ForegroundColorSpan.Reset()); - } -} diff --git a/samples/RenderingPlayground/ColorsView.cs b/samples/RenderingPlayground/ColorsView.cs deleted file mode 100644 index 97d532a275..0000000000 --- a/samples/RenderingPlayground/ColorsView.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.CommandLine.Rendering; -using System.CommandLine.Rendering.Views; - -namespace RenderingPlayground -{ - internal class ColorsView : View - { - public ColorsView(string text) - { - Text = text; - } - - private string Text { get; } - - public override Size Measure(ConsoleRenderer renderer, Size maxSize) => maxSize; - - public override void Render(ConsoleRenderer renderer, Region region) - { - byte r = 0; - byte g = 0; - byte b = 0; - - var i = 0; - - for (var x = 0; x < region.Width; x++) - for (var y = 0; y < region.Height; y++) - { - if (i >= Text.Length - 1) - { - i = 0; - } - else - { - i++; - } - - var subregion = new Region( - region.Left + x, - region.Top + y, - 1, - 1); - - unchecked - { - renderer.RenderToRegion( - $"{ForegroundColorSpan.Rgb(r += 2, g += 3, b += 5)}{Text[i]}{ForegroundColorSpan.Reset()}", - subregion); - } - } - } - } -} diff --git a/samples/RenderingPlayground/Directory.Build.props b/samples/RenderingPlayground/Directory.Build.props deleted file mode 100644 index ad29bdfb0d..0000000000 --- a/samples/RenderingPlayground/Directory.Build.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - diff --git a/samples/RenderingPlayground/Directory.Build.targets b/samples/RenderingPlayground/Directory.Build.targets deleted file mode 100644 index c1167dea6a..0000000000 --- a/samples/RenderingPlayground/Directory.Build.targets +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/samples/RenderingPlayground/DirectoryTableView.cs b/samples/RenderingPlayground/DirectoryTableView.cs deleted file mode 100644 index 6ab44d5a13..0000000000 --- a/samples/RenderingPlayground/DirectoryTableView.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.CommandLine.Rendering; -using System.CommandLine.Rendering.Views; -using System.IO; -using System.Linq; - -namespace RenderingPlayground -{ - internal class DirectoryTableView : StackLayoutView - { - public DirectoryTableView(DirectoryInfo directory) - { - if (directory == null) - { - throw new ArgumentNullException(nameof(directory)); - } - - Add(new ContentView("\n")); - Add(new ContentView(Span($"Directory: {directory.FullName.Rgb(235, 30, 180)}"))); - Add(new ContentView("\n")); - - var tableView = new TableView(); - - tableView.Items = directory.EnumerateFileSystemInfos() - .OrderByDescending(f => f is DirectoryInfo) - .ToList(); - - tableView.AddColumn( - cellValue: f => f is DirectoryInfo - ? f.Name.LightGreen() - : f.Name.White(), - header: new ContentView("Name".Underline())); - - tableView.AddColumn( - cellValue: f => Span(f.CreationTime), - header: new ContentView("Created".Underline())); - - tableView.AddColumn( - cellValue: f => Span(f.LastWriteTime), - header: new ContentView("Modified".Underline())); - - Add(tableView); - - Formatter.AddFormatter(d => $"{d:d} {ForegroundColorSpan.DarkGray()}{d:t}{ForegroundColorSpan.Reset()}"); - } - - TextSpan Span(FormattableString formattableString) - { - return Formatter.ParseToSpan(formattableString); - } - - TextSpan Span(object obj) - { - return Formatter.Format(obj); - } - - protected TextSpanFormatter Formatter { get; } = new TextSpanFormatter(); - } -} diff --git a/samples/RenderingPlayground/ProcessesView.cs b/samples/RenderingPlayground/ProcessesView.cs deleted file mode 100644 index 5cdacaa7e5..0000000000 --- a/samples/RenderingPlayground/ProcessesView.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System; -using System.Collections.Generic; -using System.CommandLine.Rendering; -using System.CommandLine.Rendering.Views; -using System.Diagnostics; -using System.Reactive.Linq; - -namespace RenderingPlayground -{ - internal class ProcessesView : StackLayoutView - { - public ProcessesView(Process[] processes) - { - var formatter = new TextSpanFormatter(); - formatter.AddFormatter(t => new ContentSpan(t.ToString(@"hh\:mm\:ss"))); - - Add(new ContentView("")); - Add(new ContentView("Processes")); - Add(new ContentView("")); - - var table = new TableView - { - Items = processes - }; - table.AddColumn(p => p.Id, new ContentView("PID".Underline())); - table.AddColumn(p => Name(p), new ContentView("COMMAND".Underline())); - table.AddColumn(p => p.PrivilegedProcessorTime, new ContentView("TIME".Underline())); - table.AddColumn(p => p.Threads.Count, new ContentView("#TH".Underline())); - table.AddColumn(p => p.PrivateMemorySize64.Abbreviate(), new ContentView("MEM".Underline())); - table.AddColumn(p => - { -#pragma warning disable CS0618 // Type or member is obsolete - var usage = p.TrackCpuUsage().First(); -#pragma warning restore CS0618 // Type or member is obsolete - return $"{usage.UsageTotal:P}"; - }, new ContentView("CPU".Underline())); - - - Add(table); - - FormattableString Name(Process p) - { - if (!p.Responding) - { - return $"{ForegroundColorSpan.Rgb(180, 0, 0)}{p.ProcessName}{ForegroundColorSpan.Reset()}"; - } - return $"{p.ProcessName}"; - } - } - } - - internal static class IntExtensions - { - private static readonly string[] _suffixes = { - "b", - "K", - "M", - "G", - "T" - }; - - public static string Abbreviate(this long value) - { - var i = 0; - var decimalValue = (decimal)value; - - while (Math.Round(decimalValue, 1) >= 1000) - { - decimalValue /= 1024; - i++; - } - - return $"{decimalValue:n1}{_suffixes[i]}"; - } - - public static DateTime StartTime = DateTime.UtcNow; - - public static IObservable TrackCpuUsage(this Process process) - { - var processorCount = Environment.ProcessorCount; - var trackingStartedAt = process.TotalProcessorTime; - var lastCheckedAt = DateTime.UtcNow; - var previousCpuTime = new TimeSpan(0); - - return Observable.ToObservable(GetTime()).Delay(TimeSpan.FromSeconds(1)).Repeat(); - - IEnumerable GetTime() - { - var currentCpuTime = process.TotalProcessorTime - trackingStartedAt; - - var usageSinceLastCheck = (currentCpuTime - previousCpuTime).TotalSeconds / - (processorCount * DateTime.UtcNow.Subtract(lastCheckedAt).TotalSeconds); - - var usageTotal = currentCpuTime.TotalSeconds / - (processorCount * DateTime.UtcNow.Subtract(StartTime).TotalSeconds); - - lastCheckedAt = DateTime.UtcNow; - - previousCpuTime = currentCpuTime; - - yield return new ProcessorTime(usageSinceLastCheck, usageTotal); - } - - //return Observable.Create(observer => - // { - // var currentCpuTime = process.TotalProcessorTime - trackingStartedAt; - // - // var usageSinceLastCheck = (currentCpuTime - previousCpuTime).TotalSeconds / - // (processorCount * DateTime.UtcNow.Subtract(lastCheckedAt).TotalSeconds); - // - // var usageTotal = currentCpuTime.TotalSeconds / - // (processorCount * DateTime.UtcNow.Subtract(StartTime).TotalSeconds); - // - // lastCheckedAt = DateTime.UtcNow; - // - // previousCpuTime = currentCpuTime; - // - // observer.OnNext(new ProcessorTime(usageSinceLastCheck, usageTotal)); - // - // return Disposable.Empty; - // }) - // .Concat(Observable.Empty().Delay(TimeSpan.FromSeconds(1))) - // .Repeat(); - } - } - - internal class ProcessorTime - { - public double UsageSinceLastCheck { get; } - public double UsageTotal { get; } - - public ProcessorTime(double usageSinceLastCheck, double usageTotal) - { - UsageSinceLastCheck = usageSinceLastCheck; - UsageTotal = usageTotal; - } - } -} diff --git a/samples/RenderingPlayground/Program.cs b/samples/RenderingPlayground/Program.cs deleted file mode 100644 index 8dbc429a87..0000000000 --- a/samples/RenderingPlayground/Program.cs +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.CommandLine; -using System.CommandLine.IO; -using System.CommandLine.Rendering; -using System.CommandLine.Rendering.Views; -using System.IO; -using System.Linq; -using System.Reactive.Subjects; -using Process = System.Diagnostics.Process; - -namespace RenderingPlayground -{ - class Program - { - /// - /// Demonstrates various rendering capabilities. - /// - /// - /// Renders a specified sample - /// The height of the rendering area - /// The width of the rendering area - /// The top position of the render area - /// The left position of the render area - /// The text to render - /// Overwrite the specified region. (If not, scroll.) - public static void Main( -#pragma warning disable CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do) - ParseResult parseResult, - SampleName sample = SampleName.Dir, - int? height = null, - int? width = null, - int top = 0, - int left = 0, - string text = null, - bool overwrite = true) -#pragma warning restore CS1573 // Parameter has no matching param tag in the XML comment (but other parameters do) - { - // Should this have a concrete reference to Console? - var region = new Region(left, - top, - width ?? Console.WindowWidth, - height ?? Console.WindowHeight, - overwrite); - - var console = new SystemConsole(); - - if (overwrite && - console is ITerminal terminal) - { - terminal.Clear(); - } - - var consoleRenderer = new ConsoleRenderer( - console, - mode: OutputMode.Auto, - resetAfterRender: true); - - switch (sample) - { - case SampleName.Colors: - { - var screen = new ScreenView(renderer: consoleRenderer, console); - screen.Child = new ColorsView(text ?? "*"); - - screen.Render(region); - } - break; - - case SampleName.Dir: - - var directoryTableView = new DirectoryTableView( - new DirectoryInfo(Directory.GetCurrentDirectory())); - - console.Append(directoryTableView); - - break; - - case SampleName.Moby: - consoleRenderer.RenderToRegion( - $"Call me {StyleSpan.BoldOn()}{StyleSpan.UnderlinedOn()}Ishmael{StyleSpan.UnderlinedOff()}{StyleSpan.BoldOff()}. Some years ago -- never mind how long precisely -- having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and {ForegroundColorSpan.Rgb(60, 0, 0)}methodically{ForegroundColorSpan.Reset()} {ForegroundColorSpan.Rgb(90, 0, 0)}knocking{ForegroundColorSpan.Reset()} {ForegroundColorSpan.Rgb(120, 0, 0)}people's{ForegroundColorSpan.Reset()} {ForegroundColorSpan.Rgb(160, 0, 0)}hats{ForegroundColorSpan.Reset()} {ForegroundColorSpan.Rgb(220, 0, 0)}off{ForegroundColorSpan.Reset()} then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball. With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising in this. If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings towards the ocean with me.", - region); - break; - - case SampleName.Processes: - { - var view = new ProcessesView(Process.GetProcesses()); - view.Render(consoleRenderer, region); - } - - break; - - case SampleName.TableView: - { - var table = new TableView - { - Items = Process.GetProcesses().Where(x => !string.IsNullOrEmpty(x.MainWindowTitle)).OrderBy(p => p.ProcessName).ToList() - }; - table.AddColumn(process => $"{process.ProcessName} ", "Name"); - table.AddColumn(process => ContentView.FromObservable(process.TrackCpuUsage(), x => $"{x.UsageTotal:P}"), "CPU", ColumnDefinition.Star(1)); - - var screen = new ScreenView(renderer: consoleRenderer, console) { Child = table }; - screen.Render(); - } - break; - - case SampleName.Clock: - { - var screen = new ScreenView(renderer: consoleRenderer, console); - var lastTime = DateTime.Now; - var clockObservable = new BehaviorSubject(lastTime); - var clockView = ContentView.FromObservable(clockObservable, x => $"{x:T}"); - screen.Child = clockView; - screen.Render(); - - while (!Console.KeyAvailable) - { - if (DateTime.Now - lastTime > TimeSpan.FromSeconds(1)) - { - lastTime = DateTime.Now; - clockObservable.OnNext(lastTime); - } - } - } - break; - - case SampleName.GridLayout: - { - var screen = new ScreenView(renderer: consoleRenderer, console); - var content = new ContentView( - "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum for Kevin."); - var smallContent = new ContentView("Kevin Bost"); - var longContent = new ContentView("Hacking on System.CommandLine"); - - var gridView = new GridView(); - gridView.SetColumns( - ColumnDefinition.SizeToContent(), - ColumnDefinition.Star(1), - ColumnDefinition.Star(0.5) - ); - gridView.SetRows( - RowDefinition.Star(0.5), - RowDefinition.Star(0.5) - ); - - gridView.SetChild(smallContent, 0, 0); - gridView.SetChild(longContent, 0, 1); - //gridView.SetChild(content, 0, 0); - gridView.SetChild(content, 1, 1); - gridView.SetChild(content, 2, 0); - - screen.Child = gridView; - - screen.Render(); - } - break; - - case SampleName.Cursor: - { - var gridView = new GridView(); - gridView.SetColumns(ColumnDefinition.SizeToContent()); - gridView.SetRows( - RowDefinition.SizeToContent(), - RowDefinition.Star(1) - ); - var content = new ContentView("Instructions:\n" + - $"DIRECTION ARROWS move the cursor; CTRL moves 2 instead of 1.\n" + - "PAGE UP/DOWN scrolls up/down.\n" + - "S saves the cursor position, R restores it.\n" + - "ENTER navigates to the start of the next line; CTRL moves 2 instead of 1.\n" + - "L moves to location (3, 9).\n" + - "ESC quits."); - gridView.SetChild(content, 0, 0); - gridView.SetChild(new ColorsView("#"), 0, 1); - - var screen = new ScreenView(renderer: consoleRenderer, console) - { - Child = gridView - }; - screen.Render(region); - - // move the cursor to the home position. - console.Out.Write($"{Ansi.Cursor.Move.ToUpperLeftCorner}"); - console.Out.Write($"{Ansi.Cursor.Show}"); - - // input seems not to be supported by the interfaces; how can this be got without using Console? - var key = Console.ReadKey(true); - - // This appears to be necessary to get the application to listen for *any* modifier key. - Console.TreatControlCAsInput = true; - while (key.Key != ConsoleKey.Escape) - { - var lines = !key.Modifiers.HasFlag(ConsoleModifiers.Control) ? default : 2; - switch (key.Key) - { - case ConsoleKey.DownArrow: - console.Out.Write($"{Ansi.Cursor.Move.Down(lines)}"); - break; - - case ConsoleKey.UpArrow: - console.Out.Write($"{Ansi.Cursor.Move.Up(lines)}"); - break; - - case ConsoleKey.RightArrow: - console.Out.Write($"{Ansi.Cursor.Move.Right(lines)}"); - break; - - case ConsoleKey.LeftArrow: - console.Out.Write($"{Ansi.Cursor.Move.Left(lines)}"); - break; - - case ConsoleKey.PageUp: - console.Out.Write($"{Ansi.Cursor.Scroll.DownOne}"); - break; - - case ConsoleKey.PageDown: - console.Out.Write($"{Ansi.Cursor.Scroll.UpOne}"); - break; - - case ConsoleKey.Enter: - console.Out.Write($"{Ansi.Cursor.Move.NextLine(lines)}"); - break; - - case ConsoleKey.S: - console.Out.Write($"{Ansi.Cursor.SavePosition}"); - break; - - case ConsoleKey.R: - console.Out.Write($"{Ansi.Cursor.RestorePosition}"); - break; - - case ConsoleKey.L: - console.Out.Write($"{Ansi.Cursor.Move.ToLocation(3, 9)}"); - break; - - case ConsoleKey.C: - if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) - { - // mimic the standard CTRL+C behaviour. - Environment.Exit(1); - } - - break; - } - - key = Console.ReadKey(true); - } - } - - // reset the screen and cursor. - console.GetTerminal().Clear(); - console.Out.Write($"{Ansi.Cursor.Move.ToUpperLeftCorner}"); - - return; - - default: - if (!string.IsNullOrWhiteSpace(text)) - { - consoleRenderer.RenderToRegion( - text, - region); - } - else - { - var screen = new ScreenView(renderer: consoleRenderer, console); - var stackLayout = new StackLayoutView(); - var content1 = new ContentView("Hello World!"); - var content2 = new ContentView( - "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum for Kevin."); - stackLayout.Add(content2); - stackLayout.Add(content1); - stackLayout.Add(content2); - screen.Child = stackLayout; - screen.Render(new Region(0, 0, 50, Size.MaxValue)); - //screen.Render(writer); - } - - break; - } - - if (!Console.IsOutputRedirected) - { - Console.ReadKey(); - } - } - - private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e) - { - throw new NotImplementedException(); - } - } -} diff --git a/samples/RenderingPlayground/RenderingPlayground.csproj b/samples/RenderingPlayground/RenderingPlayground.csproj deleted file mode 100644 index 8f7041b185..0000000000 --- a/samples/RenderingPlayground/RenderingPlayground.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - Exe - $(TargetFrameworkForNETSDK) - true - - - - - - - - - - - - diff --git a/samples/RenderingPlayground/SampleName.cs b/samples/RenderingPlayground/SampleName.cs deleted file mode 100644 index ff2567a076..0000000000 --- a/samples/RenderingPlayground/SampleName.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace RenderingPlayground -{ - internal enum SampleName - { - Colors, - Dir, - Moby, - Processes, - TableView, - Clock, - GridLayout, - Cursor, - } -} diff --git a/sourcebuild.slnf b/sourcebuild.slnf index dc155a4d4e..ba1ca0a8c3 100644 --- a/sourcebuild.slnf +++ b/sourcebuild.slnf @@ -3,9 +3,6 @@ "path": "System.CommandLine.sln", "projects": [ "src\\System.CommandLine\\System.CommandLine.csproj", - "src\\System.CommandLine.DragonFruit\\System.CommandLine.DragonFruit.csproj", - "src\\System.CommandLine.NamingConventionBinder\\System.CommandLine.NamingConventionBinder.csproj", - "src\\System.CommandLine.Rendering\\System.CommandLine.Rendering.csproj" ] } } \ No newline at end of file diff --git a/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_Hosting_api_is_not_changed.approved.txt b/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_Hosting_api_is_not_changed.approved.txt deleted file mode 100644 index e09e960373..0000000000 --- a/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_Hosting_api_is_not_changed.approved.txt +++ /dev/null @@ -1,20 +0,0 @@ -System.CommandLine.Hosting - public static class HostingExtensions - public static OptionsBuilder BindCommandLine(this OptionsBuilder optionsBuilder) - public static Microsoft.Extensions.Hosting.IHost GetHost(this System.CommandLine.ParseResult parseResult) - public static System.CommandLine.ParseResult GetParseResult(this Microsoft.Extensions.Hosting.IHostBuilder hostBuilder) - public static System.CommandLine.ParseResult GetParseResult(this Microsoft.Extensions.Hosting.HostBuilderContext context) - public static System.CommandLine.Command UseCommandHandler(this System.CommandLine.Command command) - public static System.CommandLine.CommandLineConfiguration UseHost(this System.CommandLine.CommandLineConfiguration config, System.Action configureHost = null) - public static System.CommandLine.CommandLineConfiguration UseHost(this System.CommandLine.CommandLineConfiguration config, System.Func hostBuilderFactory, System.Action configureHost = null) - public static Microsoft.Extensions.Hosting.IHostBuilder UseInvocationLifetime(this Microsoft.Extensions.Hosting.IHostBuilder host, System.Action configureOptions = null) - public class InvocationLifetime, Microsoft.Extensions.Hosting.IHostLifetime - .ctor(Microsoft.Extensions.Options.IOptions options, Microsoft.Extensions.Hosting.IHostEnvironment environment, Microsoft.Extensions.Hosting.IHostApplicationLifetime applicationLifetime, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory = null) - public Microsoft.Extensions.Hosting.IHostApplicationLifetime ApplicationLifetime { get; } - public Microsoft.Extensions.Hosting.IHostEnvironment Environment { get; } - public InvocationLifetimeOptions Options { get; } - public System.Void Dispose() - public System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken) - public System.Threading.Tasks.Task WaitForStartAsync(System.Threading.CancellationToken cancellationToken) - public class InvocationLifetimeOptions : Microsoft.Extensions.Hosting.ConsoleLifetimeOptions - .ctor() diff --git a/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_NamingConventionBinder_api_is_not_changed.approved.txt b/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_NamingConventionBinder_api_is_not_changed.approved.txt deleted file mode 100644 index 722203167a..0000000000 --- a/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_NamingConventionBinder_api_is_not_changed.approved.txt +++ /dev/null @@ -1,145 +0,0 @@ -System.CommandLine.Binding - public class BindingContext, System.IServiceProvider - public System.CommandLine.ParseResult ParseResult { get; } - public System.Void AddService(System.Type serviceType, System.Func factory) - public System.Void AddService(Func factory) - public System.Object GetService(System.Type serviceType) - public struct BoundValue : System.ValueType - public System.Object Value { get; } - public IValueDescriptor ValueDescriptor { get; } - public IValueSource ValueSource { get; } - public System.String ToString() - public interface IValueDescriptor - public System.Boolean HasDefaultValue { get; } - public System.String ValueName { get; } - public System.Type ValueType { get; } - public System.Object GetDefaultValue() - public interface IValueSource - public System.Boolean TryGetValue(IValueDescriptor valueDescriptor, BindingContext bindingContext, ref System.Object& boundValue) -System.CommandLine.NamingConventionBinder - public static class BindingContextExtensions - public static System.Void AddModelBinder(this System.CommandLine.Binding.BindingContext bindingContext, ModelBinder binder) - public static System.CommandLine.Binding.BindingContext GetBindingContext(this System.CommandLine.ParseResult parseResult) - public static ModelBinder GetOrCreateModelBinder(this System.CommandLine.Binding.BindingContext bindingContext, System.CommandLine.Binding.IValueDescriptor valueDescriptor) - public abstract class BindingHandler : System.CommandLine.Invocation.AsynchronousCommandLineAction - public System.CommandLine.Binding.BindingContext GetBindingContext(System.CommandLine.ParseResult parseResult) - public static class CommandHandler - public static BindingHandler Create(System.Delegate delegate) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Action action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(Func> action) - public static BindingHandler Create(System.Reflection.MethodInfo method, System.Object target = null) - public class ConstructorDescriptor, IMethodDescriptor - public System.Collections.Generic.IReadOnlyList ParameterDescriptors { get; } - public ModelDescriptor Parent { get; } - public System.String ToString() - public abstract class HandlerDescriptor, IMethodDescriptor - public static HandlerDescriptor FromDelegate(System.Delegate delegate) - public static HandlerDescriptor FromMethodInfo(System.Reflection.MethodInfo methodInfo, System.Object target = null) - public System.Collections.Generic.IReadOnlyList ParameterDescriptors { get; } - public ModelDescriptor Parent { get; } - public BindingHandler GetCommandHandler() - public System.String ToString() - public interface IMethodDescriptor - public System.Collections.Generic.IReadOnlyList ParameterDescriptors { get; } - public ModelDescriptor Parent { get; } - public class ModelBinder - .ctor(System.Type modelType) - public System.Boolean EnforceExplicitBinding { get; set; } - public ModelDescriptor ModelDescriptor { get; } - public System.CommandLine.Binding.IValueDescriptor ValueDescriptor { get; } - public System.Void BindMemberFromValue(System.Reflection.PropertyInfo property, System.CommandLine.Symbol symbol) - public System.Object CreateInstance(System.CommandLine.Binding.BindingContext bindingContext) - public System.Void UpdateInstance(T instance, System.CommandLine.Binding.BindingContext bindingContext) - public class ModelBinder : ModelBinder - .ctor() - public System.Void BindMemberFromValue(Expression> property, System.CommandLine.Symbol symbol) - public System.Void BindMemberFromValue(Expression> property, Func getValue) - public class ModelBindingCommandHandler : BindingHandler - public System.Void BindParameter(System.Reflection.ParameterInfo param, System.CommandLine.Argument argument) - public System.Void BindParameter(System.Reflection.ParameterInfo param, System.CommandLine.Option option) - public System.Threading.Tasks.Task InvokeAsync(System.CommandLine.ParseResult parseResult, System.Threading.CancellationToken cancellationToken = null) - public class ModelDescriptor - public static ModelDescriptor FromType() - public static ModelDescriptor FromType(System.Type type) - public System.Collections.Generic.IReadOnlyList ConstructorDescriptors { get; } - public System.Type ModelType { get; } - public System.Collections.Generic.IReadOnlyList PropertyDescriptors { get; } - public System.String ToString() - public class ParameterDescriptor, System.CommandLine.Binding.IValueDescriptor - public System.Boolean AllowsNull { get; } - public System.Boolean HasDefaultValue { get; } - public IMethodDescriptor Parent { get; } - public System.String ValueName { get; } - public System.Type ValueType { get; } - public System.Object GetDefaultValue() - public System.String ToString() - public class PropertyDescriptor, System.CommandLine.Binding.IValueDescriptor - public System.Boolean HasDefaultValue { get; } - public ModelDescriptor Parent { get; } - public System.String ValueName { get; } - public System.Type ValueType { get; } - public System.Object GetDefaultValue() - public System.Void SetValue(System.Object instance, System.Object value) - public System.String ToString() diff --git a/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.cs b/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.cs index b413bf2120..0e0a21633c 100644 --- a/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.cs +++ b/src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.CommandLine.Hosting; -using System.CommandLine.NamingConventionBinder; using ApprovalTests; using ApprovalTests.Reporters; using Xunit; @@ -18,20 +16,4 @@ public void System_CommandLine_api_is_not_changed() var contract = ApiContract.GenerateContractForAssembly(typeof(ParseResult).Assembly); Approvals.Verify(contract); } - - [Fact] - [UseReporter(typeof(DiffReporter))] - public void System_CommandLine_Hosting_api_is_not_changed() - { - var contract = ApiContract.GenerateContractForAssembly(typeof(HostingExtensions).Assembly); - Approvals.Verify(contract); - } - - [Fact] - [UseReporter(typeof(DiffReporter))] - public void System_CommandLine_NamingConventionBinder_api_is_not_changed() - { - var contract = ApiContract.GenerateContractForAssembly(typeof(ModelBindingCommandHandler).Assembly); - Approvals.Verify(contract); - } } \ No newline at end of file diff --git a/src/System.CommandLine.ApiCompatibility.Tests/System.CommandLine.ApiCompatibility.Tests.csproj b/src/System.CommandLine.ApiCompatibility.Tests/System.CommandLine.ApiCompatibility.Tests.csproj index 670b1d0361..b69badcf7c 100644 --- a/src/System.CommandLine.ApiCompatibility.Tests/System.CommandLine.ApiCompatibility.Tests.csproj +++ b/src/System.CommandLine.ApiCompatibility.Tests/System.CommandLine.ApiCompatibility.Tests.csproj @@ -10,8 +10,6 @@ - - diff --git a/src/System.CommandLine.Benchmarks/DragonFruit/Perf_CommandLine_EntryPoint.cs b/src/System.CommandLine.Benchmarks/DragonFruit/Perf_CommandLine_EntryPoint.cs deleted file mode 100644 index 6bf11881ac..0000000000 --- a/src/System.CommandLine.Benchmarks/DragonFruit/Perf_CommandLine_EntryPoint.cs +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.Collections.Generic; -using System.CommandLine.Benchmarks.Helpers; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using BenchmarkDotNet.Attributes; - -namespace System.CommandLine.Benchmarks.DragonFruit -{ - /// - /// This is an end-to-end benchmark that measures the performance of - /// - /// including the execution of Main method per se. - /// - [BenchmarkCategory(Categories.DragonFruit)] - [InvocationCount(3000)] - public class Perf_CommandLine_EntryPoint - { - private Assembly _testAssembly; - private string _testAssemblyFilePath; - private string _testAssemblyXmlDocsFilePath; - - /// - /// For classesCount == 2, methodsPerClassCount == 3 will return: - /// - /// namespace PerfTestApp - /// { - /// public class ABCClass_0 - /// { - /// public int Method_0() { return 0; } - /// public int Method_1() { return 0; } - /// public int Method_2() { return 0; } - /// } - /// - /// public class ABCClass_1 - /// { - /// public int Method_0() { return 0; } - /// ... - /// public int Method_2() { return 0; } - /// } - /// } - /// - /// namespace PerfTestApp - /// { - /// internal class Program - /// { - /// - /// User defined entry point. - /// - /// .... - /// static int Main(int p1, string p2, bool p3) { return 0; } - /// } - /// } - /// - /// > - private string GenerateTestAssemblySourceCode( - int classesCount, - int methodsPerClassCount, - string classNamePrefix = "ABCClass", - string methodNamePrefix = "Method" - ) - { - IEnumerable testMethodsCodeSnapshot = - Enumerable - .Range(0, methodsPerClassCount) - .Select(i => $"public int {methodNamePrefix}_{i}() {{ return 0; }} "); - - IEnumerable testClassesCodeSnapshot = - Enumerable - .Range(0, classesCount) - .Select(i => - "namespace PerfTestApp { " + - $"public class {classNamePrefix}_{i} {{ {string.Concat(testMethodsCodeSnapshot)} }} " + - "} \n"); - - string entryPointCodeSnapshot = - @"namespace PerfTestApp { - internal class Program { - - /// - /// Entry point summary... - /// - /// .... - /// .... - /// .... - static int Main(int p1, string p2, bool p3) { return 0; } - } - } - "; - - return string.Concat(testClassesCodeSnapshot) + entryPointCodeSnapshot; - } - - private string CreateTestAssemblyInTempFile(int classesCount, int methodsPerClassCount) - { - string testSourceCode = GenerateTestAssemblySourceCode(classesCount, methodsPerClassCount); - return Utils.CreateTestAssemblyInTempFileFromString(testSourceCode, - new[] - { - typeof(object).GetTypeInfo().Assembly.Location, - typeof(Enumerable).GetTypeInfo().Assembly.Location, - }); - } - - public IEnumerable<(int classesCount, int methodsPerClassCount)> ValuesForTestAssemblySize - => new[] { - (classesCount: 1, methodsPerClassCount: 1), - (classesCount: 10, methodsPerClassCount: 10), - (classesCount: 100, methodsPerClassCount: 100) - }; - - [ParamsSource(nameof(ValuesForTestAssemblySize))] - public (int classesCount, int methodsPerClassCount) TestAssemblySize; - - [GlobalSetup] - public void Setup() - { - _testAssemblyFilePath = CreateTestAssemblyInTempFile( - TestAssemblySize.classesCount, - TestAssemblySize.methodsPerClassCount); - - _testAssembly = Assembly.Load(File.ReadAllBytes(_testAssemblyFilePath)); - _testAssemblyXmlDocsFilePath = _testAssemblyFilePath.Replace(".dll", ".xml"); - } - - [Benchmark(Description = "ExecuteAssemblyAsync entry point search.")] - public Task SearchForStartingPointUsingReflection() - => System.CommandLine.DragonFruit.CommandLine.ExecuteAssemblyAsync( - _testAssembly, - new string[] { }, - null, - _testAssemblyXmlDocsFilePath); - - [Benchmark(Description = "ExecuteAssemblyAsync explicit entry point.")] - public Task SearchForStartingPointWhenGivenEntryPointClass() - => System.CommandLine.DragonFruit.CommandLine.ExecuteAssemblyAsync( - _testAssembly, - new string[] { }, - "PerfTestApp.Program", - _testAssemblyXmlDocsFilePath); - - [GlobalCleanup] - public void Cleanup() - { - File.Delete(_testAssemblyFilePath); - File.Delete(_testAssemblyXmlDocsFilePath); - } - } -} diff --git a/src/System.CommandLine.Benchmarks/DragonFruit/Perf_CommandLine_Help.cs b/src/System.CommandLine.Benchmarks/DragonFruit/Perf_CommandLine_Help.cs deleted file mode 100644 index 0723941cd5..0000000000 --- a/src/System.CommandLine.Benchmarks/DragonFruit/Perf_CommandLine_Help.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.CommandLine.Benchmarks.Helpers; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using BenchmarkDotNet.Attributes; - -namespace System.CommandLine.Benchmarks.DragonFruit -{ - /// - /// This is an end-to-end benchmark that measures the performance of --help option. - /// - [BenchmarkCategory(Categories.DragonFruit)] - [InvocationCount(3000)] - public class Perf_CommandLine_Help - { - private Assembly _testAssembly; - private string _testAssemblyFilePath; - private string _testAssemblyXmlDocsFilePath; - - [GlobalSetup] - public void Setup() - { - _testAssemblyFilePath = Utils.CreateTestAssemblyInTempFileFromFile( - "Sample1.Main.cs", - new[] - { - typeof(object).GetTypeInfo().Assembly.Location, - typeof(Enumerable).GetTypeInfo().Assembly.Location, - typeof(System.CommandLine.ParseResult).GetTypeInfo().Assembly.Location - } - ); - _testAssembly = Assembly.Load(File.ReadAllBytes(_testAssemblyFilePath)); - _testAssemblyXmlDocsFilePath = _testAssemblyFilePath.Replace(".dll", ".xml"); - } - - [Benchmark(Description = "--help")] - public Task SearchForStartingPointWhenGivenEntryPointClass_Help() - => System.CommandLine.DragonFruit.CommandLine.ExecuteAssemblyAsync( - _testAssembly, - new[] { "--help" }, - null, - _testAssemblyXmlDocsFilePath); - - [GlobalCleanup] - public void Cleanup() - { - File.Delete(_testAssemblyFilePath); - File.Delete(_testAssemblyXmlDocsFilePath); - } - } -} diff --git a/src/System.CommandLine.Benchmarks/DragonFruit/Perf_XmlDocReader.cs b/src/System.CommandLine.Benchmarks/DragonFruit/Perf_XmlDocReader.cs deleted file mode 100644 index ffcd65615c..0000000000 --- a/src/System.CommandLine.Benchmarks/DragonFruit/Perf_XmlDocReader.cs +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.CommandLine.Benchmarks.Helpers; -using System.CommandLine.DragonFruit; -using System.IO; -using System.Linq; -using System.Reflection; -using BenchmarkDotNet.Attributes; - -namespace System.CommandLine.Benchmarks.DragonFruit -{ - /// - /// Measures performance of initializing symbol descriptions from xml comments. - /// - /// - [BenchmarkCategory(Categories.DragonFruit)] - public class Perf_XmlDocReader - { - private readonly string _testAssemblyFilePath; - private readonly string _testAssemblyXmlDocsFilePath; - private readonly MethodInfo _mainMethodInfo; - private readonly StreamReader _xmlDocsStreamReader; - private XmlDocReader _xmlDocReaderSample1; - - public Perf_XmlDocReader() - { - _testAssemblyFilePath = Utils.CreateTestAssemblyInTempFileFromFile( - "Sample1.Main.cs", - new[] - { - typeof(object).GetTypeInfo().Assembly.Location, - typeof(Enumerable).GetTypeInfo().Assembly.Location, - typeof(ParseResult).GetTypeInfo().Assembly.Location - } - ); - - _testAssemblyXmlDocsFilePath = _testAssemblyFilePath.Replace(".dll", ".xml"); - - var testAssembly = Assembly.Load(File.ReadAllBytes(_testAssemblyFilePath)); - - _mainMethodInfo = testAssembly - .GetType("RenderingPlayground.Program", false, false) - .GetTypeInfo() - .GetDeclaredMethod("Main"); - - _xmlDocsStreamReader = new StreamReader( - new MemoryStream(File.ReadAllBytes(_testAssemblyXmlDocsFilePath) - ) - ); - } - - [Benchmark] - public XmlDocReader TryLoad_Sample1() - { - // I experienced problems with [IterationSetup]/[IterationCleanup] - // https://github.com/dotnet/BenchmarkDotNet/issues/1127 - // So I have ended up placing it here for now - _xmlDocsStreamReader.BaseStream.Seek(0, SeekOrigin.Begin); - // - XmlDocReader.TryLoad(_xmlDocsStreamReader, out var docReader); - return docReader; - } - - [GlobalSetup(Target = nameof(TryGetMethodDescription_Sample1))] - public void SetupTryGetMethodDescription_Sample1() - { - _xmlDocReaderSample1 = TryLoad_Sample1(); - } - - [Benchmark] - public CommandHelpMetadata TryGetMethodDescription_Sample1() - { - // I experienced problems with [IterationSetup]/[IterationCleanup] - // https://github.com/dotnet/BenchmarkDotNet/issues/1127 - // So I have ended up placing it here for now - _xmlDocsStreamReader.BaseStream.Seek(0, SeekOrigin.Begin); - // - _xmlDocReaderSample1.TryGetMethodDescription(_mainMethodInfo, out var helpMetadata); - return helpMetadata; - } - - [GlobalCleanup] - public void Cleanup() - { - _xmlDocsStreamReader.Close(); - File.Delete(_testAssemblyFilePath); - File.Delete(_testAssemblyXmlDocsFilePath); - } - } -} diff --git a/src/System.CommandLine.Benchmarks/System.CommandLine.Benchmarks.csproj b/src/System.CommandLine.Benchmarks/System.CommandLine.Benchmarks.csproj index cf5e9701f6..c8f464cf2b 100644 --- a/src/System.CommandLine.Benchmarks/System.CommandLine.Benchmarks.csproj +++ b/src/System.CommandLine.Benchmarks/System.CommandLine.Benchmarks.csproj @@ -37,7 +37,6 @@ - diff --git a/src/System.CommandLine.DragonFruit.Tests/CommandLineTests.cs b/src/System.CommandLine.DragonFruit.Tests/CommandLineTests.cs deleted file mode 100644 index a2c1799c21..0000000000 --- a/src/System.CommandLine.DragonFruit.Tests/CommandLineTests.cs +++ /dev/null @@ -1,255 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.IO; -using System.Threading.Tasks; -using FluentAssertions; -using Xunit; - -namespace System.CommandLine.DragonFruit.Tests -{ - public class CommandLineTests - { - private readonly TestProgram _testProgram; - - public CommandLineTests() - { - _testProgram = new TestProgram(); - } - - [Fact] - public async Task It_executes_method_with_string_option() - { - StringWriter output = new(); - int exitCode = await CommandLine.InvokeMethodAsync( - new[] { "--name", "Wayne" }, - TestProgram.TestMainMethodInfoWithoutPara, - null, - _testProgram, - output); - exitCode.Should().Be(0); - output.ToString().Should().Be("Wayne"); - } - - [Fact] - public void It_executes_method_synchronously_with_string_option() - { - StringWriter output = new(); - int exitCode = CommandLine.InvokeMethod( - new[] { "--name", "Wayne" }, - TestProgram.TestMainMethodInfoWithoutPara, - null, - _testProgram, - output); - exitCode.Should().Be(0); - output.ToString().Should().Be("Wayne"); - } - - [Fact] - public async Task It_shows_help_text_based_on_XML_documentation_comments() - { - StringWriter output = new(); - int exitCode = await CommandLine.InvokeMethodAsync( - new[] { "--help" }, - TestProgram.TestMainMethodInfoWithoutPara, - null, - _testProgram, - output); - - exitCode.Should().Be(0); - - var stdOut = output.ToString(); - - stdOut.Should() - .Contain(" These are arguments") - .And.Contain("Arguments:"); - stdOut.Should() - .ContainAll("--name", "Specifies the name option") - .And.Contain("Options:"); - stdOut.Should() - .Contain($"Description:{Environment.NewLine} Normal summary"); - } - - [Fact] - public async Task When_XML_documentation_comment_contains_a_para_tag_then_help_is_written_with_a_newline() - { - StringWriter output = new(); - int exitCode = await CommandLine.InvokeMethodAsync( - new[] { "--help" }, - TestProgram.TestMainMethodInfoWithPara, - null, - _testProgram, - output); - - exitCode.Should().Be(0); - - var stdOut = output.ToString(); - - stdOut.Should() - .Contain(" These are arguments") - .And.Contain("Arguments:"); - stdOut.Should() - .ContainAll("--name", "Specifies the name option") - .And.Contain("Options:"); - stdOut.Should() - .Contain($"Description:{Environment.NewLine} Help for the test program{Environment.NewLine} More help for the test program{Environment.NewLine}"); - } - - [Fact] - public async Task When_XML_documentation_comment_contains_a_para_tag_and_some_text_then_help_skips_text_outside_para_tag() - { - StringWriter output = new(); - int exitCode = await CommandLine.InvokeMethodAsync( - new[] { "--help" }, - TestProgram.TestMainMethodInfoWithTextAndPara, - null, - _testProgram, - output); - - exitCode.Should().Be(0); - - var stdOut = output.ToString(); - - stdOut.Should() - .Contain(" These are arguments") - .And.Contain("Arguments:"); - stdOut.Should() - .ContainAll("--name", "Specifies the name option") - .And.Contain("Options:"); - stdOut.Should() - .Contain($"Description:{Environment.NewLine} Help for the test program{Environment.NewLine} More help for the test program{Environment.NewLine}"); - } - - [Fact] - public void It_synchronously_shows_help_text_based_on_XML_documentation_comments() - { - StringWriter output = new(); - int exitCode = CommandLine.InvokeMethod( - new[] { "--help" }, - TestProgram.TestMainMethodInfoWithDefault, - null, - _testProgram, - output); - - exitCode.Should().Be(0); - - var stdOut = output.ToString(); - - stdOut.Should() - .ContainAll("--name","name [default: Bruce]") - .And.Contain("Options:"); - } - - [Fact] - public async Task It_executes_method_with_string_option_with_default() - { - StringWriter output = new(); - int exitCode = await CommandLine.InvokeMethodAsync( - Array.Empty(), - TestProgram.TestMainMethodInfoWithDefault, - null, - _testProgram, - output); - - exitCode.Should().Be(0); - output.ToString().Should().Be("Bruce"); - } - - [Fact] - public void It_executes_method_synchronously_with_string_option_with_default() - { - StringWriter output = new(); - int exitCode = CommandLine.InvokeMethod( - Array.Empty(), - TestProgram.TestMainMethodInfoWithDefault, - null, - _testProgram, - output); - - exitCode.Should().Be(0); - output.ToString().Should().Be("Bruce"); - } - - private void TestMainThatThrows() => throw new InvalidOperationException("This threw an error"); - - [Fact] - public async Task It_shows_error_without_invoking_method() - { - Action action = TestMainThatThrows; - - StringWriter error = new(); - int exitCode = await CommandLine.InvokeMethodAsync( - new[] { "--unknown" }, - action.Method, - null, - this, - standardError: error); - - exitCode.Should().Be(1); - error.ToString() - .Should().NotBeEmpty() - .And - .Contain("--unknown"); - } - - [Fact] - public void It_shows_error_without_invoking_method_synchronously() - { - Action action = TestMainThatThrows; - - StringWriter error = new(); - int exitCode = CommandLine.InvokeMethod( - new[] { "--unknown" }, - action.Method, - null, - this, - standardError: error); - - exitCode.Should().Be(1); - error.ToString() - .Should().NotBeEmpty() - .And - .Contain("--unknown"); - } - - [Fact] - public async Task It_handles_uncaught_exceptions() - { - Action action = TestMainThatThrows; - - StringWriter error = new(); - int exitCode = await CommandLine.InvokeMethodAsync( - Array.Empty(), - action.Method, - null, - this, - standardError: error); - - exitCode.Should().Be(1); - error.ToString() - .Should().NotBeEmpty() - .And - .Contain("This threw an error"); - } - - [Fact] - public void It_handles_uncaught_exceptions_synchronously() - { - Action action = TestMainThatThrows; - - StringWriter error = new(); - int exitCode = CommandLine.InvokeMethod( - Array.Empty(), - action.Method, - null, - this, - standardError: error); - - exitCode.Should().Be(1); - error.ToString() - .Should().NotBeEmpty() - .And - .Contain("This threw an error"); - } - } -} diff --git a/src/System.CommandLine.DragonFruit.Tests/ConfigureFromMethodTests.cs b/src/System.CommandLine.DragonFruit.Tests/ConfigureFromMethodTests.cs deleted file mode 100644 index bfa187d910..0000000000 --- a/src/System.CommandLine.DragonFruit.Tests/ConfigureFromMethodTests.cs +++ /dev/null @@ -1,308 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.CommandLine.Binding; -using System.CommandLine.Tests.Binding; -using System.CommandLine.Tests.Utility; -using System.IO; -using FluentAssertions; -using System.Linq; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using Xunit; - -namespace System.CommandLine.DragonFruit.Tests -{ - public class ConfigureFromMethodTests - { - private object[] _receivedValues; - - [Fact] - public async Task Generated_boolean_parameters_will_accept_zero_arguments() - { - var config = new CommandLineConfiguration(new RootCommand()) - .ConfigureRootCommandFromMethod( - GetMethodInfo(nameof(Method_taking_bool)), this); - config.Output = TextWriter.Null; - - await config.InvokeAsync($"{RootCommand.ExecutableName} --value"); - - _receivedValues.Should().BeEquivalentTo(new object[] { true }); - } - - [Theory] - [InlineData("--value true", true)] - [InlineData("--value false", false)] - [InlineData("--value:true", true)] - [InlineData("--value:false", false)] - [InlineData("--value=true", true)] - [InlineData("--value=false", false)] - public async Task Generated_boolean_parameters_will_accept_one_argument(string commandLine, bool expected) - { - var config = new CommandLineConfiguration(new RootCommand()) - .ConfigureRootCommandFromMethod( - GetMethodInfo(nameof(Method_taking_bool)), this); - config.Output = TextWriter.Null; - - await config.InvokeAsync(commandLine); - - _receivedValues.Should().BeEquivalentTo(new [] { expected }); - } - - [Fact] - public async Task Single_character_parameters_generate_aliases_that_accept_a_single_dash_prefix() - { - var config = new CommandLineConfiguration(new RootCommand()) - .ConfigureRootCommandFromMethod( - GetMethodInfo(nameof(Method_with_single_letter_parameters)), this); - config.Output = TextWriter.Null; - - await config.InvokeAsync("-x 123 -y 456"); - - _receivedValues.Should() - .BeEquivalentSequenceTo(123, 456); - } - - [Theory] - [InlineData(nameof(Method_having_string_argument), 1, 1)] - [InlineData(nameof(Method_having_string_argument_with_null_default_value), 0, 1)] - [InlineData(nameof(Method_having_string_argument_with_non_null_default_value), 0, 1)] - [InlineData(nameof(Method_having_string_array_arguments), 0, 100_000)] - [InlineData(nameof(Method_having_string_array_arguments_with_default_value), 0, 100_000)] - [InlineData(nameof(Method_having_FileInfo_argument), 1, 1)] - [InlineData(nameof(Method_having_FileInfo_argument_with_default_value), 0, 1)] - [InlineData(nameof(Method_having_FileInfo_array_args), 0, 100_000)] - public void Parameters_named_arguments_generate_command_arguments_having_the_correct_arity( - string methodName, - int minNumberOfValues, - int maxNumberOfValues) - { - var config = new CommandLineConfiguration(new RootCommand()) - .ConfigureRootCommandFromMethod(GetMethodInfo(methodName)); - - var rootCommandArgument = config.RootCommand.Arguments.Single(); - - rootCommandArgument.Arity - .Should() - .BeEquivalentTo(new ArgumentArity(minNumberOfValues, maxNumberOfValues)); - } - - [Theory] - [InlineData(nameof(Method_having_string_argument), "argument")] - [InlineData(nameof(Method_having_string_argument_with_null_default_value), "argument")] - [InlineData(nameof(Method_having_string_array_arguments), "arguments")] - [InlineData(nameof(Method_having_string_array_arguments_with_default_value), "arguments")] - [InlineData(nameof(Method_having_FileInfo_argument), "argument")] - [InlineData(nameof(Method_having_FileInfo_argument_with_default_value), "argument")] - [InlineData(nameof(Method_having_FileInfo_array_args), "args")] - public void Parameters_named_arguments_generate_command_arguments_having_the_correct_name(string methodName, string expectedArgName) - { - var config = new CommandLineConfiguration(new RootCommand()) - .ConfigureRootCommandFromMethod(GetMethodInfo(methodName)); - - var rootCommandArgument = config.RootCommand.Arguments.Single(); - - rootCommandArgument.Name - .Should() - .Be(expectedArgName); - } - - [Theory] - [InlineData(nameof(Method_having_string_argument))] - [InlineData(nameof(Method_having_string_argument_with_null_default_value))] - [InlineData(nameof(Method_having_string_array_arguments))] - [InlineData(nameof(Method_having_string_array_arguments_with_default_value))] - [InlineData(nameof(Method_having_FileInfo_argument))] - [InlineData(nameof(Method_having_FileInfo_argument_with_default_value))] - [InlineData(nameof(Method_having_FileInfo_array_args))] - public void Options_are_not_generated_for_command_argument_parameters(string methodName) - { - var config = new CommandLineConfiguration(new RootCommand()) - .ConfigureRootCommandFromMethod(GetMethodInfo(methodName)); - - var rootCommand = config.RootCommand; - - var argumentParameterNames = new[] - { - "arguments", - "argument", - "args" - }; - - rootCommand.Options - .Should() - .NotContain(o => argumentParameterNames.Contains(o.Name)); - } - - [Theory] - [InlineData(nameof(Method_having_string_argument), typeof(string))] - [InlineData(nameof(Method_having_string_argument_with_null_default_value), typeof(string))] - [InlineData(nameof(Method_having_string_array_arguments), typeof(string[]))] - [InlineData(nameof(Method_having_string_array_arguments_with_default_value), typeof(string[]))] - [InlineData(nameof(Method_having_FileInfo_argument), typeof(FileInfo))] - [InlineData(nameof(Method_having_FileInfo_argument_with_default_value), typeof(FileInfo))] - [InlineData(nameof(Method_having_FileInfo_array_args), typeof(FileInfo[]))] - public void Parameters_named_arguments_generate_command_arguments_having_the_correct_type( - string methodName, - Type expectedType) - { - var config = new CommandLineConfiguration(new RootCommand()) - .ConfigureRootCommandFromMethod(GetMethodInfo(methodName)); - - var rootCommandArgument = config.RootCommand.Arguments.Single(); - - rootCommandArgument.ValueType - .Should() - .Be(expectedType); - } - - [Fact] - public async Task When_method_returns_void_then_return_code_is_0() - { - var config = new CommandLineConfiguration(new RootCommand()) - .ConfigureRootCommandFromMethod( - GetMethodInfo(nameof(Method_returning_void)), this); - config.Output = TextWriter.Null; - - var result = await config.InvokeAsync(""); - - result.Should().Be(0); - } - - [Fact] - public async Task When_method_returns_int_then_return_code_is_set_to_return_value() - { - var config = new CommandLineConfiguration(new RootCommand()) - .ConfigureRootCommandFromMethod( - GetMethodInfo(nameof(Method_returning_int)), this); - config.Output = TextWriter.Null; - - var result = await config.InvokeAsync("-i 123"); - - result.Should().Be(123); - } - - [Fact] - public async Task When_method_returns_Task_of_int_then_return_code_is_set_to_return_value() - { - var config = new CommandLineConfiguration(new RootCommand()) - .ConfigureRootCommandFromMethod( - GetMethodInfo(nameof(Method_returning_Task_of_int)), this); - config.Output = TextWriter.Null; - - var result = await config.InvokeAsync("-i 123"); - - result.Should().Be(123); - } - - [Theory] - [InlineData(typeof(BindingContext))] - [InlineData(typeof(ParseResult))] - [InlineData(typeof(CancellationToken))] - public void Options_are_not_built_for_infrastructure_types_exposed_by_method_parameters(Type type) - { - var targetType = typeof(ClassWithMethodHavingParameter<>).MakeGenericType(type); - - var handlerMethod = targetType.GetMethod(nameof(ClassWithMethodHavingParameter.Handle)); - - var options = handlerMethod.BuildOptions(); - - options.Should() - .NotContain(o => o.GetType().IsAssignableTo(typeof(Option<>).MakeGenericType(type))); - } - - [Fact] - public async Task Method_parameters_on_the_invoked_member_method_are_bound_to_matching_option_names_by_MethodInfo_with_target() - { - var command = new Command("test"); - command.ConfigureFromMethod(GetMethodInfo(nameof(Method_taking_bool)), this); - - await command.Parse("--value").InvokeAsync(); - - _receivedValues.Should().BeEquivalentTo(new [] { true }); - } - - [Fact] - public async Task Method_with_multiple_parameters_with_default_values_are_resolved_correctly() - { - var command = new Command("test"); - command.ConfigureFromMethod(GetMethodInfo(nameof(Method_with_multiple_default_values)), this); - - await command.Parse("").InvokeAsync(); - - _receivedValues.Should().BeEquivalentTo(new [] { 1, 2 }); - } - - internal void Method_taking_bool(bool value = false) - { - _receivedValues = new object[] { value }; - } - - internal void Method_with_single_letter_parameters( - int x, - int y) - { - _receivedValues = new object[] { x, y }; - } - - internal void Method_returning_void() - { - } - - internal int Method_returning_int(int i) - { - return i; - } - - internal async Task Method_returning_Task_of_int(int i) - { - await Task.Yield(); - return i; - } - - internal void Method_having_string_argument(string stringOption, int intOption, string argument) - { - } - - internal void Method_having_string_argument_with_null_default_value(string stringOption, int intOption, string argument = null) - { - } - - internal void Method_having_string_argument_with_non_null_default_value(string stringOption, int intOption, string argument = "the-default-value") - { - } - - internal void Method_having_string_array_arguments(string stringOption, int intOption, string[] arguments) - { - } - - internal void Method_having_string_array_arguments_with_default_value(string stringOption, int intOption, string[] arguments = null) - { - } - - internal void Method_having_FileInfo_argument(string stringOption, int intOption, FileInfo argument) - { - } - - internal void Method_having_FileInfo_argument_with_default_value(string stringOption, int intOption, FileInfo argument = null) - { - } - - internal void Method_having_FileInfo_array_args(string stringOption, int intOption, FileInfo[] args) - { - } - - internal void Method_with_multiple_default_values(int firstValue = 1, int secondValue = 2) - { - _receivedValues = new object[] { firstValue, secondValue }; - } - - private MethodInfo GetMethodInfo(string name) - { - return typeof(ConfigureFromMethodTests) - .GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) - .Single(m => m.Name == name); - } - } -} diff --git a/src/System.CommandLine.DragonFruit.Tests/EntryPointCreatorTests.cs b/src/System.CommandLine.DragonFruit.Tests/EntryPointCreatorTests.cs deleted file mode 100644 index 3bec9f066b..0000000000 --- a/src/System.CommandLine.DragonFruit.Tests/EntryPointCreatorTests.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.Collections.Generic; -using System.Reflection; -using FluentAssertions; -using Xunit; - -namespace System.CommandLine.DragonFruit.Tests -{ - public class EntryPointCreatorTests - { - [Fact] - public void ItThrowsIfEntryPointNotFound() - { - Action find = () => EntryPointDiscoverer.FindStaticEntryMethod(typeof(IEnumerable<>).Assembly); - find.Should().Throw(); - } - - private class Program - { - public static void Main(string arg1) { } - public static void Main(string arg2, string arg3) { } - } - - [Fact] - public void ItThrowsIfMultipleEntryPointNotFound() - { - Action find = () => EntryPointDiscoverer.FindStaticEntryMethod(typeof(CommandLineTests).Assembly); - find.Should().Throw(); - } - } -} diff --git a/src/System.CommandLine.DragonFruit.Tests/StringExtensionTests.cs b/src/System.CommandLine.DragonFruit.Tests/StringExtensionTests.cs deleted file mode 100644 index 6ec3f3d159..0000000000 --- a/src/System.CommandLine.DragonFruit.Tests/StringExtensionTests.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using FluentAssertions; -using Xunit; - -namespace System.CommandLine.DragonFruit.Tests -{ - public class StringExtensionTests - { - [Theory] - [InlineData(null, null)] - [InlineData("", "")] - [InlineData("Option123", "option123")] - [InlineData("dWORD", "d-word")] - [InlineData("MSBuild", "msbuild")] - [InlineData("NoEdit", "no-edit")] - [InlineData("SetUpstreamBranch", "set-upstream-branch")] - [InlineData("lowerCaseFirst", "lower-case-first")] - [InlineData("_field", "field")] - [InlineData("__field", "field")] - [InlineData("___field", "field")] - [InlineData("m_field", "m-field")] - [InlineData("m_Field", "m-field")] - public void ToKebabCase(string input, string expected) => input.ToKebabCase().Should().Be(expected); - } -} diff --git a/src/System.CommandLine.DragonFruit.Tests/System.CommandLine.DragonFruit.Tests.csproj b/src/System.CommandLine.DragonFruit.Tests/System.CommandLine.DragonFruit.Tests.csproj deleted file mode 100644 index 87c96e559b..0000000000 --- a/src/System.CommandLine.DragonFruit.Tests/System.CommandLine.DragonFruit.Tests.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - $(TargetFrameworkForNETSDK) - AutoGeneratedProgram - - true - - - - $(NoWarn);1701;1702;1591 - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/System.CommandLine.DragonFruit.Tests/TestProgram.cs b/src/System.CommandLine.DragonFruit.Tests/TestProgram.cs deleted file mode 100644 index 7c2a3eaa75..0000000000 --- a/src/System.CommandLine.DragonFruit.Tests/TestProgram.cs +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.Reflection; - -namespace System.CommandLine.DragonFruit.Tests -{ - public class TestProgram - { - public static readonly MethodInfo TestMainMethodInfoWithoutPara = typeof(TestProgram).GetMethod(nameof(TestMainWithoutPara)); - - public static readonly MethodInfo TestMainMethodInfoWithPara = typeof(TestProgram).GetMethod(nameof(TestMainWithPara)); - - public static readonly MethodInfo TestMainMethodInfoWithTextAndPara = typeof(TestProgram).GetMethod(nameof(TestMainWithTextAndPara)); - - public static readonly MethodInfo TestMainMethodInfoWithDefault = typeof(TestProgram).GetMethod(nameof(TestMainWithDefault)); - - /// - /// Help for the test program - /// More help for the test program - /// - /// Specifies the name option - /// - /// These are arguments - public void TestMainWithPara(string name, ParseResult parseResult, string[] args = null) - { - parseResult.Configuration.Output.Write(name); - if (args != null && args.Length > 0) - { - parseResult.Configuration.Output.Write($"args: { string.Join(",", args) }"); - } - } - - /// - /// Skipped help for the test program - /// More skipped help for the test programHelp for the test programMore skipped help for the test program - /// More skipped help for the test programMore help for the test programMore skipped help for the test program - /// - /// More skipped help for the test program - /// - /// Specifies the name option - /// - /// These are arguments - public void TestMainWithTextAndPara(string name, ParseResult parseResult, string[] args = null) - { - parseResult.Configuration.Output.Write(name); - if (args != null && args.Length > 0) - { - parseResult.Configuration.Output.Write($"args: { string.Join(",", args) }"); - } - } - - /// - /// Normal summary - /// - /// Specifies the name option - /// - /// These are arguments - public void TestMainWithoutPara(string name, ParseResult parseResult, string[] args = null) - { - parseResult.Configuration.Output.Write(name); - } - - public void TestMainWithDefault(string name = "Bruce", ParseResult parseResult = null) - { - parseResult?.Configuration.Output.Write(name); - } - } -} diff --git a/src/System.CommandLine.DragonFruit.Tests/XmlDocReaderTests.cs b/src/System.CommandLine.DragonFruit.Tests/XmlDocReaderTests.cs deleted file mode 100644 index 7333f30bee..0000000000 --- a/src/System.CommandLine.DragonFruit.Tests/XmlDocReaderTests.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.IO; -using FluentAssertions; -using Xunit; - -namespace System.CommandLine.DragonFruit.Tests -{ - public class XmlDocReaderTests - { - private class Program - { - public static void Main(bool verbose = false, string flavor = null, int? count = 0) - { - } - - public static void MainWithoutParam() - { - } - } - - [Fact] - public void It_finds_member_xml() - { - const string xml = @" - - - DragonFruit - - - - - Hello - - Show verbose output - Which flavor to use - How many smoothies? - - - -"; - Action action = Program.Main; - var reader = new StringReader(xml); - XmlDocReader.TryLoad(reader, out var docReader).Should().BeTrue(); - - docReader.TryGetMethodDescription(action.Method, out var helpMetadata).Should().BeTrue(); - helpMetadata.Description.Should().Be("Hello"); - helpMetadata.ParameterDescriptions["verbose"].Should().Be("Show verbose output"); - helpMetadata.ParameterDescriptions["flavor"].Should().Be("Which flavor to use"); - helpMetadata.ParameterDescriptions["count"].Should().Be("How many smoothies?"); - } - - [Fact] - public void It_finds_member_without_param() - { - const string xml = @" - - - DragonFruit - - - - - Hello - - - - -"; - Action action = Program.MainWithoutParam; - var reader = new StringReader(xml); - XmlDocReader.TryLoad(reader, out var docReader).Should().BeTrue(); - - docReader.TryGetMethodDescription(action.Method, out var helpMetadata).Should().BeTrue(); - helpMetadata.Description.Should().Be("Hello"); - } - } -} diff --git a/src/System.CommandLine.DragonFruit/CommandHelpMetadata.cs b/src/System.CommandLine.DragonFruit/CommandHelpMetadata.cs deleted file mode 100644 index f2b3ddf01f..0000000000 --- a/src/System.CommandLine.DragonFruit/CommandHelpMetadata.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.Collections.Generic; - -namespace System.CommandLine.DragonFruit -{ - public class CommandHelpMetadata - { - public string Description { get; set; } - - public string Name { get; set; } - - public Dictionary ParameterDescriptions { get; } = new Dictionary(); - } -} diff --git a/src/System.CommandLine.DragonFruit/CommandLine.cs b/src/System.CommandLine.DragonFruit/CommandLine.cs deleted file mode 100644 index 01387118e8..0000000000 --- a/src/System.CommandLine.DragonFruit/CommandLine.cs +++ /dev/null @@ -1,337 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.Collections.Generic; -using System.CommandLine.Binding; -using System.CommandLine.NamingConventionBinder; -using System.CommandLine.Utility; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using CommandHandler = System.CommandLine.NamingConventionBinder.CommandHandler; - -namespace System.CommandLine.DragonFruit -{ - public static class CommandLine - { - /// - /// Finds and executes 'Program.Main', but with strong types. - /// - /// The entry assembly - /// The string arguments. - /// Explicitly defined entry point - /// Explicitly defined path to xml file containing XML Docs - /// The exit code. - public static Task ExecuteAssemblyAsync( - Assembly entryAssembly, - string[] args, - string entryPointFullTypeName, - string xmlDocsFilePath = null) - { - if (entryAssembly == null) - { - throw new ArgumentNullException(nameof(entryAssembly)); - } - - args = args ?? Array.Empty(); - entryPointFullTypeName = entryPointFullTypeName?.Trim(); - - MethodInfo entryMethod = EntryPointDiscoverer.FindStaticEntryMethod(entryAssembly, entryPointFullTypeName); - - //TODO The xml docs file name and location can be customized using project property. - return InvokeMethodAsync(args, entryMethod, xmlDocsFilePath, null); - } - - /// - /// Finds and executes 'Program.Main', but with strong types. - /// - /// The entry assembly - /// The string arguments. - /// Explicitly defined entry point - /// Explicitly defined path to xml file containing XML Docs - /// The exit code. - public static int ExecuteAssembly( - Assembly entryAssembly, - string[] args, - string entryPointFullTypeName, - string xmlDocsFilePath = null) - { - if (entryAssembly == null) - { - throw new ArgumentNullException(nameof(entryAssembly)); - } - - args = args ?? Array.Empty(); - entryPointFullTypeName = entryPointFullTypeName?.Trim(); - - MethodInfo entryMethod = EntryPointDiscoverer.FindStaticEntryMethod(entryAssembly, entryPointFullTypeName); - - //TODO The xml docs file name and location can be customized using project property. - return InvokeMethod(args, entryMethod, xmlDocsFilePath, null); - } - - public static Task InvokeMethodAsync( - string[] args, - MethodInfo method, - string xmlDocsFilePath = null, - object target = null, - TextWriter standardOutput = null, - TextWriter standardError = null) - { - CommandLineConfiguration configuration = BuildConfiguration(method, xmlDocsFilePath, target); - configuration.Output = standardOutput ?? Console.Out; - configuration.Error = standardError ?? Console.Error; - - return configuration.Parse(args).InvokeAsync(); - } - - public static int InvokeMethod( - string[] args, - MethodInfo method, - string xmlDocsFilePath = null, - object target = null, - TextWriter standardOutput = null, - TextWriter standardError = null) - { - CommandLineConfiguration configuration = BuildConfiguration(method, xmlDocsFilePath, target); - configuration.Output = standardOutput ?? Console.Out; - configuration.Error = standardError ?? Console.Error; - - return configuration.Parse(args).Invoke(); - } - - private static CommandLineConfiguration BuildConfiguration(MethodInfo method, - string xmlDocsFilePath, - object target) - { - return new CommandLineConfiguration(new RootCommand()) - .ConfigureRootCommandFromMethod(method, target) - .ConfigureHelpFromXmlComments(method, xmlDocsFilePath); - } - - public static CommandLineConfiguration ConfigureRootCommandFromMethod( - this CommandLineConfiguration builder, - MethodInfo method, - object target = null) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - if (method == null) - { - throw new ArgumentNullException(nameof(method)); - } - - builder.RootCommand.ConfigureFromMethod(method, target); - - return builder; - } - - private static readonly string[] _argumentParameterNames = - { - "arguments", - "argument", - "args" - }; - - public static void ConfigureFromMethod( - this Command command, - MethodInfo method, - object target = null) - { - if (command == null) - { - throw new ArgumentNullException(nameof(command)); - } - - if (method == null) - { - throw new ArgumentNullException(nameof(method)); - } - - foreach (var option in method.BuildOptions()) - { - command.Options.Add(option); - } - - if (method.GetParameters().FirstOrDefault(p => _argumentParameterNames.Contains(p.Name)) is { } argsParam) - { - command.Arguments.Add(ArgumentBuilder.CreateArgument(argsParam)); - } - - command.Action = CommandHandler.Create(method, target); - } - - public static CommandLineConfiguration ConfigureHelpFromXmlComments( - this CommandLineConfiguration builder, - MethodInfo method, - string xmlDocsFilePath) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - if (method == null) - { - throw new ArgumentNullException(nameof(method)); - } - - if (XmlDocReader.TryLoad(xmlDocsFilePath ?? GetDefaultXmlDocsFileLocation(method.DeclaringType.Assembly), out var xmlDocs)) - { - if (xmlDocs.TryGetMethodDescription(method, out CommandHelpMetadata metadata) && - metadata.Description != null) - { - builder.RootCommand.Description = metadata.Description; - - foreach (var parameterDescription in metadata.ParameterDescriptions) - { - var kebabCasedParameterName = parameterDescription.Key.ToKebabCase(); - - var option = builder.RootCommand.Options.FirstOrDefault(o => HasAliasIgnoringPrefix(o, kebabCasedParameterName)); - - if (option != null) - { - option.Description = parameterDescription.Value; - } - else - { - for (var i = 0; i < builder.RootCommand.Arguments.Count; i++) - { - var argument = builder.RootCommand.Arguments[i]; - if (string.Equals( - argument.Name, - kebabCasedParameterName, - StringComparison.OrdinalIgnoreCase)) - { - argument.Description = parameterDescription.Value; - } - } - } - } - - metadata.Name = method.DeclaringType.Assembly.GetName().Name; - } - } - - return builder; - } - - public static string BuildAlias(this IValueDescriptor descriptor) - { - if (descriptor == null) - { - throw new ArgumentNullException(nameof(descriptor)); - } - - return BuildAlias(descriptor.ValueName); - } - - internal static string BuildAlias(string parameterName) - { - if (String.IsNullOrWhiteSpace(parameterName)) - { - throw new ArgumentException("Value cannot be null or whitespace.", nameof(parameterName)); - } - - return parameterName.Length > 1 - ? $"--{parameterName.ToKebabCase()}" - : $"-{parameterName.ToLowerInvariant()}"; - } - - public static IEnumerable