diff --git a/FSharp.CommandLine.fsproj b/FSharp.CommandLine.fsproj
new file mode 100644
index 0000000..b23486a
--- /dev/null
+++ b/FSharp.CommandLine.fsproj
@@ -0,0 +1,28 @@
+
+
+ net6.0;netstandard2.0
+ A framework for building command line application in F#. Supports command line option parsing, type-safe scanf, monadic command construction, automatic help & shell completion generation, and so on.
+ cannorin
+
+ (c) cannorin 2017-2022
+ https://github.com/cannorin/FSharp.CommandLine
+ https://github.com/cannorin/FSharp.CommandLine/blob/master/LICENSE.txt
+ fsharp commandline parsing framework
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/FSharp.CommandLine.sln b/FSharp.CommandLine.sln
deleted file mode 100755
index e57f2c1..0000000
--- a/FSharp.CommandLine.sln
+++ /dev/null
@@ -1,31 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27428.2011
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{f2a71f9b-5d33-465a-a702-920d77279786}") = "FSharp.CommandLine", "src\FSharp.CommandLine\FSharp.CommandLine.fsproj", "{32A93182-5504-4C36-98E0-D2486AA6B361}"
-EndProject
-Project("{f2a71f9b-5d33-465a-a702-920d77279786}") = "FSharp.Scanf", "src\FSharp.Scanf\FSharp.Scanf.fsproj", "{9540C26A-B0A5-4E78-A596-C62F036A2DF1}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {32A93182-5504-4C36-98E0-D2486AA6B361}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {32A93182-5504-4C36-98E0-D2486AA6B361}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {32A93182-5504-4C36-98E0-D2486AA6B361}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {32A93182-5504-4C36-98E0-D2486AA6B361}.Release|Any CPU.Build.0 = Release|Any CPU
- {9540C26A-B0A5-4E78-A596-C62F036A2DF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9540C26A-B0A5-4E78-A596-C62F036A2DF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9540C26A-B0A5-4E78-A596-C62F036A2DF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9540C26A-B0A5-4E78-A596-C62F036A2DF1}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {80272E67-BBF7-47F2-A615-C56E4B39D7D6}
- EndGlobalSection
-EndGlobal
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 199f445..046dd7e 100755
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,9 +1,10 @@
+* 4.0.0 - Massive refactoring
* 3.4.* - Indent multiline command descriptions
* 3.3.* - Fixed scanf parser.
* 3.2.* - Fixed scanf parser.
* 3.1.* - Improve comments. Some refactoring.
* 3.0.* - Breaking API changes. Use FAKE again. Refactor Scanf.
-* 2.2.* - Fix broken NuGet dependency
+* 2.2.* - Fix broken NuGet dependency
* 2.1.* - Separated scanf module
* 2.0.* - Breaking API changes: no more internal side effects
* 1.2.* - Get rid of FAKE
diff --git a/build.fsx b/build.fsx
index 5f8f649..07af2cd 100755
--- a/build.fsx
+++ b/build.fsx
@@ -1,14 +1,14 @@
#r "paket:
-source https://api.nuget.org/v3/index.json
nuget FSharp.Core
nuget Fake.DotNet.Cli
-nuget Fake.IO.FileSystem
nuget Fake.DotNet.MSBuild
-nuget Fake.Core.Target
nuget Fake.DotNet.AssemblyInfoFile
-nuget Fake.Core.ReleaseNotes //"
-
+nuget Fake.Core.Target
+nuget Fake.Core.ReleaseNotes
+nuget Fake.IO.FileSystem
+//"
#load ".fake/build.fsx/intellisense.fsx"
+
open Fake.Core
open Fake.DotNet
open Fake.IO
@@ -51,7 +51,7 @@ let disableLogging (c: MSBuild.CliArguments) =
{ c with ConsoleLogParameters = []; DistributedLoggers = None; DisableInternalBinLog = true }
Target.create "WriteVersion" (fun _ ->
- AssemblyInfoFile.createFSharp "./src/common/Version.fs" [
+ AssemblyInfoFile.createFSharp "./src/version.fs" [
AssemblyInfo.Version release.AssemblyVersion
AssemblyInfo.FileVersion release.AssemblyVersion
]
@@ -60,7 +60,7 @@ Target.create "WriteVersion" (fun _ ->
Target.create "Clean" (fun _ ->
!! "src/**/bin"
++ "src/**/obj"
- |> Shell.cleanDirs
+ |> Shell.cleanDirs
)
Target.create "Build" (fun _ ->
diff --git a/build.fsx.lock b/build.fsx.lock
old mode 100755
new mode 100644
index 6b14a07..9b65aee
--- a/build.fsx.lock
+++ b/build.fsx.lock
@@ -1,576 +1,233 @@
STORAGE: NONE
-RESTRICTION: == netstandard2.0
+RESTRICTION: || (== net6.0) (== netstandard2.0)
NUGET
remote: https://api.nuget.org/v3/index.json
- BlackFox.VsWhere (1.0)
+ BlackFox.VsWhere (1.1)
FSharp.Core (>= 4.2.3)
- Fake.Core.CommandLineParsing (5.11.1)
- FParsec (>= 1.0.3)
+ Microsoft.Win32.Registry (>= 4.7)
+ Fake.Core.CommandLineParsing (5.22)
+ FParsec (>= 1.1.1)
+ FSharp.Core (>= 6.0)
+ Fake.Core.Context (5.22)
+ FSharp.Core (>= 6.0)
+ Fake.Core.Environment (5.22)
+ FSharp.Core (>= 6.0)
+ Fake.Core.FakeVar (5.22)
+ Fake.Core.Context (>= 5.22)
+ FSharp.Core (>= 6.0)
+ Fake.Core.Process (5.22)
+ Fake.Core.Environment (>= 5.22)
+ Fake.Core.FakeVar (>= 5.22)
+ Fake.Core.String (>= 5.22)
+ Fake.Core.Trace (>= 5.22)
+ Fake.IO.FileSystem (>= 5.22)
+ FSharp.Core (>= 6.0)
+ System.Collections.Immutable (>= 5.0)
+ Fake.Core.ReleaseNotes (5.22)
+ Fake.Core.SemVer (>= 5.22)
+ Fake.Core.String (>= 5.22)
+ FSharp.Core (>= 6.0)
+ Fake.Core.SemVer (5.22)
+ FSharp.Core (>= 6.0)
+ Fake.Core.String (5.22)
+ FSharp.Core (>= 6.0)
+ Fake.Core.Target (5.22)
+ Fake.Core.CommandLineParsing (>= 5.22)
+ Fake.Core.Context (>= 5.22)
+ Fake.Core.Environment (>= 5.22)
+ Fake.Core.FakeVar (>= 5.22)
+ Fake.Core.Process (>= 5.22)
+ Fake.Core.String (>= 5.22)
+ Fake.Core.Trace (>= 5.22)
+ FSharp.Control.Reactive (>= 5.0.2)
+ FSharp.Core (>= 6.0)
+ Fake.Core.Tasks (5.22)
+ Fake.Core.Trace (>= 5.22)
+ FSharp.Core (>= 6.0)
+ Fake.Core.Trace (5.22)
+ Fake.Core.Environment (>= 5.22)
+ Fake.Core.FakeVar (>= 5.22)
+ FSharp.Core (>= 6.0)
+ Fake.Core.Xml (5.22)
+ Fake.Core.String (>= 5.22)
+ FSharp.Core (>= 6.0)
+ Fake.DotNet.AssemblyInfoFile (5.22)
+ Fake.Core.Environment (>= 5.22)
+ Fake.Core.String (>= 5.22)
+ Fake.Core.Trace (>= 5.22)
+ Fake.IO.FileSystem (>= 5.22)
+ FSharp.Core (>= 6.0)
+ Fake.DotNet.Cli (5.22)
+ Fake.Core.Environment (>= 5.22)
+ Fake.Core.Process (>= 5.22)
+ Fake.Core.String (>= 5.22)
+ Fake.Core.Trace (>= 5.22)
+ Fake.DotNet.MSBuild (>= 5.22)
+ Fake.DotNet.NuGet (>= 5.22)
+ Fake.IO.FileSystem (>= 5.22)
+ FSharp.Core (>= 6.0)
+ Mono.Posix.NETStandard (>= 1.0)
+ Newtonsoft.Json (>= 13.0.1)
+ Fake.DotNet.MSBuild (5.22)
+ BlackFox.VsWhere (>= 1.1)
+ Fake.Core.Environment (>= 5.22)
+ Fake.Core.Process (>= 5.22)
+ Fake.Core.String (>= 5.22)
+ Fake.Core.Trace (>= 5.22)
+ Fake.IO.FileSystem (>= 5.22)
+ FSharp.Core (>= 6.0)
+ MSBuild.StructuredLogger (>= 2.1.545)
+ Fake.DotNet.NuGet (5.22)
+ Fake.Core.Environment (>= 5.22)
+ Fake.Core.Process (>= 5.22)
+ Fake.Core.SemVer (>= 5.22)
+ Fake.Core.String (>= 5.22)
+ Fake.Core.Tasks (>= 5.22)
+ Fake.Core.Trace (>= 5.22)
+ Fake.Core.Xml (>= 5.22)
+ Fake.IO.FileSystem (>= 5.22)
+ Fake.Net.Http (>= 5.22)
+ FSharp.Core (>= 6.0)
+ Newtonsoft.Json (>= 13.0.1)
+ NuGet.Protocol (>= 5.11)
+ Fake.IO.FileSystem (5.22)
+ Fake.Core.String (>= 5.22)
+ FSharp.Core (>= 6.0)
+ Fake.Net.Http (5.22)
+ Fake.Core.Trace (>= 5.22)
+ FSharp.Core (>= 6.0)
+ FParsec (1.1.1)
FSharp.Core (>= 4.3.4)
- Fake.Core.Context (5.11.1)
- FSharp.Core (>= 4.3.4)
- Fake.Core.Environment (5.11.1)
- FSharp.Core (>= 4.3.4)
- Fake.Core.FakeVar (5.11.1)
- Fake.Core.Context (>= 5.11.1)
- FSharp.Core (>= 4.3.4)
- Fake.Core.Process (5.11.1)
- Fake.Core.Environment (>= 5.11.1)
- Fake.Core.FakeVar (>= 5.11.1)
- Fake.Core.String (>= 5.11.1)
- Fake.Core.Trace (>= 5.11.1)
- Fake.IO.FileSystem (>= 5.11.1)
- FSharp.Core (>= 4.3.4)
- System.Diagnostics.Process (>= 4.3)
- Fake.Core.ReleaseNotes (5.11.1)
- Fake.Core.SemVer (>= 5.11.1)
- Fake.Core.String (>= 5.11.1)
- FSharp.Core (>= 4.3.4)
- Fake.Core.SemVer (5.11.1)
- FSharp.Core (>= 4.3.4)
- System.Runtime.Numerics (>= 4.3)
- Fake.Core.String (5.11.1)
- FSharp.Core (>= 4.3.4)
- Fake.Core.Target (5.11.1)
- Fake.Core.CommandLineParsing (>= 5.11.1)
- Fake.Core.Context (>= 5.11.1)
- Fake.Core.Environment (>= 5.11.1)
- Fake.Core.FakeVar (>= 5.11.1)
- Fake.Core.Process (>= 5.11.1)
- Fake.Core.String (>= 5.11.1)
- Fake.Core.Trace (>= 5.11.1)
- FSharp.Control.Reactive (>= 4.1)
- FSharp.Core (>= 4.3.4)
- System.Reactive.Compatibility (>= 4.1.2)
- Fake.Core.Trace (5.11.1)
- Fake.Core.Environment (>= 5.11.1)
- Fake.Core.FakeVar (>= 5.11.1)
- FSharp.Core (>= 4.3.4)
- Fake.DotNet.AssemblyInfoFile (5.11.1)
- Fake.Core.Environment (>= 5.11.1)
- Fake.Core.String (>= 5.11.1)
- Fake.Core.Trace (>= 5.11.1)
- Fake.IO.FileSystem (>= 5.11.1)
- FSharp.Core (>= 4.3.4)
- Fake.DotNet.Cli (5.11.1)
- Fake.Core.Environment (>= 5.11.1)
- Fake.Core.Process (>= 5.11.1)
- Fake.Core.String (>= 5.11.1)
- Fake.Core.Trace (>= 5.11.1)
- Fake.DotNet.MSBuild (>= 5.11.1)
- Fake.IO.FileSystem (>= 5.11.1)
- FSharp.Core (>= 4.3.4)
- Newtonsoft.Json (>= 12.0.1)
- Fake.DotNet.MSBuild (5.11.1)
- BlackFox.VsWhere (>= 1.0)
- Fake.Core.Environment (>= 5.11.1)
- Fake.Core.Process (>= 5.11.1)
- Fake.Core.String (>= 5.11.1)
- Fake.Core.Trace (>= 5.11.1)
- Fake.IO.FileSystem (>= 5.11.1)
- FSharp.Core (>= 4.3.4)
- MSBuild.StructuredLogger (>= 2.0.61)
- Fake.IO.FileSystem (5.11.1)
- Fake.Core.String (>= 5.11.1)
- FSharp.Core (>= 4.3.4)
- System.Diagnostics.FileVersionInfo (>= 4.3)
- System.IO.FileSystem.Watcher (>= 4.3)
- FParsec (1.0.3)
- FSharp.Core (>= 4.2.3)
- NETStandard.Library (>= 1.6.1)
- FSharp.Control.Reactive (4.1)
- FSharp.Core (>= 4.2.3)
- System.Reactive (>= 4.0)
- FSharp.Core (4.5.4)
- Microsoft.Build (15.9.20)
- Microsoft.Build.Framework (>= 15.9.20)
+ FSharp.Control.Reactive (5.0.5)
+ FSharp.Core (>= 4.7.2)
+ System.Reactive (>= 5.0 < 6.0)
+ FSharp.Core (6.0.3)
+ Microsoft.Build (17.1)
+ Microsoft.Build.Framework (>= 17.1) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= net472)) (&& (== netstandard2.0) (>= net6.0))
+ Microsoft.NET.StringTools (>= 1.0) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= net472)) (&& (== netstandard2.0) (>= net6.0))
+ Microsoft.Win32.Registry (>= 4.3) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= net6.0))
+ System.Collections.Immutable (>= 5.0) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= net472)) (&& (== netstandard2.0) (>= net6.0))
+ System.Configuration.ConfigurationManager (>= 4.7) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= net472)) (&& (== netstandard2.0) (>= net6.0))
+ System.Reflection.Metadata (>= 1.6) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= net6.0))
+ System.Security.Principal.Windows (>= 4.7) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= net6.0))
+ System.Text.Encoding.CodePages (>= 4.0.1) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= net6.0))
+ System.Text.Json (>= 6.0) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= net472)) (&& (== netstandard2.0) (>= net6.0))
+ System.Threading.Tasks.Dataflow (>= 6.0) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= net472)) (&& (== netstandard2.0) (>= net6.0))
+ Microsoft.Build.Framework (17.1)
Microsoft.Win32.Registry (>= 4.3)
- System.Collections.Immutable (>= 1.5)
- System.Diagnostics.TraceSource (>= 4.0)
- System.IO.Compression (>= 4.3)
- System.Reflection.Metadata (>= 1.6)
- System.Reflection.TypeExtensions (>= 4.1)
- System.Runtime.InteropServices.RuntimeInformation (>= 4.3)
- System.Runtime.Loader (>= 4.0)
- System.Text.Encoding.CodePages (>= 4.0.1)
- System.Threading.Tasks.Dataflow (>= 4.6)
- Microsoft.Build.Framework (15.9.20)
- System.Runtime.Serialization.Primitives (>= 4.1.1)
- System.Threading.Thread (>= 4.0)
- Microsoft.Build.Tasks.Core (15.9.20)
- Microsoft.Build.Framework (>= 15.9.20)
- Microsoft.Build.Utilities.Core (>= 15.9.20)
+ System.Security.Permissions (>= 4.7)
+ Microsoft.Build.Tasks.Core (17.1)
+ Microsoft.Build.Framework (>= 17.1)
+ Microsoft.Build.Utilities.Core (>= 17.1)
+ Microsoft.NET.StringTools (>= 1.0)
Microsoft.Win32.Registry (>= 4.3)
System.CodeDom (>= 4.4)
- System.Collections.Immutable (>= 1.5)
- System.Linq.Parallel (>= 4.0.1)
- System.Net.Http (>= 4.3)
+ System.Collections.Immutable (>= 5.0)
System.Reflection.Metadata (>= 1.6)
- System.Reflection.TypeExtensions (>= 4.1)
- System.Resources.Writer (>= 4.0)
- System.Threading.Tasks.Dataflow (>= 4.6)
- Microsoft.Build.Utilities.Core (15.9.20)
- Microsoft.Build.Framework (>= 15.9.20)
+ System.Resources.Extensions (>= 4.6)
+ System.Security.Cryptography.Pkcs (>= 4.7)
+ System.Security.Cryptography.Xml (>= 4.7)
+ System.Security.Permissions (>= 4.7)
+ System.Threading.Tasks.Dataflow (>= 6.0)
+ Microsoft.Build.Utilities.Core (17.1)
+ Microsoft.Build.Framework (>= 17.1)
+ Microsoft.NET.StringTools (>= 1.0)
Microsoft.Win32.Registry (>= 4.3)
- System.Collections.Immutable (>= 1.5)
- System.Runtime.InteropServices.RuntimeInformation (>= 4.3)
- System.Text.Encoding.CodePages (>= 4.4)
- Microsoft.NETCore.Platforms (2.2)
- Microsoft.NETCore.Targets (2.1)
- Microsoft.Win32.Primitives (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
- Microsoft.Win32.Registry (4.5)
- System.Buffers (>= 4.4)
- System.Memory (>= 4.5)
- System.Security.AccessControl (>= 4.5)
- System.Security.Principal.Windows (>= 4.5)
- MSBuild.StructuredLogger (2.0.64)
- Microsoft.Build (>= 15.8.166)
- Microsoft.Build.Framework (>= 15.8.166)
- Microsoft.Build.Tasks.Core (>= 15.8.166)
- Microsoft.Build.Utilities.Core (>= 15.8.166)
- NETStandard.Library (2.0.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Newtonsoft.Json (12.0.1)
- runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.debian.9-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.fedora.27-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.fedora.28-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.native.System (4.3.1)
- Microsoft.NETCore.Platforms (>= 1.1.1)
- Microsoft.NETCore.Targets (>= 1.1.3)
- runtime.native.System.IO.Compression (4.3.2)
- Microsoft.NETCore.Platforms (>= 1.1.1)
- Microsoft.NETCore.Targets (>= 1.1.3)
- runtime.native.System.Net.Http (4.3.1)
+ System.Collections.Immutable (>= 5.0)
+ System.Configuration.ConfigurationManager (>= 4.7)
+ System.Security.Permissions (>= 4.7)
+ System.Text.Encoding.CodePages (>= 4.0.1)
+ Microsoft.NET.StringTools (1.0)
+ System.Memory (>= 4.5.4)
+ System.Runtime.CompilerServices.Unsafe (>= 5.0)
+ Microsoft.NETCore.Platforms (6.0.3) - restriction: || (&& (== net6.0) (< netcoreapp3.1)) (&& (== net6.0) (< netstandard1.2)) (&& (== net6.0) (< netstandard1.3)) (&& (== net6.0) (< netstandard1.5)) (== netstandard2.0)
+ Microsoft.NETCore.Targets (5.0) - restriction: || (&& (== net6.0) (< netcoreapp3.1)) (&& (== net6.0) (< netstandard1.2)) (&& (== net6.0) (< netstandard1.3)) (&& (== net6.0) (< netstandard1.5)) (== netstandard2.0)
+ Microsoft.Win32.Registry (5.0)
+ System.Buffers (>= 4.5.1) - restriction: || (&& (== net6.0) (>= monoandroid) (< netstandard1.3)) (&& (== net6.0) (>= monotouch)) (&& (== net6.0) (< netcoreapp2.0)) (&& (== net6.0) (>= xamarinios)) (&& (== net6.0) (>= xamarinmac)) (&& (== net6.0) (>= xamarintvos)) (&& (== net6.0) (>= xamarinwatchos)) (== netstandard2.0)
+ System.Memory (>= 4.5.4) - restriction: || (&& (== net6.0) (< netcoreapp2.0)) (&& (== net6.0) (< netcoreapp2.1)) (&& (== net6.0) (>= uap10.1)) (== netstandard2.0)
+ System.Security.AccessControl (>= 5.0)
+ System.Security.Principal.Windows (>= 5.0)
+ Microsoft.Win32.SystemEvents (6.0.1) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= netcoreapp3.1))
+ Mono.Posix.NETStandard (1.0)
+ MSBuild.StructuredLogger (2.1.630)
+ Microsoft.Build (>= 16.10)
+ Microsoft.Build.Framework (>= 16.10)
+ Microsoft.Build.Tasks.Core (>= 16.10)
+ Microsoft.Build.Utilities.Core (>= 16.10)
+ Newtonsoft.Json (13.0.1)
+ NuGet.Common (6.1)
+ NuGet.Frameworks (>= 6.1)
+ NuGet.Configuration (6.1)
+ NuGet.Common (>= 6.1)
+ System.Security.Cryptography.ProtectedData (>= 4.4)
+ NuGet.Frameworks (6.1)
+ NuGet.Packaging (6.1)
+ Newtonsoft.Json (>= 13.0.1)
+ NuGet.Configuration (>= 6.1)
+ NuGet.Versioning (>= 6.1)
+ System.Security.Cryptography.Cng (>= 5.0)
+ System.Security.Cryptography.Pkcs (>= 5.0)
+ NuGet.Protocol (6.1)
+ NuGet.Packaging (>= 6.1)
+ NuGet.Versioning (6.1)
+ System.Buffers (4.5.1) - restriction: || (&& (== net6.0) (>= monoandroid) (< netstandard1.3)) (&& (== net6.0) (>= monotouch)) (&& (== net6.0) (< netcoreapp2.0)) (&& (== net6.0) (>= xamarinios)) (&& (== net6.0) (>= xamarinmac)) (&& (== net6.0) (>= xamarintvos)) (&& (== net6.0) (>= xamarinwatchos)) (== netstandard2.0)
+ System.CodeDom (6.0)
+ System.Collections.Immutable (6.0)
+ System.Memory (>= 4.5.4) - restriction: || (&& (== net6.0) (>= net461)) (== netstandard2.0)
+ System.Runtime.CompilerServices.Unsafe (>= 6.0)
+ System.Configuration.ConfigurationManager (6.0)
+ System.Security.Cryptography.ProtectedData (>= 6.0)
+ System.Security.Permissions (>= 6.0)
+ System.Drawing.Common (6.0) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= netcoreapp3.1))
+ Microsoft.Win32.SystemEvents (>= 6.0) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= netcoreapp3.1))
+ System.Formats.Asn1 (6.0)
+ System.Buffers (>= 4.5.1) - restriction: || (&& (== net6.0) (>= net461)) (== netstandard2.0)
+ System.Memory (>= 4.5.4) - restriction: || (&& (== net6.0) (>= net461)) (== netstandard2.0)
+ System.Memory (4.5.4)
+ System.Buffers (>= 4.5.1) - restriction: || (&& (== net6.0) (>= monotouch)) (&& (== net6.0) (>= net461)) (&& (== net6.0) (< netcoreapp2.0)) (&& (== net6.0) (< netstandard1.1)) (&& (== net6.0) (< netstandard2.0)) (&& (== net6.0) (>= xamarinios)) (&& (== net6.0) (>= xamarinmac)) (&& (== net6.0) (>= xamarintvos)) (&& (== net6.0) (>= xamarinwatchos)) (== netstandard2.0)
+ System.Numerics.Vectors (>= 4.4) - restriction: || (&& (== net6.0) (< netcoreapp2.0)) (== netstandard2.0)
+ System.Runtime.CompilerServices.Unsafe (>= 4.5.3) - restriction: || (&& (== net6.0) (>= monotouch)) (&& (== net6.0) (>= net461)) (&& (== net6.0) (< netcoreapp2.0)) (&& (== net6.0) (< netcoreapp2.1)) (&& (== net6.0) (< netstandard1.1)) (&& (== net6.0) (< netstandard2.0)) (&& (== net6.0) (>= uap10.1)) (&& (== net6.0) (>= xamarinios)) (&& (== net6.0) (>= xamarinmac)) (&& (== net6.0) (>= xamarintvos)) (&& (== net6.0) (>= xamarinwatchos)) (== netstandard2.0)
+ System.Numerics.Vectors (4.5) - restriction: || (&& (== net6.0) (>= net461)) (== netstandard2.0)
+ System.Reactive (5.0)
+ System.Runtime.InteropServices.WindowsRuntime (>= 4.3) - restriction: || (&& (== net6.0) (< netcoreapp3.1)) (== netstandard2.0)
+ System.Threading.Tasks.Extensions (>= 4.5.4) - restriction: || (&& (== net6.0) (>= net472)) (&& (== net6.0) (< netcoreapp3.1)) (&& (== net6.0) (>= uap10.1)) (== netstandard2.0)
+ System.Reflection.Metadata (6.0.1)
+ System.Collections.Immutable (>= 6.0)
+ System.Resources.Extensions (6.0)
+ System.Memory (>= 4.5.4) - restriction: || (&& (== net6.0) (>= net461)) (== netstandard2.0)
+ System.Runtime (4.3.1) - restriction: || (&& (== net6.0) (< netcoreapp3.1)) (== netstandard2.0)
Microsoft.NETCore.Platforms (>= 1.1.1)
Microsoft.NETCore.Targets (>= 1.1.3)
- runtime.native.System.Security.Cryptography.Apple (4.3.1)
- runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple (>= 4.3.1)
- runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.debian.9-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.fedora.27-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.fedora.28-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.opensuse.42.3-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.ubuntu.18.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.3)
- runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.opensuse.42.3-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple (4.3.1)
- runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- runtime.ubuntu.18.04-x64.runtime.native.System.Security.Cryptography.OpenSsl (4.3.3)
- System.Buffers (4.5)
- System.CodeDom (4.5)
- System.Collections (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
- System.Collections.Concurrent (4.3)
- System.Collections (>= 4.3)
- System.Diagnostics.Debug (>= 4.3)
- System.Diagnostics.Tracing (>= 4.3)
- System.Globalization (>= 4.3)
- System.Reflection (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Threading (>= 4.3)
- System.Threading.Tasks (>= 4.3)
- System.Collections.Immutable (1.5)
- System.Diagnostics.Debug (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
- System.Diagnostics.DiagnosticSource (4.5.1)
- System.Diagnostics.FileVersionInfo (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- System.Globalization (>= 4.3)
- System.IO (>= 4.3)
- System.IO.FileSystem (>= 4.3)
- System.IO.FileSystem.Primitives (>= 4.3)
- System.Reflection.Metadata (>= 1.4.1)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Runtime.InteropServices (>= 4.3)
- System.Diagnostics.Process (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.Win32.Primitives (>= 4.3)
- Microsoft.Win32.Registry (>= 4.3)
- runtime.native.System (>= 4.3)
- System.Collections (>= 4.3)
- System.Diagnostics.Debug (>= 4.3)
- System.Globalization (>= 4.3)
- System.IO (>= 4.3)
- System.IO.FileSystem (>= 4.3)
- System.IO.FileSystem.Primitives (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Runtime.Handles (>= 4.3)
- System.Runtime.InteropServices (>= 4.3)
- System.Text.Encoding (>= 4.3)
- System.Text.Encoding.Extensions (>= 4.3)
- System.Threading (>= 4.3)
- System.Threading.Tasks (>= 4.3)
- System.Threading.Thread (>= 4.3)
- System.Threading.ThreadPool (>= 4.3)
- System.Diagnostics.TraceSource (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- runtime.native.System (>= 4.3)
- System.Collections (>= 4.3)
- System.Diagnostics.Debug (>= 4.3)
- System.Globalization (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Threading (>= 4.3)
- System.Diagnostics.Tracing (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
- System.Globalization (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
- System.Globalization.Calendars (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Globalization (>= 4.3)
- System.Runtime (>= 4.3)
- System.Globalization.Extensions (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- System.Globalization (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Runtime.InteropServices (>= 4.3)
- System.IO (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
- System.Text.Encoding (>= 4.3)
- System.Threading.Tasks (>= 4.3)
- System.IO.Compression (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- runtime.native.System (>= 4.3)
- runtime.native.System.IO.Compression (>= 4.3)
- System.Buffers (>= 4.3)
- System.Collections (>= 4.3)
- System.Diagnostics.Debug (>= 4.3)
- System.IO (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Runtime.Handles (>= 4.3)
- System.Runtime.InteropServices (>= 4.3)
- System.Text.Encoding (>= 4.3)
- System.Threading (>= 4.3)
- System.Threading.Tasks (>= 4.3)
- System.IO.FileSystem (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.IO (>= 4.3)
- System.IO.FileSystem.Primitives (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Handles (>= 4.3)
- System.Text.Encoding (>= 4.3)
- System.Threading.Tasks (>= 4.3)
- System.IO.FileSystem.Primitives (4.3)
- System.Runtime (>= 4.3)
- System.IO.FileSystem.Watcher (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.Win32.Primitives (>= 4.3)
- runtime.native.System (>= 4.3)
- System.Collections (>= 4.3)
- System.IO.FileSystem (>= 4.3)
- System.IO.FileSystem.Primitives (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Runtime.Handles (>= 4.3)
- System.Runtime.InteropServices (>= 4.3)
- System.Text.Encoding (>= 4.3)
- System.Threading (>= 4.3)
- System.Threading.Overlapped (>= 4.3)
- System.Threading.Tasks (>= 4.3)
- System.Threading.Thread (>= 4.3)
- System.Linq (4.3)
- System.Collections (>= 4.3)
- System.Diagnostics.Debug (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Linq.Parallel (4.3)
- System.Collections (>= 4.3)
- System.Collections.Concurrent (>= 4.3)
- System.Diagnostics.Debug (>= 4.3)
- System.Diagnostics.Tracing (>= 4.3)
- System.Linq (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Threading (>= 4.3)
- System.Threading.Tasks (>= 4.3)
- System.Memory (4.5.1)
- System.Buffers (>= 4.4)
- System.Numerics.Vectors (>= 4.4)
- System.Runtime.CompilerServices.Unsafe (>= 4.5)
- System.Net.Http (4.3.4)
- Microsoft.NETCore.Platforms (>= 1.1.1)
- runtime.native.System (>= 4.3)
- runtime.native.System.Net.Http (>= 4.3)
- runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2)
- System.Collections (>= 4.3)
- System.Diagnostics.Debug (>= 4.3)
- System.Diagnostics.DiagnosticSource (>= 4.3)
- System.Diagnostics.Tracing (>= 4.3)
- System.Globalization (>= 4.3)
- System.Globalization.Extensions (>= 4.3)
- System.IO (>= 4.3)
- System.IO.FileSystem (>= 4.3)
- System.Net.Primitives (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Runtime.Handles (>= 4.3)
- System.Runtime.InteropServices (>= 4.3)
- System.Security.Cryptography.Algorithms (>= 4.3)
- System.Security.Cryptography.Encoding (>= 4.3)
- System.Security.Cryptography.OpenSsl (>= 4.3)
- System.Security.Cryptography.Primitives (>= 4.3)
- System.Security.Cryptography.X509Certificates (>= 4.3)
- System.Text.Encoding (>= 4.3)
- System.Threading (>= 4.3)
- System.Threading.Tasks (>= 4.3)
- System.Net.Primitives (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
- System.Runtime.Handles (>= 4.3)
- System.Numerics.Vectors (4.5)
- System.Reactive (4.1.2)
- System.Runtime.InteropServices.WindowsRuntime (>= 4.3)
- System.Threading.Tasks.Extensions (>= 4.5.1)
- System.Reactive.Compatibility (4.1.2)
- System.Reactive.Core (>= 4.1.2)
- System.Reactive.Interfaces (>= 4.1.2)
- System.Reactive.Linq (>= 4.1.2)
- System.Reactive.PlatformServices (>= 4.1.2)
- System.Reactive.Providers (>= 4.1.2)
- System.Reactive.Core (4.1.2)
- System.Reactive (>= 4.1.2)
- System.Threading.Tasks.Extensions (>= 4.5.1)
- System.Reactive.Interfaces (4.1.2)
- System.Reactive (>= 4.1.2)
- System.Threading.Tasks.Extensions (>= 4.5.1)
- System.Reactive.Linq (4.1.2)
- System.Reactive (>= 4.1.2)
- System.Threading.Tasks.Extensions (>= 4.5.1)
- System.Reactive.PlatformServices (4.1.2)
- System.Reactive (>= 4.1.2)
- System.Threading.Tasks.Extensions (>= 4.5.1)
- System.Reactive.Providers (4.1.2)
- System.Reactive (>= 4.1.2)
- System.Threading.Tasks.Extensions (>= 4.5.1)
- System.Reflection (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.IO (>= 4.3)
- System.Reflection.Primitives (>= 4.3)
- System.Runtime (>= 4.3)
- System.Reflection.Extensions (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Reflection (>= 4.3)
- System.Runtime (>= 4.3)
- System.Reflection.Metadata (1.6)
- System.Collections.Immutable (>= 1.5)
- System.Reflection.Primitives (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
- System.Reflection.TypeExtensions (4.5.1)
- System.Resources.ResourceManager (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Globalization (>= 4.3)
- System.Reflection (>= 4.3)
- System.Runtime (>= 4.3)
- System.Resources.Writer (4.3)
- System.Collections (>= 4.3)
- System.IO (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Text.Encoding (>= 4.3)
- System.Runtime (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime.CompilerServices.Unsafe (4.5.2)
- System.Runtime.Extensions (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
- System.Runtime.Handles (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
- System.Runtime.InteropServices (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Reflection (>= 4.3)
- System.Reflection.Primitives (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Handles (>= 4.3)
- System.Runtime.InteropServices.RuntimeInformation (4.3)
- runtime.native.System (>= 4.3)
- System.Reflection (>= 4.3)
- System.Reflection.Extensions (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.InteropServices (>= 4.3)
- System.Threading (>= 4.3)
- System.Runtime.InteropServices.WindowsRuntime (4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Loader (4.3)
- System.IO (>= 4.3)
- System.Reflection (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Numerics (4.3)
- System.Globalization (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Runtime.Serialization.Primitives (4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Security.AccessControl (4.5)
- System.Security.Principal.Windows (>= 4.5)
- System.Security.Cryptography.Algorithms (4.3.1)
- Microsoft.NETCore.Platforms (>= 1.1)
- runtime.native.System.Security.Cryptography.Apple (>= 4.3.1)
- runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2)
- System.Collections (>= 4.3)
- System.IO (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Runtime.Handles (>= 4.3)
- System.Runtime.InteropServices (>= 4.3)
- System.Runtime.Numerics (>= 4.3)
- System.Security.Cryptography.Encoding (>= 4.3)
- System.Security.Cryptography.Primitives (>= 4.3)
- System.Text.Encoding (>= 4.3)
- System.Security.Cryptography.Cng (4.5)
- System.Security.Cryptography.Csp (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- System.IO (>= 4.3)
- System.Reflection (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Runtime.Handles (>= 4.3)
- System.Runtime.InteropServices (>= 4.3)
- System.Security.Cryptography.Algorithms (>= 4.3)
- System.Security.Cryptography.Encoding (>= 4.3)
- System.Security.Cryptography.Primitives (>= 4.3)
- System.Text.Encoding (>= 4.3)
- System.Threading (>= 4.3)
- System.Security.Cryptography.Encoding (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3)
- System.Collections (>= 4.3)
- System.Collections.Concurrent (>= 4.3)
- System.Linq (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Runtime.Handles (>= 4.3)
- System.Runtime.InteropServices (>= 4.3)
- System.Security.Cryptography.Primitives (>= 4.3)
- System.Text.Encoding (>= 4.3)
- System.Security.Cryptography.OpenSsl (4.5)
- System.Security.Cryptography.Primitives (4.3)
- System.Diagnostics.Debug (>= 4.3)
- System.Globalization (>= 4.3)
- System.IO (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Threading (>= 4.3)
- System.Threading.Tasks (>= 4.3)
- System.Security.Cryptography.X509Certificates (4.3.2)
- Microsoft.NETCore.Platforms (>= 1.1)
- runtime.native.System (>= 4.3)
- runtime.native.System.Net.Http (>= 4.3)
- runtime.native.System.Security.Cryptography.OpenSsl (>= 4.3.2)
- System.Collections (>= 4.3)
- System.Diagnostics.Debug (>= 4.3)
- System.Globalization (>= 4.3)
- System.Globalization.Calendars (>= 4.3)
- System.IO (>= 4.3)
- System.IO.FileSystem (>= 4.3)
- System.IO.FileSystem.Primitives (>= 4.3)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Extensions (>= 4.3)
- System.Runtime.Handles (>= 4.3)
- System.Runtime.InteropServices (>= 4.3)
- System.Runtime.Numerics (>= 4.3)
- System.Security.Cryptography.Algorithms (>= 4.3)
- System.Security.Cryptography.Cng (>= 4.3)
- System.Security.Cryptography.Csp (>= 4.3)
- System.Security.Cryptography.Encoding (>= 4.3)
- System.Security.Cryptography.OpenSsl (>= 4.3)
- System.Security.Cryptography.Primitives (>= 4.3)
- System.Text.Encoding (>= 4.3)
- System.Threading (>= 4.3)
- System.Security.Principal.Windows (4.5.1)
- System.Text.Encoding (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
- System.Text.Encoding.CodePages (4.5)
- System.Runtime.CompilerServices.Unsafe (>= 4.5)
- System.Text.Encoding.Extensions (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
- System.Text.Encoding (>= 4.3)
- System.Threading (4.3)
- System.Runtime (>= 4.3)
- System.Threading.Tasks (>= 4.3)
- System.Threading.Overlapped (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- System.Resources.ResourceManager (>= 4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Handles (>= 4.3)
- System.Threading.Tasks (4.3)
- Microsoft.NETCore.Platforms (>= 1.1)
- Microsoft.NETCore.Targets (>= 1.1)
- System.Runtime (>= 4.3)
- System.Threading.Tasks.Dataflow (4.9)
- System.Threading.Tasks.Extensions (4.5.1)
- System.Runtime.CompilerServices.Unsafe (>= 4.5)
- System.Threading.Thread (4.3)
- System.Runtime (>= 4.3)
- System.Threading.ThreadPool (4.3)
- System.Runtime (>= 4.3)
- System.Runtime.Handles (>= 4.3)
+ System.Runtime.CompilerServices.Unsafe (6.0)
+ System.Runtime.InteropServices.WindowsRuntime (4.3) - restriction: || (&& (== net6.0) (< netcoreapp3.1)) (== netstandard2.0)
+ System.Runtime (>= 4.3)
+ System.Security.AccessControl (6.0)
+ System.Security.Principal.Windows (>= 5.0) - restriction: || (&& (== net6.0) (>= net461)) (== netstandard2.0)
+ System.Security.Cryptography.Cng (5.0)
+ System.Formats.Asn1 (>= 5.0) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= netcoreapp3.0))
+ System.Security.Cryptography.Pkcs (6.0)
+ System.Buffers (>= 4.5.1) - restriction: || (&& (== net6.0) (< netstandard2.1)) (== netstandard2.0)
+ System.Formats.Asn1 (>= 6.0)
+ System.Memory (>= 4.5.4) - restriction: || (&& (== net6.0) (< netstandard2.1)) (== netstandard2.0)
+ System.Security.Cryptography.Cng (>= 5.0) - restriction: || (&& (== net6.0) (< netcoreapp3.1)) (&& (== net6.0) (< netstandard2.1)) (== netstandard2.0)
+ System.Security.Cryptography.ProtectedData (6.0)
+ System.Security.Cryptography.Xml (6.0)
+ System.Memory (>= 4.5.4) - restriction: == netstandard2.0
+ System.Security.AccessControl (>= 6.0)
+ System.Security.Cryptography.Pkcs (>= 6.0)
+ System.Security.Permissions (6.0)
+ System.Security.AccessControl (>= 6.0)
+ System.Windows.Extensions (>= 6.0) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= netcoreapp3.1))
+ System.Security.Principal.Windows (5.0)
+ System.Text.Encoding.CodePages (6.0)
+ System.Runtime.CompilerServices.Unsafe (>= 6.0)
+ System.Text.Encodings.Web (6.0) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= net472)) (&& (== netstandard2.0) (>= net6.0))
+ System.Runtime.CompilerServices.Unsafe (>= 6.0)
+ System.Text.Json (6.0.3) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= net472)) (&& (== netstandard2.0) (>= net6.0))
+ System.Runtime.CompilerServices.Unsafe (>= 6.0)
+ System.Text.Encodings.Web (>= 6.0)
+ System.Threading.Tasks.Dataflow (6.0)
+ System.Threading.Tasks.Extensions (4.5.4) - restriction: || (&& (== net6.0) (>= net472)) (&& (== net6.0) (< netcoreapp3.1)) (&& (== net6.0) (>= uap10.1)) (== netstandard2.0)
+ System.Runtime.CompilerServices.Unsafe (>= 4.5.3) - restriction: || (&& (== net6.0) (>= net461)) (&& (== net6.0) (< netcoreapp2.1)) (&& (== net6.0) (< netstandard1.0)) (&& (== net6.0) (< netstandard2.0)) (&& (== net6.0) (>= wp8)) (== netstandard2.0)
+ System.Windows.Extensions (6.0) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= netcoreapp3.1))
+ System.Drawing.Common (>= 6.0) - restriction: || (== net6.0) (&& (== netstandard2.0) (>= netcoreapp3.1))
diff --git a/fake.cmd b/fake.cmd
deleted file mode 100755
index 2f757d1..0000000
--- a/fake.cmd
+++ /dev/null
@@ -1,7 +0,0 @@
-SET TOOL_PATH=.fake
-
-IF NOT EXIST "%TOOL_PATH%\fake.exe" (
- dotnet tool install fake-cli --tool-path ./%TOOL_PATH%
-)
-
-"%TOOL_PATH%/fake.exe" %*
\ No newline at end of file
diff --git a/fake.sh b/fake.sh
deleted file mode 100755
index f6bbfcc..0000000
--- a/fake.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/usr/bin/env bash
-export DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER=0
-
-set -eu
-set -o pipefail
-
-# liberated from https://stackoverflow.com/a/18443300/433393
-realpath() {
- OURPWD=$PWD
- cd "$(dirname "$1")"
- LINK=$(readlink "$(basename "$1")")
- while [ "$LINK" ]; do
- cd "$(dirname "$LINK")"
- LINK=$(readlink "$(basename "$1")")
- done
- REALPATH="$PWD/$(basename "$1")"
- cd "$OURPWD"
- echo "$REALPATH"
-}
-
-TOOL_PATH=$(realpath .fake)
-FAKE="$TOOL_PATH"/fake
-
-if ! [ -e "$FAKE" ]
-then
- dotnet tool install fake-cli --tool-path "$TOOL_PATH"
-fi
-"$FAKE" "$@"
diff --git a/nuget.config b/nuget.config
deleted file mode 100755
index fa83729..0000000
--- a/nuget.config
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/src/FSharp.CommandLine/FSharp.CommandLine.fsproj b/src/FSharp.CommandLine/FSharp.CommandLine.fsproj
deleted file mode 100755
index ebf263e..0000000
--- a/src/FSharp.CommandLine/FSharp.CommandLine.fsproj
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
- netstandard2.0;net46
- A framework for building command line application in F#. Supports command line option parsing, type-safe scanf, monadic command construction, automatic help & shell completion generation, and so on.
- cannorin
-
- (c) cannorin 2017-2019
- https://github.com/cannorin/FSharp.CommandLine
- https://github.com/cannorin/FSharp.CommandLine/blob/master/LICENSE.txt
- fsharp commandline parsing framework
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/FSharp.CommandLine/abstraction.fs b/src/FSharp.CommandLine/abstraction.fs
deleted file mode 100755
index 7382ec6..0000000
--- a/src/FSharp.CommandLine/abstraction.fs
+++ /dev/null
@@ -1,54 +0,0 @@
-namespace FSharp.CommandLine.Internals
-
-module Abstraction =
- type State<'Args, 'a> = 'Args -> ('a * 'Args)
-
- type StateConfig<'Config, 'Args, 'a> = {
- config: 'Config -> 'Config
- func: State<'Args, 'a>
- }
-
- module StateConfig =
- let inline scbind (f: 'a -> StateConfig<'Config, 'Args, 'b>) (g: 'Config -> 'Config) (m: StateConfig<'Config, 'Args, 'a>) =
- {
- config = m.config >> g
- func =
- fun args ->
- let (a, args) = m.func args
- (f a).func args
- }
-
- let inline returnValue (a: 'a) : StateConfig<_, _, 'a> =
- {
- config = id
- func = fun args -> (a, args)
- }
-
- let inline returnWith (f: unit -> 'a) : StateConfig<_, _, 'a> =
- {
- config = id
- func = fun args -> (f(), args)
- }
-
- let inline bind f m = m |> scbind f id
-
- let inline mapConfig g m = m |> scbind returnValue g
-
- let inline map f m = m |> bind (f >> returnValue)
-
- let inline zip (m: StateConfig<_, _, 'a>) (n: StateConfig<_, _, 'b>) (f: 'a -> 'b -> 'c) =
- scbind (fun a ->
- {
- config = id
- func = fun args -> let (b, args) = n.func args in (f a b, args)
- })
- n.config
- m
-
- let inline combine (a: StateConfig<_,_,_>) (b: StateConfig<_,_,_>) = zip a b (fun _ b -> b)
-
- let args =
- {
- config = id
- func = fun args -> (args, args)
- }
diff --git a/src/FSharp.CommandLine/basictypes.fs b/src/FSharp.CommandLine/basictypes.fs
deleted file mode 100755
index dff9c97..0000000
--- a/src/FSharp.CommandLine/basictypes.fs
+++ /dev/null
@@ -1,160 +0,0 @@
-namespace FSharp.CommandLine
-
-[]
-module BasicTypes =
- open FSharp.CommandLine.Internals.Abstraction
- open System.Runtime.CompilerServices
-
- type Args = string list
-
- type HelpElement =
- /// prints `usage: $(command name) $(args)`.
- | HelpUsage
- /// prints `usage: $(command name) $(args)` of which `args` can be customized.
- | HelpUsageCustomArgs of args: string list
- /// prints a string.
- | HelpRawString of text: string
- /// prints the infomation of all the subcommands.
- | HelpAllSubcommands
- /// prints the infomation of the specified subcommands.
- | HelpSpecificSubcommands of names: string list
- /// prints the infomation of all the command options.
- | HelpAllOptions
- /// prints the infomation of the specified command options.
- | HelpSpecificOptions of namesWithoutHyphen: string list
- /// prints elements as a section. the content will be indented.
- /// nested sections make the indentation deeper.
- | HelpSection of sectionName: string * sectionBody: seq
- /// prints an empty line.
- | HelpEmptyLine
-
- module internal Seq =
- let inline snoc x xs = seq { yield! xs; yield x }
-
- []
- type HelpBuilder =
- member inline __.For (_, _) = failwith "Not supported"
- member inline __.Yield _ : HelpElement seq = Seq.empty
- /// prints `usage: $(command name) $(args)`.
- []
- member inline __.Usage xs = xs |> Seq.snoc HelpUsage
- /// prints `usage: $(command name) $(args)` of which `args` can be customized.
- []
- member inline __.UsageWithCustomArgs (xs, argNames) = xs |> Seq.snoc (HelpUsageCustomArgs argNames)
- /// prints a string.
- []
- member inline __.RawText (xs, str) = xs |> Seq.snoc (HelpRawString str)
- /// prints the infomation of all the subcommands.
- []
- member inline __.Subcommands xs = xs |> Seq.snoc HelpAllSubcommands
- /// prints the infomation of the specified subcommands.
- []
- member inline __.SpecificSubcommands (xs, cmds) = xs |> Seq.snoc (HelpSpecificSubcommands cmds)
- /// prints the infomation of all the command options.
- []
- member inline __.Options xs = xs |> Seq.snoc HelpAllOptions
- /// prints the infomation of the specified command options.
- []
- member inline __.SpecificOptions (xs, opts) = xs |> Seq.snoc (HelpSpecificOptions opts)
- /// prints elements as a section. the content will be indented.
- /// nested sections make the indentation deeper.
- []
- member inline __.Section (xs, sectionName, section) = xs |> Seq.snoc (HelpSection(sectionName, section))
- /// prints elements as a section when the condition holds. the content will be indented.
- /// nested sections make the indentation deeper.
- []
- member inline __.ConditionalSection (xs, sectionName, cond, section) =
- if cond() then
- xs |> Seq.snoc (HelpSection(sectionName, section))
- else
- xs
- /// prints an empty line.
- []
- member inline __.EmptyLine xs = xs |> Seq.snoc HelpEmptyLine
-
- let helpText = HelpBuilder ()
-
- type CommandSuggestion =
- /// suggests a set of string.
- | Values of string list
- /// suggests a set of string with description.
- | ValuesWithDescription of (string * string) list
- /// suggests files optionally with pattern.
- | Files of pattern: string option
- /// suggests directories.
- | Directories of pattern: string option
- /// suggests a command option.
- | OptionSuggestion of (string list) * string
- /// prints a message.
- | Message of string
-
- type CommandOptionSummary = {
- names: string list;
- description: string;
- isFlag: bool;
- paramNames: (string list) list
- isMatch: string list -> string list option
- genSuggestions: string option -> CommandSuggestion list
- }
- with
- member this.Param =
- let rec print eq xss =
- let heads = xss |> List.map List.tryHead
- if heads |> List.exists Option.isSome then
- let isOptional = heads |> List.exists Option.isNone
- let groups = xss |> List.filter (List.isEmpty >> not)
- |> List.groupBy List.head
- |> List.map (fun (g, xs) -> sprintf "%s%s" g (xs |> List.map List.tail |> print ""))
- let s =
- if List.length groups > 1 then
- let s = groups |> String.concat "|"
- if isOptional then s else sprintf "{%s}" s
- else
- groups |> String.concat ""
- if isOptional then sprintf "[%s%s]" eq s else sprintf "%s%s"eq s
- else
- ""
- in print "=" (this.paramNames |> List.rev)
-
- member this.NameRepresentations =
- this.names |> List.collect (function
- | x when x.Length = 1 ->
- [ "-"; "/" ] |> List.map (fun prefix -> sprintf "%s%s" prefix x)
- | x ->
- [ "--"; "/" ] |> List.map (fun prefix -> sprintf "%s%s" prefix x))
-
- member this.Print () =
- let o x = if this.isFlag then sprintf "%s[+|-]" x else sprintf "%s%s" x this.Param
- ((this.NameRepresentations |> List.filter (String.startsWith "-") |> String.concat ", " |> o), this.description)
-
- []
- type CommandSummary = {
- name: string;
- displayName: string option;
- description: string;
- paramNames: (string list) option
- help: HelpElement seq option
- genSuggestions: Args -> CommandSuggestion list
- }
-
- []
- type CommandInfo = {
- summary: CommandSummary
- options: CommandOptionSummary list
- subcommands: Command list
- }
- and Command<'a> = StateConfig
-
- type CommandInfo with
- static member empty =
- {
- summary = Unchecked.defaultof
- options = []
- subcommands = []
- }
-
- []
- type ICommandExt() =
- []
- static member inline Summary(x: Command<_>) =
- (x.config CommandInfo.empty).summary
diff --git a/src/FSharp.CommandLine/commands.fs b/src/FSharp.CommandLine/commands.fs
deleted file mode 100755
index 034bffd..0000000
--- a/src/FSharp.CommandLine/commands.fs
+++ /dev/null
@@ -1,185 +0,0 @@
-namespace FSharp.CommandLine
-
-[]
-module Commands =
- open System
- open FSharp.CommandLine.Options
- open FSharp.CommandLine.Generators
- open FSharp.CommandLine.Internals.Abstraction
-
- let inline private mapSummary f co =
- co |> StateConfig.mapConfig (fun cfg -> { cfg with summary = f cfg.summary })
-
- type CommandBuilder() =
- member inline __.Bind (c, f) : Command<_> = StateConfig.bind f c
- member inline __.Return x = StateConfig.returnValue x
- member inline __.For (c, f) : Command<_> = StateConfig.bind f c
- member inline __.Yield x = StateConfig.returnValue x
- member inline __.ReturnFrom (x: Command<_>) = x
- member inline __.Combine (a, b) : Command<_> = StateConfig.combine a b
- member inline __.Combine (f: unit -> _, b: Command<_>) : Command<_> = StateConfig.combine (f()) b
- member inline __.Combine (a: Command<_>, f: unit -> _) : Command<_> = StateConfig.combine a (f())
- member inline __.Zero () = StateConfig.returnValue ()
- member inline __.Delay (f: unit -> Command<_>) = f
- member inline __.Undelay x : Command<_> = x()
- member inline __.Run f : Command<_> = f()
- member inline __.TryWith (f, h) = try f() with exn -> h exn
- member inline __.TryFinally (f, h) = try f() finally h()
- member inline this.Using (disp: #System.IDisposable, m) =
- this.TryFinally(
- this.Delay(fun () -> m disp),
- fun () -> dispose disp
- )
- member inline this.While (cond, m: unit -> Command<_>) =
- let rec loop cond m : Command<_> =
- if cond () then this.Combine(this.Undelay m, loop cond m)
- else this.Zero ()
- loop cond m
- member inline this.For (xs: #seq<_>, exec) =
- this.Using(
- (xs :> seq<_>).GetEnumerator(),
- fun en ->
- this.While(
- en.MoveNext,
- this.Delay(fun () -> exec en.Current))
- )
- /// uses a command option.
- []
- member inline __.UseOption (co: Command<'a>, opt: #ICommandOption<'b>, f: 'a -> 'b -> 'c) =
- {
- config = co.config >> opt.Config
- func =
- fun args ->
- let (a, args) = co.func args
- let (b, args) = opt.Parse args
- (f a b, args)
- }
- /// imports a command to this command. will inherit options and other metadatas.
- []
- member inline __.ImportCommand (c1, c2, f) : Command<_> = StateConfig.zip c1 c2 f
- /// required. sets the name of the command. will also be used when this command is
- /// a subcommand of the other one.
- []
- member inline __.Name (co, x) =
- co |> mapSummary (fun s -> { s with name = x })
- /// optional. sets the name of the command that will be displayed in the help text.
- /// the one speficied by `name` will be used if not specified.
- []
- member inline __.DisplayName (co, n) =
- co |> mapSummary (fun s -> { s with displayName = Some n })
- /// required. sets the description of the command.
- []
- member inline __.Description (co, x) =
- co |> mapSummary (fun s -> { s with description = x })
- /// optional. speficies the suggestions it will generate.
- []
- member inline __.Suggests (co: Command<_>, f) =
- co |> mapSummary (fun s -> { s with genSuggestions = f })
- /// optional. customizes the help text.
- []
- member inline __.Help (co: Command<_>, xs: HelpElement seq) =
- co |> mapSummary (fun s -> { s with help = Some xs })
- []
- []
- member inline __.Preprocess xs = xs
- /// optional. specifies the subcommands.
- []
- member inline __.Subcommands (co, xs) =
- {
- config =
- fun cfg ->
- let cfg = co.config cfg
- { cfg with subcommands = cfg.subcommands @ xs }
- func =
- fun args ->
- let sc =
- match args with
- | h :: _ ->
- List.tryFind (fun (x:Command<_>) -> x.Summary().name = h) xs
- | _ -> None
- if sc.IsSome then
- let (code, _) = sc.Value.func (List.tail args)
- RequestExit code |> raise
- else
- co.func args
- }
-
- let command = CommandBuilder ()
-
- module Command =
- let args : Command = StateConfig.args
- let inline bind f m : Command<_> = StateConfig.bind f m
- let inline returnValue x : Command<_> = StateConfig.returnValue x
- let inline returnWith f : Command<_> = StateConfig.returnWith f
- let inline map f m : Command<_> = StateConfig.map f m
- let inline mapInfo f m : Command<_> = StateConfig.mapConfig f m
- let inline zip a b f : Command<_> = StateConfig.zip a b f
- let inline combine a b : Command<_> = StateConfig.combine a b
-
- let private runMain args (cmd: Command) =
- match args |> List.ofArray with
- | OptionParse ReservedCommandOptions.suggestOption (sug, rest) ->
- Suggestions.generate rest cmd
- |> Suggestions.print (SuggestionBackends.findByName sug)
- |> printfn "%A"
- (0, [])
- | OptionParse ReservedCommandOptions.helpOption (true, rest) ->
- for line in Help.generate rest cmd do
- printfn "%s" line
- (0, [])
- | args ->
- cmd.func args
-
- #if DEBUG
- let runAsEntryPointDebug args (cmd: Command) = runMain args cmd
- #endif
-
- /// executes the command as an entry point:
- ///
- /// ```
- /// []
- /// let main argv =
- /// Command.runAsEntryPoint argv command
- /// ```
- let runAsEntryPoint args (cmd: Command) =
- try
- runMain args cmd |> fst
- with
- | RequestExit code -> code
- | RequestShowHelp msg ->
- cprintfn ConsoleColor.Red "error: %s\n" msg
- for line in Help.generate (args |> List.ofArray) cmd do
- printfn "%s" line
- -1
- | OptionParseFailed (_, msg)
- | CommandExecutionFailed msg -> cprintfn ConsoleColor.Red "error: %s\n" msg; -1
- | e -> reraise' e
-
- /// stops the execution immediately and then exits with the specified code.
- let inline exit code =
- RequestExit code |> raise
-
- /// stops the execution immediately and then exits with the specified error message and code `-1`.
- let inline fail msg =
- CommandExecutionFailed msg |> raise
-
- /// stops the execution immediately and then exits with the specified error message and code `-1`.
- let inline failf fmt =
- Printf.kprintf (fun msg -> CommandExecutionFailed msg |> raise ) fmt
-
- /// if there are remaining unknown options, then stops the execution
- /// immediately and then exits with code `-1`.
- let failOnUnknownOptions () =
- command {
- let! argv = StateConfig.args in
- let uks = argv |> CommandOption.getRemainingOptions in
- if uks |> List.isEmpty then
- return ()
- else
- sprintf "unknown option: '%s'" (List.head uks) |> CommandExecutionFailed |> raise
- }
-
- /// shows the error message and the help of the current (sub)command, then exits with code `-1`.
- let inline failShowingHelp message =
- RequestShowHelp message |> raise
-
diff --git a/src/FSharp.CommandLine/extensions.fs b/src/FSharp.CommandLine/extensions.fs
deleted file mode 100755
index 9f19065..0000000
--- a/src/FSharp.CommandLine/extensions.fs
+++ /dev/null
@@ -1,25 +0,0 @@
-namespace FSharp.CommandLine
-
-[]
-module InternalExtensions =
- open Microsoft.FSharp.Quotations
- open Microsoft.FSharp.Quotations.Patterns
- open Microsoft.FSharp.Linq.RuntimeHelpers
-
- type FuncHelper = private | FuncHelper with
- static member compileFunc (x: Expr<'a -> 'b>) =
- LeafExpressionConverter.EvaluateQuotation x :?> ('a -> 'b)
-
- static member getFirstArgumentName (x: Expr<'a -> 'b>) =
- let rec gn tupleArgName = function
- | Let (v, TupleGet(Var tn, index), body) when (tupleArgName = tn.Name) ->
- (index, v.Name) :: gn tupleArgName body
- | _ -> []
- in
- match x with
- | Lambda (v, e) ->
- match (gn v.Name e) with
- | [] -> Some [v.Name]
- | xs -> xs |> List.sortBy fst |> List.map snd |> Some
- | _ -> None
-
diff --git a/src/FSharp.CommandLine/optionValues.fs b/src/FSharp.CommandLine/optionValues.fs
deleted file mode 100755
index acb1917..0000000
--- a/src/FSharp.CommandLine/optionValues.fs
+++ /dev/null
@@ -1,105 +0,0 @@
-namespace FSharp.CommandLine
-
-[]
-module OptionValues =
- open System
- open FSharp.Scanf
- open FSharp.Scanf.Optimized
- open Microsoft.FSharp.Quotations
- open System.Text.RegularExpressions
-
- type ValueFormat<'p,'st,'rd,'rl,'t,'a> = {
- format: PrintfFormat<'p,'st,'rd,'rl,'t>
- paramNames: (string list) option
- handler: 't -> 'a
- }
- with
- static member inline construct (this: ValueFormat<_,_,_,_,_,_>) =
- let parser s =
- s |> tryKsscanf this.format this.handler
- |> function Ok x -> Some x | _ -> None
- in
- let formatTokens =
- let defaultNames =
- this.format.GetFormatterNames()
- |> List.map (String.replace ' ' '_' >> String.toUpperInvariant)
- |> List.map (sprintf "%s_VALUE")
- in
- let names = (this.paramNames ?| defaultNames) |> List.map (sprintf "<%s>") in
- this.format.PrettyTokenize names
- in
- (parser, formatTokens)
-
- member this.map ([]mapper: Expr<'a -> 'b>) =
- let mf x = (FuncHelper.compileFunc mapper) x in
- let pns = FuncHelper.getFirstArgumentName mapper in
- { format = this.format; handler = this.handler >> mf; paramNames = pns }
-
- member this.withNames names =
- { this with paramNames = Some names }
-
- member this.asConst value =
- { format = this.format; handler = (fun _ -> value); paramNames = this.paramNames }
-
- let inline format (fmt: PrintfFormat<_,_,_,_,'t>) : ValueFormat<_,_,_,_,'t,'t> =
- { format = fmt; handler = id; paramNames = None }
-
- type ValueRegex<'a> = {
- regex: Regex
- handler: string list -> 'a
- }
- with
- static member construct (this: ValueRegex<_>) =
- let parser (str: string) =
- let m: Match = this.regex.Match(str)
- if m.Success then
- m.Groups
- |> Seq.cast
- |> List.ofSeq
- |> List.zip (this.regex.GetGroupNames() |> List.ofArray)
- |> List.filter (fun (name, _) -> name |> String.forall Char.IsDigit |> not)
- |> List.map (fun (_, x) -> x.Value)
- |> this.handler |> Some
- else None
- let tokens = [to_s this.regex]
- (parser, tokens)
-
- member this.map mapper =
- { regex = this.regex; handler = this.handler >> mapper }
-
- member this.asConst value =
- { regex = this.regex; handler = fun _ -> value }
-
- let inline regex r =
- { regex = Regex(r); handler = id }
-
- type ValueTypedRegex<'a, '_Regex, '_Match > = {
- typedRegex: '_Regex
- handler: '_Match -> 'a
- }
- with
- static member inline construct (this: ValueTypedRegex<_, ^Regex, ^Match>) : _
- when ^Match :> Match =
- let parser str =
- let m = (^Regex: (member TypedMatch: string -> ^Match) this.typedRegex,str)
- if m.Success then
- this.handler m |> Some
- else None
- let tokens = [to_s this.typedRegex]
- (parser, tokens)
-
- member inline this.map mapper =
- { typedRegex = this.typedRegex; handler = this.handler >> mapper }
-
- member inline this.asConst value =
- { typedRegex = this.typedRegex; handler = fun _ -> value }
-
- let inline typedRegex< ^Regex, ^Match when ^Regex: (new: unit -> ^Regex) and ^Regex: (member TypedMatch: string -> ^Match) > : ValueTypedRegex< ^Match, ^Regex, ^Match > =
- { typedRegex = new ^Regex(); handler = id }
-
- let inline asConst value (optionValue: ^X) =
- (^X: (member asConst: _ -> _) optionValue,value)
-
- let inline internal construct (optionValue: ^X) =
- (^X: (static member construct: _ -> _) optionValue)
-
diff --git a/src/FSharp.CommandLine/options.fs b/src/FSharp.CommandLine/options.fs
deleted file mode 100755
index 834fc59..0000000
--- a/src/FSharp.CommandLine/options.fs
+++ /dev/null
@@ -1,435 +0,0 @@
-namespace FSharp.CommandLine
-
-[]
-module rec Options =
- open FSharp.Scanf.Optimized
- open Microsoft.FSharp.Quotations
-
- open CommandOption
-
- /// specify how to treat options like ```-abcd```
- type SingleHyphenStyle =
- /// treat ```-abcd``` as ```--abcd```
- | SingleLong
- /// treat ```-abcd``` as ```-a bcd```
- | SingleShort
- /// treat ```-abcd``` as ```-a -b -c -d```
- | MergedShort
-
- []
- type CommandOptionNoArgProvided<'a> =
- | UseDefault of 'a
- | JustFail
-
- []
- type CommandOptionKind<'a> =
- | Flag of (bool -> 'a)
- | TakingValueWith of CommandOptionNoArgProvided<'a> * (string -> 'a option) list
-
- type ICommandOption<'a> =
- abstract member Parse: string list -> ('a * string list)
- abstract member Config: CommandInfo -> CommandInfo
- abstract member Summary: CommandOptionSummary
-
- /// represents a command option parser that tries to parse the arguments
- /// and returns an optional result value.
- []
- type CommandOption<'a> = {
- baseSummary: CommandOptionSummary
- kind: CommandOptionKind<'a>
- style: SingleHyphenStyle
- }
- with
- member this.Summary =
- let self = this
- {
- this.baseSummary with
- isMatch =
- fun argv ->
- match (parseImpl self argv) with
- | (Some _, rem) -> Some rem
- | (None, _) -> None
- }
- member this.Parse argv = parseImpl this argv
- interface ICommandOption<'a option> with
- member this.Summary = this.Summary
- member this.Parse argv = parseImpl this argv
- member this.Config cfg =
- {
- cfg with
- options = this.Summary :: cfg.options
- }
-
- /// represents a command option of which behavior and/or functionality are augmented.
- /// (e.g. can parse multiple occurrence of the option at once)
- []
- type AugmentedCommandOption<'a, 'b> = {
- orig: ICommandOption<'a>
- augmenter: ICommandOption<'a> -> Args -> ('b * Args)
- }
- with
- interface ICommandOption<'b> with
- member this.Summary = this.orig.Summary
- member this.Parse argv = this.augmenter this.orig argv
- member this.Config cfg = (this.orig :> ICommandOption<_>).Config cfg
-
- let inline private defaultCO () =
- {
- baseSummary =
- {
- names = [];
- description = "";
- isFlag = false;
- paramNames = [];
- isMatch = fun _ -> None
- genSuggestions = (fun _ -> [])
- };
- kind = TakingValueWith (JustFail, []);
- style = MergedShort
- }
-
- let inline private defaultCF () =
- {
- baseSummary =
- {
- names = [];
- description = "";
- isFlag = true;
- paramNames = [];
- isMatch = fun _ -> None
- genSuggestions = (fun _ -> [])
- };
- kind = Flag id;
- style = MergedShort
- }
-
-
- module ReservedCommandOptions =
- let helpOption =
- {
- baseSummary =
- {
- names = ["?"; "h"; "help"]
- description = "display this help usage."
- isFlag = false
- paramNames = []
- isMatch = fun _ -> None
- genSuggestions = (fun _ -> [])
- }
- kind = Flag id
- style = MergedShort
- }
-
- let suggestOption =
- {
- baseSummary =
- {
- names = ["generate-suggestions"; "generate-suggestions-incomplete"]
- description = ""
- isFlag = false
- paramNames = [["name"]]
- isMatch = fun _ -> None
- genSuggestions = (fun _ -> [])
- }
- kind = TakingValueWith (UseDefault "zsh", [Some])
- style = MergedShort
- }
-
- []
- type CommandOptionBuilder<'a>(dc: unit -> CommandOption<'a>) =
- member __.For (_, _) = failwith "Not supported"
- member __.Yield _ = dc ()
- /// required.
- /// specifies the option's names. hyphens should not be included,
- /// as they will automatically be handled depending on
- /// the length of the name and optionally the `style` command.
- []
- member __.Names (co, x) = { co with baseSummary = { co.baseSummary with names = x } }
- []
- member __.Description (co, x) = { co with baseSummary = { co.baseSummary with description = x } }
- /// required for command option.
- /// specifies the format of the argument. for example:
- /// `takes (format("%s").map(fun str -> someFunc str))`
- []
- member inline __.Takes (co: CommandOption<'a>, x) =
- let (f, ts) = construct x in
- { co with
- kind =
- match co.kind with
- | TakingValueWith (d, xs) -> TakingValueWith (d, List.append xs [f])
- | _ -> TakingValueWith (JustFail, [f]);
- baseSummary =
- { co.baseSummary with
- paramNames = ts :: co.baseSummary.paramNames
- }
- }
- /// `takesFormat fmt (fun .. -> ..)` is a shorthand for
- /// `takes (format(fmt).map(fun .. -> ..))`.
- []
- member inline __.TakesFormat (co: CommandOption<_>, fmt: PrintfFormat<_,_,_,_,_>, []mapper: Expr<_ -> _>) =
- let mf x = (FuncHelper.compileFunc mapper) x in
- let pns = FuncHelper.getFirstArgumentName mapper in
- let x =
- { format = fmt; handler = mf; paramNames = pns }
- let (f, ts) = construct x in
- { co with
- kind =
- match co.kind with
- | TakingValueWith (d, xs) -> TakingValueWith (d, List.append xs [f])
- | _ -> TakingValueWith (JustFail, [f]);
- baseSummary =
- { co.baseSummary with
- paramNames = ts :: co.baseSummary.paramNames
- }
- }
- /// optional.
- /// makes the option's argument optional, and specifies the default value
- /// that will be used when the argument is not provided.
- []
- member __.DefaultValue (co: CommandOption<'a>, value: 'a) =
- { co with
- kind =
- match co.kind with
- | TakingValueWith (_, xs) -> TakingValueWith (UseDefault value, xs)
- | x -> x
- }
- /// optional.
- /// specifies the command suggestions this option will generate.
- []
- member __.Suggests (co, f) = { co with baseSummary = { co.baseSummary with genSuggestions=f } }
- /// optional.
- /// specify how to treat options like ```-abcd```.
- /// the default value is `MergedShort`.
- []
- member __.Style (co, st) = { co with style = st }
-
- let commandOption<'a> = CommandOptionBuilder<'a> defaultCO
- let commandFlag = CommandOptionBuilder defaultCF
-
- type Command =
- /// short-form definition of command option
- static member inline option (_names, _format, ?_descr, ?defVal, ?_style) =
- let mutable co =
- commandOption {
- names _names
- takes (format _format)
- description (_descr ?| "")
- style (_style ?| SingleHyphenStyle.MergedShort)
- }
- defVal |> Option.iter (fun x -> co <- commandOption<_>.DefaultValue(co, x))
- co
-
- /// short-form definition of command flag
- static member inline flag (_names, ?_descr, ?_style) =
- commandFlag {
- names _names
- description (_descr ?| "")
- style (_style ?| SingleHyphenStyle.MergedShort)
- }
-
- type private RefinedToken =
- | RFlag of string
- | RFlagDisable of string
- | RFlagAndValue of string * string
- | RMaybeCombinedFlag of string
- | RMaybeCombinedFlagAndValue of string * string
- | RValue of string
- | RIgnoreAfter
- with
- override this.ToString() =
- match this with
- | RFlag s -> sprintf "--%s" s
- | RFlagDisable s -> sprintf "-%s-" s
- | RFlagAndValue (s, v) -> sprintf "--%s=%s" s v
- | RMaybeCombinedFlag s -> sprintf "-%s" s
- | RMaybeCombinedFlagAndValue (s, v) -> sprintf "-%s=%s" s v
- | RValue s -> s
- | RIgnoreAfter -> "--"
-
- let private optionForms = [
- tryKsscanf "--" (fun () -> RIgnoreAfter)
- tryKsscanf "-%c" (RFlag << to_s);
- tryKsscanf "-%c=%s" (Tuple.map2 to_s id >> RFlagAndValue);
- tryKsscanf "--%s=%s" RFlagAndValue;
- tryKsscanf "/%s=%s" RFlagAndValue;
- tryKsscanf "--%s" RFlag;
- tryKsscanf "-%c+" (RFlag << to_s);
- tryKsscanf "-%c-" (RFlagDisable << to_s);
- tryKsscanf "-%s=%s" RMaybeCombinedFlagAndValue;
- tryKsscanf "-%s" RMaybeCombinedFlag;
- tryKsscanf "/%s" RFlag;
- tryKsscanf "%s" RValue
- ]
-
- let rec private tokenize argv =
- seq {
- if List.isEmpty argv then
- yield! Seq.empty
- else
- let (h, t) = (List.head argv, List.tail argv)
- let ro = optionForms |> List.map (fun f -> f h)
- |> List.choose (function Ok x -> Some x | _ -> None)
- |> List.tryHead
- if Option.isSome ro then
- yield ro.Value;
- yield!
- match ro.Value with
- | RIgnoreAfter -> t |> Seq.map RValue
- | _ -> tokenize t
- else
- yield! Seq.empty
- }
-
- module CommandOption =
- /// gets the arguments which look like (will potentially be recognized by the parser as)
- /// a command option.
- let getRemainingOptions argv =
- argv |> tokenize |> List.ofSeq
- |> List.choose (function RIgnoreAfter | RValue _ -> None | x -> Some x)
- |> List.map to_s
-
- let internal parseImpl (opt: CommandOption<'a>) argv =
- let inline isSingle s = String.length s = 1
- let inline matches x = opt.baseSummary.names |> List.contains x
- let shortNames = opt.baseSummary.names |> List.filter isSingle
- let opf msg = OptionParseFailed(opt.baseSummary, msg)
-
- let tokens = tokenize argv |> List.ofSeq
- let rec find ts =
- match opt.kind with
- | Flag f ->
- let inline f x = f x |> Some
- match ts with
- | RFlag x :: rest when matches x -> (f true, rest)
- | RFlagDisable x :: rest when matches x -> (f false, rest)
- | RFlagAndValue (x, _) :: _ when matches x ->
- sprintf "'%s' is a flag and does not take an argument" x |> opf |> raise
- | RMaybeCombinedFlag xs :: rest & x :: _ ->
- match opt.style with
- | MergedShort when shortNames |> List.exists xs.Contains ->
- let c = shortNames |> List.find xs.Contains
- (f true, RMaybeCombinedFlag (xs.Replace(c, "")) :: rest)
- | SingleLong when matches xs -> (f true, rest)
- | SingleShort when shortNames |> List.exists xs.StartsWith ->
- sprintf "'%c' is a flag and does not take an argument" (xs.[0]) |> opf |> raise
- | _ -> find rest |> Tuple.map2 id (fun rest' -> x :: rest')
- | RMaybeCombinedFlagAndValue (xs, v) :: rest & x :: _ ->
- match opt.style with
- | MergedShort when shortNames |> List.exists xs.Contains ->
- let c = shortNames |> List.find xs.Contains
- if shortNames |> List.exists xs.EndsWith then
- sprintf "'%s' is a flag and does not take an argument" c |> opf |> raise
- else
- (f true, RMaybeCombinedFlagAndValue(xs.Replace(c, ""), v) :: rest)
- | SingleLong when matches xs ->
- sprintf "'%s' is a flag and does not take an argument" xs |> opf |> raise
- | SingleShort -> sprintf "invalid option: '-%s=%s'" xs v |> opf |> raise
- | _ -> find rest |> Tuple.map2 id (fun rest' -> x :: rest')
- | x :: rest -> find rest |> Tuple.map2 id (fun rest' -> x :: rest')
- | [] -> (None, [])
- | TakingValueWith (na, fs) ->
- let inline tryReturn v name =
- match (fs |> List.map (fun f -> f v) |> List.choose id |> List.tryHead) with
- | Some x -> Some x
- | None ->
- sprintf "the value '%s' is invalid for the option '%s'" v name |> opf |> raise
- let inline tryDefault name =
- match na with
- | UseDefault x -> Some x
- | JustFail ->
- sprintf "a value is missing for the option '%s'" name |> opf |> raise
- match ts with
- | RFlag x :: RValue v :: rest
- | RFlagAndValue (x, v) :: rest when matches x -> (tryReturn v x, rest)
- | RFlag x :: rest when matches x -> (tryDefault x, rest)
- | RFlagDisable x :: _ when matches x ->
- sprintf "a value is missing for the option '%s'" x |> opf |> raise
- | RMaybeCombinedFlag xs :: RValue v :: rest & x :: _ :: _->
- match opt.style with
- | MergedShort when shortNames |> List.exists xs.EndsWith ->
- let c = shortNames |> List.find xs.EndsWith
- (tryReturn v c, RMaybeCombinedFlag (xs.Replace(c, "")) :: rest)
- | MergedShort when shortNames |> List.exists xs.Contains ->
- let c = shortNames |> List.find xs.Contains
- (tryDefault c, RMaybeCombinedFlag (xs.Replace(c, "")) :: RValue v :: rest)
- | SingleShort when shortNames |> List.exists xs.StartsWith ->
- let c = shortNames |> List.find xs.StartsWith
- let v' = xs.Substring(1)
- (tryReturn v' c, RValue v :: rest)
- | SingleLong when matches xs ->
- (tryReturn v xs, rest)
- | _ -> find rest |> Tuple.map2 id (fun rest' -> x :: RValue v :: rest')
- | RMaybeCombinedFlagAndValue (xs, v) :: rest & x :: _ ->
- match opt.style with
- | MergedShort when shortNames |> List.exists xs.EndsWith ->
- let c = shortNames |> List.find xs.EndsWith
- (tryReturn v c, RMaybeCombinedFlag (xs.Replace(c, "")) :: rest)
- | MergedShort when shortNames |> List.exists xs.Contains ->
- let c = shortNames |> List.find xs.Contains
- (tryDefault c, RMaybeCombinedFlagAndValue (xs.Replace(c, ""), v) :: rest)
- | SingleLong when matches xs ->
- (tryReturn v xs, rest)
- | SingleShort -> sprintf "invalid option: '-%s=%s'" xs v |> opf |> raise
- | _ -> find rest |> Tuple.map2 id (fun rest' -> x :: rest')
- | x :: rest -> find rest |> Tuple.map2 id (fun rest' -> x :: rest')
- | [] -> (None, [])
- find tokens |> Tuple.map2 id (List.map to_s)
-
- /// given a command option and arguments, applies the parser to the arguments
- /// and returns the parsed result and the remaining arguments.
- let inline parse (opt: #ICommandOption<_>) argv = opt.Parse argv
-
- /// given a command option and arguments, applies the parser to the arguments until it fails
- /// and returns the results and the remaining arguments.
- let parseMany (opt: #ICommandOption<_>) argv =
- let rec p xs =
- seq {
- yield!
- match (opt.Parse xs) with
- | (Some x, rest) ->
- seq { yield (x, rest); yield! p rest }
- | (None, _) ->
- Seq.empty
- }
- let x = p argv
- (x |> Seq.map fst |> List.ofSeq, x |> Seq.map snd |> Seq.tryLast ?| argv)
-
- /// given a command option, augments its functionality by modifying
- /// its behavior. both the original command option and the arguments which
- /// will be passed at the execution time are available.
- let inline augment f c = { orig=c; augmenter=f }
- let inline map f c =
- let ac = augment (fun c args -> c.Parse args) c
- {
- orig=ac.orig;
- augmenter=(fun o x -> ac.augmenter o x |> Tuple.map2 f id)
- }
-
- /// given a command option, returns a new command option that parses
- /// zero or more occurrence of that command option.
- let inline zeroOrMore co =
- co |> augment parseMany
-
- /// given a command option, returns a new command option that fails
- /// if there are more than one occurrence of that command option.
- let inline zeroOrExactlyOne co =
- co |> zeroOrMore
- |> map (function
- | [] -> None
- | x :: [] -> Some x
- | _ ->
- let msg = sprintf "the option '%s' should be provided only once"
- (co.Summary.NameRepresentations |> List.head)
- OptionParseFailed (co.Summary, msg) |> raise
- )
-
- /// given a command option, returns a new command option that returns
- /// the specified default value if there is no occurence.
- let inline whenMissingUse defaultValue co =
- co |> map (function Some x -> x | None -> defaultValue)
-
- /// an active pattern to parse the arguments using the command option
- /// and gets the result and the remaining arguments.
- let inline (|OptionParse|_|) opt argv =
- let (reso, argv') = parse opt argv
- reso |> Option.map (fun x -> (x, argv'))
\ No newline at end of file
diff --git a/src/FSharp.Scanf/FSharp.Scanf.fsproj b/src/FSharp.Scanf/FSharp.Scanf.fsproj
deleted file mode 100755
index 5d270db..0000000
--- a/src/FSharp.Scanf/FSharp.Scanf.fsproj
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
- netstandard2.0;netstandard1.6;net46;net45
- Type-safe scanf for F#
- cannorin
-
- (c) cannorin 2017-2019
- https://github.com/cannorin/FSharp.CommandLine/tree/master/src/FSharp.Scanf
- MIT
- fsharp commandline console scanf
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/FSharp.Scanf/scanf.fs b/src/FSharp.Scanf/scanf.fs
deleted file mode 100755
index b94fe61..0000000
--- a/src/FSharp.Scanf/scanf.fs
+++ /dev/null
@@ -1,436 +0,0 @@
-(*
-The MIT License
-Scanf.fs - type safe scanf
-Copyright(c) 2018-2019 cannorin
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*)
-
-// original: http://www.fssnip.net/4I/title/sscanf-parsing-with-format-strings
-
-/// Scanf functions.
-/// If the result type is 7-tuple or less, consider using `FSharp.Scanf.Optimized` module instead.
-module FSharp.Scanf
-
-open System
-open System.IO
-open Microsoft.FSharp.Reflection
-
-let inline internal to_s x = x.ToString()
-
-let inline internal check f x = if f x then x else failwithf "format failure \"%s\"" x
-
-let inline internal parseDecimal x = Decimal.Parse(x, System.Globalization.CultureInfo.InvariantCulture)
-
-module Internal =
- // type wrapper
- []
- type ScanfTypeMarker<'t> = | ScanfTypeMarker
-
- []
- let parserChars = "bdisuxXoeEfFgGMcA"
-
- let inline internal formatIntegerStr str fmt =
- match fmt with
- | 'i' | 'd' | 'u' -> str
- | 'x' -> str |> check (String.forall (fun c -> Char.IsLower c || Char.IsDigit c)) |> ((+) "0x")
- | 'X' -> str |> check (String.forall (fun c -> Char.IsUpper c || Char.IsDigit c)) |> ((+) "0x")
- | 'o' -> "0o" + str
- | _ -> str
-
- let inline internal convertUnsafe fmt targetType str =
- let str = formatIntegerStr str fmt
- if targetType = typeof then box str
- else if targetType = typeof then int32 str |> box
- else if targetType = typeof then float str |> box
- else if targetType = typeof then char str |> box
- else if targetType = typeof then Boolean.Parse(str) |> box
- else if targetType = typeof then int8 str |> box
- else if targetType = typeof then uint8 str |> box
- else if targetType = typeof then int16 str |> box
- else if targetType = typeof then uint16 str |> box
- else if targetType = typeof then uint32 str |> box
- else if targetType = typeof then int64 str |> box
- else if targetType = typeof then uint64 str |> box
- else if targetType = typeof then float32 str |> box
- else if targetType = typeof then parseDecimal str |> box
- else if targetType = typeof then box ()
- else if targetType = typeof then bigint.Parse str |> box
- else failwithf "Unsupported type '%s'" targetType.Name
-
- let inline internal typemarker<'t> : ScanfTypeMarker<'t> = ScanfTypeMarker
-
- // Compile-time resolved string-to-value parsers
- type OptimizedConverter =
- static member inline Convert (_: ScanfTypeMarker, _, _) = ()
- static member inline Convert (_: ScanfTypeMarker, s: string list, _) = Boolean.Parse(s.Head)
- static member inline Convert (_: ScanfTypeMarker, s: string list, _) = s.Head
- static member inline Convert (_: ScanfTypeMarker, s:string list, _) = char s.Head
- static member inline Convert (_: ScanfTypeMarker, s: string list, formatters: char list) =
- formatIntegerStr s.Head formatters.Head |> int8
- static member inline Convert (_: ScanfTypeMarker, s: string list, formatters: char list) =
- formatIntegerStr s.Head formatters.Head |> uint8
- static member inline Convert (_: ScanfTypeMarker, s: string list, formatters: char list) =
- formatIntegerStr s.Head formatters.Head |> int16
- static member inline Convert (_: ScanfTypeMarker, s: string list, formatters: char list) =
- formatIntegerStr s.Head formatters.Head |> uint16
- static member inline Convert (_: ScanfTypeMarker, s: string list, formatters: char list) =
- formatIntegerStr s.Head formatters.Head |> int32
- static member inline Convert (_: ScanfTypeMarker, s: string list, formatters: char list) =
- formatIntegerStr s.Head formatters.Head |> uint32
- static member inline Convert (_: ScanfTypeMarker, s: string list, formatters: char list) =
- formatIntegerStr s.Head formatters.Head |> int64
- static member inline Convert (_: ScanfTypeMarker, s: string list, formatters: char list) =
- formatIntegerStr s.Head formatters.Head |> uint64
- static member inline Convert (_: ScanfTypeMarker, s: string list, formatters: char list) =
- formatIntegerStr s.Head formatters.Head |> bigint.Parse
- static member inline Convert (_: ScanfTypeMarker, s:string list, _) = float s.Head
- static member inline Convert (_: ScanfTypeMarker, s:string list, _) = float32 s.Head
- static member inline Convert (_: ScanfTypeMarker, s:string list, _) = parseDecimal s.Head
-
- let inline internal convertFast (typ: ScanfTypeMarker< ^t >) (s: string list) (formatter:char list) =
- let inline call_2 (_: ScanfTypeMarker< ^Converter >, _: ScanfTypeMarker< ^x >) =
- ((^Converter or ^x): (static member Convert: _*_*_ -> ^t) typ,s,formatter)
- let inline call (a: ScanfTypeMarker<'a>, b: ScanfTypeMarker<'b>) = call_2 (a, b)
- call (typemarker, typ)
-
- // 8-tuples or more are reprensented as `System.Tuple'7<_,_,_,_,_,_,_,System.Tuple<...>>`
- // but it is impossible to handle them generically
- type OptimizedConverter with
- static member inline Convert (_: ScanfTypeMarker<'t1*'t2>, s: string list, fs: char list) =
- convertFast typemarker<'t1> s fs,
- convertFast typemarker<'t2> s.Tail fs.Tail
- static member inline Convert (_: ScanfTypeMarker<'t1*'t2*'t3>, s: string list, fs: char list) =
- convertFast typemarker<'t1> s fs,
- convertFast typemarker<'t2> s.Tail fs.Tail,
- convertFast typemarker<'t3> s.Tail.Tail fs.Tail.Tail
- static member inline Convert (_: ScanfTypeMarker<'t1*'t2*'t3*'t4>, s: string list, fs: char list) =
- convertFast typemarker<'t1> s fs,
- convertFast typemarker<'t2> s.Tail fs.Tail,
- convertFast typemarker<'t3> s.Tail.Tail fs.Tail.Tail,
- convertFast typemarker<'t4> s.Tail.Tail.Tail fs.Tail.Tail.Tail
- static member inline Convert (_: ScanfTypeMarker<'t1*'t2*'t3*'t4*'t5>, s: string list, fs: char list) =
- convertFast typemarker<'t1> s fs,
- convertFast typemarker<'t2> s.Tail fs.Tail,
- convertFast typemarker<'t3> s.Tail.Tail fs.Tail.Tail,
- convertFast typemarker<'t4> s.Tail.Tail.Tail fs.Tail.Tail.Tail,
- convertFast typemarker<'t5> s.Tail.Tail.Tail.Tail fs.Tail.Tail.Tail.Tail
- static member inline Convert (_: ScanfTypeMarker<'t1*'t2*'t3*'t4*'t5*'t6>, s: string list, fs: char list) =
- convertFast typemarker<'t1> s fs,
- convertFast typemarker<'t2> s.Tail fs.Tail,
- convertFast typemarker<'t3> s.Tail.Tail fs.Tail.Tail,
- convertFast typemarker<'t4> s.Tail.Tail.Tail fs.Tail.Tail.Tail,
- convertFast typemarker<'t5> s.Tail.Tail.Tail.Tail fs.Tail.Tail.Tail.Tail,
- convertFast typemarker<'t6> s.Tail.Tail.Tail.Tail.Tail fs.Tail.Tail.Tail.Tail.Tail
- static member inline Convert (_: ScanfTypeMarker<'t1*'t2*'t3*'t4*'t5*'t6*'t7>, s: string list, fs: char list) =
- convertFast typemarker<'t1> s fs,
- convertFast typemarker<'t2> s.Tail fs.Tail,
- convertFast typemarker<'t3> s.Tail.Tail fs.Tail.Tail,
- convertFast typemarker<'t4> s.Tail.Tail.Tail fs.Tail.Tail.Tail,
- convertFast typemarker<'t5> s.Tail.Tail.Tail.Tail fs.Tail.Tail.Tail.Tail,
- convertFast typemarker<'t6> s.Tail.Tail.Tail.Tail.Tail fs.Tail.Tail.Tail.Tail.Tail,
- convertFast typemarker<'t7> s.Tail.Tail.Tail.Tail.Tail.Tail fs.Tail.Tail.Tail.Tail.Tail.Tail
-
- // Creates a list of formatter characters from a format string,
- // for example "(%s,%d)" -> ['s', 'd']
- let rec internal getFormatters xs =
- match xs with
- | '%' :: '%' :: xr -> getFormatters xr
- | '%' :: x :: xr ->
- if parserChars |> Seq.contains x then x :: getFormatters xr
- else failwithf "Unsupported formatter '%%%c'" x
- | _ :: xr -> getFormatters xr
- | [] -> []
-
- []
- type FormatStringPart =
- | Placeholder of typ:char
- | Literal of string
- | Space
- static member getFormatters(fmt: FormatStringPart list) =
- let rec get = function
- | Placeholder c :: rest -> c :: get rest
- | _ :: rest -> get rest
- | [] -> []
- get fmt
-
- let inline internal (<+>) h t =
- match h, t with
- | FormatStringPart.Literal s, FormatStringPart.Literal t :: rest ->
- FormatStringPart.Literal (s+t) :: rest
- | _ -> h :: t
-
- let rec internal parsePlaceholderImpl currentPos (str: string) =
- let c = str.[currentPos]
- let nextPos = currentPos + 1
- if Char.IsLetter c then
- FormatStringPart.Placeholder c :: parseFormatImpl nextPos nextPos str
- else if c = '%' then
- FormatStringPart.Literal "%" <+> parseFormatImpl nextPos nextPos str
- else failwithf "Unsupported formatter '%%%c'" c
-
- and internal parseFormatImpl startPos currentPos (str: string) =
- if currentPos >= str.Length then
- if currentPos = startPos then []
- else
- let s = str.Substring(startPos, currentPos - startPos)
- FormatStringPart.Literal s :: []
- else
- let c = str.[currentPos]
- if c = '%' then
- let nextPos = currentPos + 1
- if currentPos = startPos then
- parsePlaceholderImpl nextPos str
- else
- let s = str.Substring(startPos, currentPos - startPos)
- FormatStringPart.Literal s <+> parsePlaceholderImpl nextPos str
- else if c = ' ' || c = '\n' || c = '\r' || c = '\t' then
- let mutable i = 1
- while currentPos + i < str.Length
- && let c = str.[currentPos + i] in
- c = ' ' || c = '\n' || c = '\r' || c = '\t' do i <- i+1
- let nextPos = currentPos + i
- if currentPos = startPos then
- FormatStringPart.Space :: parseFormatImpl nextPos nextPos str
- else
- let s = str.Substring(startPos, currentPos - startPos)
- FormatStringPart.Literal s :: FormatStringPart.Space :: parseFormatImpl nextPos nextPos str
- else
- parseFormatImpl startPos (currentPos + 1) str
-
- let inline internal parseFormat (str: string) =
- parseFormatImpl 0 0 str
-
- open FParsec
- let inline (<++>) p1 p2 = p1 .>>. p2 |>> List.Cons
- let inline strOf p = withSkippedString (fun s _ -> s) p
-
- let rec internal buildParser = function
- | [] -> eof >>% []
- | FormatStringPart.Space :: rest ->
- spaces1 >>. buildParser rest
- | FormatStringPart.Literal lit :: rest ->
- skipString lit >>. buildParser rest
- | FormatStringPart.Placeholder c :: rest->
- let cont = buildParser rest
- match c with
- | 'b' -> (pstring "true" <|> pstring "false") <++> cont
- | 'd' | 'i' -> many1Satisfy isDigit <++> cont
- | 's' | 'A' ->
- manyCharsTill anyChar (followedBy cont) .>>.? cont |>> List.Cons
- | 'u' -> strOf puint64 <++> cont
- | 'x' | 'X' -> manySatisfy isHex <++> cont
- | 'o' -> manySatisfy isOctal <++> cont
- | 'e' | 'E' | 'f' | 'F' | 'g' | 'G' ->
- (skipStringCI "nan" >>% "NaN")
- <|> (skipStringCI "infinity" <|> skipStringCI "inf" >>% "Infinity")
- <|> (strOf pfloat)
- <++> cont
- | 'M' ->
- many1Satisfy isDigit .>>.? opt (skipChar '.' >>? many1Satisfy isDigit)
- |>> (fun (i, j) -> i + Option.defaultValue "" j)
- <++> cont
- | 'c' -> anyChar |>> string <++> cont
- | c -> failwithf "Unsupported formatter '%%%c'" c
-
- let inline internal matchFormat fmt fmtStr str =
- match run (buildParser fmt) str with
- | Success (xs, _, _) -> xs
- | Failure (msg, _, _) ->
- failwithf "the input does not match the format '%s': %s" fmtStr msg
-
- // Extracts string matches and the format from a format string and a given string.
- let getMatchesAndFormat (pf: PrintfFormat<_, _, _, _, _>) s =
- let formatStr = pf.Value
- let fmt = parseFormat formatStr
- let groups = matchFormat fmt formatStr s
- let formatters = FormatStringPart.getFormatters fmt
- groups, formatStr, formatters
-
-open Internal
-
-type PrintfFormat<'a,'b,'c,'d,'e> with
- member this.GetFormatterNames () =
- let fs = this.Value.ToCharArray()
- |> Array.toList |> getFormatters in
- let print = function
- | 's' -> "string"
- | 'c' -> "char"
- | 'b' -> "bool"
- | 'i' | 'd' -> "int"
- | 'u' -> "uint"
- | 'x' -> "lowercase hex"
- | 'X' -> "uppercase hex"
- | 'o' -> "octal"
- | 'f' | 'e' | 'E' | 'g' | 'G' -> "double"
- | 'M' -> "decimal"
- | 'A' -> "any type"
- | x -> failwithf "Unsupported formatter '%%%c'" x
- in
- fs |> List.map print
-
- member this.PrettyTokenize names =
- let fcs = this.Value.ToCharArray() |> Array.toList in
- if (List.length names) < (fcs |> getFormatters |> List.length) then
- failwith "Parameter count does not match to the format"
- else
- let rec replace = function
- | [], _ -> []
- | cs, [] ->
- cs |> List.map to_s
- | '%' :: '%' :: cs, ns ->
- replace (cs, ns)
- | '%' :: c :: cs, n :: ns when parserChars |> Seq.contains c ->
- n :: replace (cs, ns)
- | c :: cs, ns ->
- to_s c :: replace (cs, ns)
- in
- replace (fcs, names)
-
- member this.PrettyPrint names = this.PrettyTokenize names |> String.concat ""
-
-type ScanfTypeMarker<'t> = Internal.ScanfTypeMarker<'t>
-
-/// If the result type is 7-tuple or less, consider using `FSharp.Scanf.Optimized` module instead.
-let ksscanf (pf: PrintfFormat<_,_,_,_,'t>) (cont: 't -> 'u) s : 'u =
- let matches, formatStr, formatters = getMatchesAndFormat pf s
- let value =
- if typeof<'t> = typeof then
- if s = formatStr then
- box () :?> 't
- else
- failwith "Match failed"
- else
- if matches.Length = 1 then
- convertUnsafe formatters.[0] typeof<'t> matches.[0] :?> 't
- else
- let targetTypes = FSharpType.GetTupleElements(typeof<'t>)
- let values =
- (formatters, targetTypes, matches)
- |||> Seq.map3 convertUnsafe
- |> Seq.toArray
- FSharpValue.MakeTuple(values, typeof<'t>) :?> 't
- cont value
-
-/// If the result type is 7-tuple or less, consider using `FSharp.Scanf.Optimized` module instead.
-let inline tryKsscanf pf cont s =
- try
- ksscanf pf cont s |> Ok
- with
- | ex -> Error ex
-
-/// If the result type is 7-tuple or less, consider using `FSharp.Scanf.Optimized` module instead.
-let inline sscanf pf s =
- ksscanf pf id s
-
-/// If the result type is 7-tuple or less, consider using `FSharp.Scanf.Optimized` module instead.
-let inline trySscanf pf s =
- tryKsscanf pf id s
-
-/// If the result type is 7-tuple or less, consider using `FSharp.Scanf.Optimized` module instead.
-let inline scanfn pf =
- Console.ReadLine() |> sscanf pf
-
-/// If the result type is 7-tuple or less, consider using `FSharp.Scanf.Optimized` module instead.
-let inline tryScanfn pf =
- Console.ReadLine() |> trySscanf pf
-
-/// If the result type is 7-tuple or less, consider using `FSharp.Scanf.Optimized` module instead.
-let inline kscanfn pf cont =
- ksscanf pf cont <| Console.ReadLine()
-
-/// If the result type is 7-tuple or less, consider using `FSharp.Scanf.Optimized` module instead.
-let inline tryKscanfn pf cont =
- tryKsscanf pf cont <| Console.ReadLine()
-
-/// If the result type is 7-tuple or less, consider using `FSharp.Scanf.Optimized` module instead.
-let inline fscanfn pf (tr: TextReader) =
- tr.ReadLine() |> sscanf pf
-
-/// If the result type is 7-tuple or less, consider using `FSharp.Scanf.Optimized` module instead.
-let inline tryFscanfn pf (tr: TextReader) =
- tr.ReadLine() |> trySscanf pf
-
-/// If the result type is 7-tuple or less, consider using `FSharp.Scanf.Optimized` module instead.
-let inline kfscanfn pf cont (tr: TextReader) =
- ksscanf pf cont <| tr.ReadLine()
-
-/// If the result type is 7-tuple or less, consider using `FSharp.Scanf.Optimized` module instead.
-let inline tryKfscanfn pf cont (tr: TextReader) =
- tryKsscanf pf cont <| tr.ReadLine()
-
-// active pattern
-let (|Sscanf|_|) (format:PrintfFormat<_,_,_,_,'t>) input =
- trySscanf format input |> function | Ok x -> Some x | Error _ -> None
-
-/// Scanf functions, no reflection/boxing. About 6x-7x faster than unoptimized ones.
-///
-/// Can only be used with up to 7 captures (i.e. the result type must be up to 7-tuples).
-///
-/// If you implement a static member with signature `Convert: ScanfTypeMarker * string list * char list -> YourType`,
-/// you can directly parse the string into that type by using `%A`.
-///
-/// ```
-/// type A = A of string with
-/// static member Convert (_: ScanfTypeMarker, ss: string list, _) = ss.[0]
-///
-/// let a: A = sscanf "%A" "foo"
-/// // val a : A = A "foo"
-/// ```
-module Optimized =
- type ScanfTypeMarker<'t> = Internal.ScanfTypeMarker<'t>
-
- /// If the result type is 8-tuple or more, it fails to typecheck. Use `FSharp.Scanf` module instead or try reducing the captures by applying `scanf` to the result string.
- let inline ksscanf (pf: PrintfFormat<_,_,_,_,^t>) (cont: ^t -> 'u) s : 'u =
- let matches, _, formatters = getMatchesAndFormat pf s
- let strings = matches |> Seq.toList
- convertFast typemarker< ^t > strings formatters |> cont
- /// If the result type is 8-tuple or more, it fails to typecheck. Use `FSharp.Scanf` module instead or try reducing the captures by applying `scanf` to the result string.
- let inline tryKsscanf pf cont s =
- try
- ksscanf pf cont s |> Ok
- with
- | ex -> Error ex
- /// If the result type is 8-tuple or more, it fails to typecheck. Use `FSharp.Scanf` module instead or try reducing the captures by applying `scanf` to the result string.
- let inline sscanf pf s =
- ksscanf pf id s
- /// If the result type is 8-tuple or more, it fails to typecheck. Use `FSharp.Scanf` module instead or try reducing the captures by applying `scanf` to the result string.
- let inline trySscanf pf s =
- tryKsscanf pf id s
- /// If the result type is 8-tuple or more, it fails to typecheck. Use `FSharp.Scanf` module instead or try reducing the captures by applying `scanf` to the result string.
- let inline scanfn pf =
- Console.ReadLine() |> sscanf pf
- /// If the result type is 8-tuple or more, it fails to typecheck. Use `FSharp.Scanf` module instead or try reducing the captures by applying `scanf` to the result string.
- let inline tryScanfn pf =
- Console.ReadLine() |> trySscanf pf
- /// If the result type is 8-tuple or more, it fails to typecheck. Use `FSharp.Scanf` module instead or try reducing the captures by applying `scanf` to the result string.
- let inline kscanfn pf cont =
- ksscanf pf cont <| Console.ReadLine()
- /// If the result type is 8-tuple or more, it fails to typecheck. Use `FSharp.Scanf` module instead or try reducing the captures by applying `scanf` to the result string.
- let inline tryKscanfn pf cont =
- tryKsscanf pf cont <| Console.ReadLine()
- /// If the result type is 8-tuple or more, it fails to typecheck. Use `FSharp.Scanf` module instead or try reducing the captures by applying `scanf` to the result string.
- let inline fscanfn pf (tr: TextReader) =
- tr.ReadLine() |> sscanf pf
- /// If the result type is 8-tuple or more, it fails to typecheck. Use `FSharp.Scanf` module instead or try reducing the captures by applying `scanf` to the result string.
- let inline tryFscanfn pf (tr: TextReader) =
- tr.ReadLine() |> trySscanf pf
- /// If the result type is 8-tuple or more, it fails to typecheck. Use `FSharp.Scanf` module instead or try reducing the captures by applying `scanf` to the result string.
- let inline kfscanfn pf cont (tr: TextReader) =
- ksscanf pf cont <| tr.ReadLine()
- /// If the result type is 8-tuple or more, it fails to typecheck. Use `FSharp.Scanf` module instead or try reducing the captures by applying `scanf` to the result string.
- let inline tryKfscanfn pf cont (tr: TextReader) =
- tryKsscanf pf cont <| tr.ReadLine()
diff --git a/src/abstractions.fs b/src/abstractions.fs
new file mode 100644
index 0000000..2b916cc
--- /dev/null
+++ b/src/abstractions.fs
@@ -0,0 +1,53 @@
+namespace FSharp.CommandLine.Internals
+
+type State<'Args, 'a> = 'Args -> ('a * 'Args)
+
+type StateConfig<'Config, 'Args, 'a> = {
+ config: 'Config -> 'Config
+ func: State<'Args, 'a>
+}
+
+module StateConfig =
+ let inline scbind (f: 'a -> StateConfig<'Config, 'Args, 'b>) (g: 'Config -> 'Config) (m: StateConfig<'Config, 'Args, 'a>) =
+ {
+ config = m.config >> g
+ func =
+ fun args ->
+ let (a, args) = m.func args
+ (f a).func args
+ }
+
+ let inline returnValue (a: 'a) : StateConfig<_, _, 'a> =
+ {
+ config = id
+ func = fun args -> (a, args)
+ }
+
+ let inline returnWith (f: unit -> 'a) : StateConfig<_, _, 'a> =
+ {
+ config = id
+ func = fun args -> (f(), args)
+ }
+
+ let inline bind f m = m |> scbind f id
+
+ let inline mapConfig g m = m |> scbind returnValue g
+
+ let inline map f m = m |> bind (f >> returnValue)
+
+ let inline zip (m: StateConfig<_, _, 'a>) (n: StateConfig<_, _, 'b>) (f: 'a -> 'b -> 'c) =
+ scbind (fun a ->
+ {
+ config = id
+ func = fun args -> let (b, args) = n.func args in (f a b, args)
+ })
+ n.config
+ m
+
+ let inline combine (a: StateConfig<_,_,_>) (b: StateConfig<_,_,_>) = zip a b (fun _ b -> b)
+
+ let args =
+ {
+ config = id
+ func = fun args -> (args, args)
+ }
diff --git a/src/basictypes.fs b/src/basictypes.fs
new file mode 100644
index 0000000..3a9f2f6
--- /dev/null
+++ b/src/basictypes.fs
@@ -0,0 +1,112 @@
+namespace FSharp.CommandLine
+
+open FSharp.CommandLine.Internals
+open System.Runtime.CompilerServices
+
+type Args = string list
+
+type HelpElement =
+ /// prints `usage: $(command name) $(args)`.
+ | HelpUsage
+ /// prints `usage: $(command name) $(args)` of which `args` can be customized.
+ | HelpUsageCustomArgs of args: string list
+ /// prints a string.
+ | HelpRawString of text: string
+ /// prints the infomation of all the subcommands.
+ | HelpAllSubcommands
+ /// prints the infomation of the specified subcommands.
+ | HelpSpecificSubcommands of names: string list
+ /// prints the infomation of all the command options.
+ | HelpAllOptions
+ /// prints the infomation of the specified command options.
+ | HelpSpecificOptions of namesWithoutHyphen: string list
+ /// prints elements as a section. the content will be indented.
+ /// nested sections make the indentation deeper.
+ | HelpSection of sectionName: string * sectionBody: seq
+ /// prints an empty line.
+ | HelpEmptyLine
+
+type HelpText = HelpElement seq
+
+type CommandSuggestion =
+ /// suggests a set of string.
+ | Values of string list
+ /// suggests a set of string with description.
+ | ValuesWithDescription of (string * string) list
+ /// suggests files optionally with pattern.
+ | Files of pattern: string option
+ /// suggests directories.
+ | Directories of pattern: string option
+ /// suggests a command option.
+ | OptionSuggestion of (string list) * string
+ /// prints a message.
+ | Message of string
+
+type CommandOptionSummary = {
+ names: string list;
+ description: string;
+ isFlag: bool;
+ paramNames: (string list) list
+ isMatch: string list -> string list option
+ genSuggestions: string option -> CommandSuggestion list
+}
+with
+ member this.Param =
+ let rec print eq xss =
+ let heads = xss |> List.map List.tryHead
+ if heads |> List.exists Option.isSome then
+ let isOptional = heads |> List.exists Option.isNone
+ let groups = xss |> List.filter (List.isEmpty >> not)
+ |> List.groupBy List.head
+ |> List.map (fun (g, xs) -> sprintf "%s%s" g (xs |> List.map List.tail |> print ""))
+ let s =
+ if List.length groups > 1 then
+ let s = groups |> String.concat "|"
+ if isOptional then s else sprintf "{%s}" s
+ else
+ groups |> String.concat ""
+ if isOptional then sprintf "[%s%s]" eq s else sprintf "%s%s"eq s
+ else
+ ""
+ in print "=" (this.paramNames |> List.rev)
+
+ member this.NameRepresentations =
+ this.names |> List.collect (function
+ | x when x.Length = 1 ->
+ [ "-"; "/" ] |> List.map (fun prefix -> sprintf "%s%s" prefix x)
+ | x ->
+ [ "--"; "/" ] |> List.map (fun prefix -> sprintf "%s%s" prefix x))
+
+ member this.Print () =
+ let o x = if this.isFlag then sprintf "%s[+|-]" x else sprintf "%s%s" x this.Param
+ ((this.NameRepresentations |> List.filter (String.startsWith "-") |> String.concat ", " |> o), this.description)
+
+type CommandSummary = {
+ name: string;
+ displayName: string option;
+ description: string;
+ paramNames: (string list) option
+ help: HelpText option
+ genSuggestions: Args -> CommandSuggestion list
+}
+
+type CommandInfo = {
+ summary: CommandSummary
+ options: CommandOptionSummary list
+ subcommands: Command list
+}
+and Command<'a> = StateConfig
+
+type CommandInfo with
+ static member empty =
+ {
+ summary = Unchecked.defaultof
+ options = []
+ subcommands = []
+ }
+
+[]
+type ICommandExt() =
+ []
+ static member inline Summary(x: Command<_>) =
+ (x.config CommandInfo.empty).summary
diff --git a/src/builders.fs b/src/builders.fs
new file mode 100644
index 0000000..fb84d71
--- /dev/null
+++ b/src/builders.fs
@@ -0,0 +1,244 @@
+namespace FSharp.CommandLine.Internals
+
+open FSharp.CommandLine
+open Microsoft.FSharp.Quotations
+
+module internal Helpers =
+ let inline snoc x xs = seq { yield! xs; yield x }
+
+ let inline mapSummary f co =
+ co |> Command.mapInfo (fun cfg -> { cfg with summary = f cfg.summary })
+
+open Helpers
+
+type HelpBuilder() =
+ member inline __.For (_, _) = failwith "Not supported"
+ member inline __.Yield _ : HelpElement seq = Seq.empty
+
+ /// prints `usage: $(command name) $(args)`.
+ []
+ member inline __.Usage xs = xs |> snoc HelpUsage
+
+ /// prints `usage: $(command name) $(args)` of which `args` can be customized.
+ []
+ member inline __.UsageWithCustomArgs (xs, argNames) = xs |> snoc (HelpUsageCustomArgs argNames)
+
+ /// prints a string.
+ []
+ member inline __.RawText (xs, str) = xs |> snoc (HelpRawString str)
+
+ /// prints the infomation of all the subcommands.
+ []
+ member inline __.Subcommands xs = xs |> snoc HelpAllSubcommands
+
+ /// prints the infomation of the specified subcommands.
+ []
+ member inline __.SpecificSubcommands (xs, cmds) = xs |> snoc (HelpSpecificSubcommands cmds)
+
+ /// prints the infomation of all the command options.
+ []
+ member inline __.Options xs = xs |> snoc HelpAllOptions
+
+ /// prints the infomation of the specified command options.
+ []
+ member inline __.SpecificOptions (xs, opts) = xs |> snoc (HelpSpecificOptions opts)
+
+ /// prints elements as a section. the content will be indented.
+ /// nested sections make the indentation deeper.
+ []
+ member inline __.Section (xs, sectionName, section) = xs |> snoc (HelpSection(sectionName, section))
+
+ /// prints elements as a section when the condition holds. the content will be indented.
+ /// nested sections make the indentation deeper.
+ []
+ member inline __.ConditionalSection (xs, sectionName, cond, section) =
+ if cond() then
+ xs |> snoc (HelpSection(sectionName, section))
+ else
+ xs
+
+ /// prints an empty line.
+ []
+ member inline __.EmptyLine xs = xs |> snoc HelpEmptyLine
+
+type CommandOptionBuilder<'a>(dc: unit -> CommandOption<'a>) =
+ member __.For (_, _) = failwith "Not supported"
+ member __.Yield _ = dc ()
+
+ /// required.
+ /// specifies the option's names. hyphens should not be included,
+ /// as they will automatically be handled depending on
+ /// the length of the name and optionally the `style` command.
+ []
+ member __.Names (co, x) = { co with baseSummary = { co.baseSummary with names = x } }
+
+ []
+ member __.Description (co, x) = { co with baseSummary = { co.baseSummary with description = x } }
+
+ /// required for command option.
+ /// specifies the format of the argument. for example:
+ /// `takes (format("%s").map(fun str -> someFunc str))`
+ []
+ member inline __.Takes (co: CommandOption<'a>, x) =
+ let (f, ts) = construct x in
+ { co with
+ kind =
+ match co.kind with
+ | TakingValueWith (d, xs) -> TakingValueWith (d, List.append xs [f])
+ | _ -> TakingValueWith (JustFail, [f]);
+ baseSummary =
+ { co.baseSummary with
+ paramNames = ts :: co.baseSummary.paramNames
+ }
+ }
+
+ /// `takesFormat fmt (fun .. -> ..)` is a shorthand for
+ /// `takes (format(fmt).map(fun .. -> ..))`.
+ []
+ member inline __.TakesFormat (co: CommandOption<_>, fmt: PrintfFormat<_,_,_,_,_>, []mapper: Expr<_ -> _>) =
+ let mf x = (FuncHelper.compileFunc mapper) x in
+ let pns = FuncHelper.getFirstArgumentName mapper in
+ let x =
+ { format = fmt; handler = mf; paramNames = pns }
+ let (f, ts) = construct x in
+ { co with
+ kind =
+ match co.kind with
+ | TakingValueWith (d, xs) -> TakingValueWith (d, List.append xs [f])
+ | _ -> TakingValueWith (JustFail, [f]);
+ baseSummary =
+ { co.baseSummary with
+ paramNames = ts :: co.baseSummary.paramNames
+ }
+ }
+
+ /// optional.
+ /// makes the option's argument optional, and specifies the default value
+ /// that will be used when the argument is not provided.
+ []
+ member __.DefaultValue (co: CommandOption<'a>, value: 'a) =
+ { co with
+ kind =
+ match co.kind with
+ | TakingValueWith (_, xs) -> TakingValueWith (UseDefault value, xs)
+ | x -> x
+ }
+
+ /// optional.
+ /// specifies the command suggestions this option will generate.
+ []
+ member __.Suggests (co, f) = { co with baseSummary = { co.baseSummary with genSuggestions=f } }
+
+ /// optional.
+ /// specify how to treat options like ```-abcd```.
+ /// the default value is `MergedShort`.
+ []
+ member __.Style (co, st) = { co with style = st }
+
+type CommandBuilder() =
+ member inline __.Bind (c, f) = Command.bind f c
+ member inline __.Return x = Command.returnValue x
+ member inline __.For (c, f) = Command.bind f c
+ member inline __.Yield x = Command.returnValue x
+ member inline __.ReturnFrom (x: Command<_>) = x
+ member inline __.Combine (a, b) = Command.combine a b
+ member inline __.Combine (f, b) = Command.combine (f()) b
+ member inline __.Combine (a, f) = Command.combine a (f())
+ member inline __.Zero () = Command.returnValue ()
+ member inline __.Delay (f: unit -> Command<_>) = f
+ member inline __.Undelay x : Command<_> = x()
+ member inline __.Run f : Command<_> = f()
+ member inline __.TryWith (f, h) = try f() with exn -> h exn
+ member inline __.TryFinally (f, h) = try f() finally h()
+ member inline this.Using (disp: #System.IDisposable, m) = this.TryFinally(this.Delay(fun () -> m disp), fun () -> dispose disp)
+ member inline this.While (cond, m: unit -> Command<_>) =
+ let rec loop cond m : Command<_> =
+ if cond () then this.Combine(this.Undelay m, loop cond m)
+ else this.Zero ()
+ loop cond m
+ member inline this.For (xs: #seq<_>, exec) =
+ this.Using(
+ (xs :> seq<_>).GetEnumerator(),
+ fun en ->
+ this.While(
+ en.MoveNext,
+ this.Delay(fun () -> exec en.Current))
+ )
+
+ /// uses a command option.
+ []
+ member inline __.UseOption (co: Command<'a>, opt: #ICommandOption<'b>, f: 'a -> 'b -> 'c) =
+ {
+ config = co.config >> opt.Config
+ func =
+ fun args ->
+ let (a, args) = co.func args
+ let (b, args) = opt.Parse args
+ (f a b, args)
+ }
+
+ /// imports a command to this command. will inherit options and other metadatas.
+ []
+ member inline __.ImportCommand (c1, c2, f) : Command<_> = Command.zip c1 c2 f
+
+ /// required. sets the name of the command. will also be used when this command is
+ /// a subcommand of the other one.
+ []
+ member inline __.Name (co, x) =
+ co |> mapSummary (fun s -> { s with name = x })
+
+ /// optional. sets the name of the command that will be displayed in the help text.
+ /// the one speficied by `name` will be used if not specified.
+ []
+ member inline __.DisplayName (co, n) =
+ co |> mapSummary (fun s -> { s with displayName = Some n })
+
+ /// required. sets the description of the command.
+ []
+ member inline __.Description (co, x) =
+ co |> mapSummary (fun s -> { s with description = x })
+
+ /// optional. speficies the suggestions it will generate.
+ []
+ member inline __.Suggests (co: Command<_>, f) =
+ co |> mapSummary (fun s -> { s with genSuggestions = f })
+
+ /// optional. customizes the help text.
+ []
+ member inline __.Help (co: Command<_>, xs: HelpElement seq) =
+ co |> mapSummary (fun s -> { s with help = Some xs })
+
+ /// optional. specifies the subcommands.
+ []
+ member inline __.Subcommands (co, xs) = {
+ config =
+ fun cfg ->
+ let cfg = co.config cfg
+ { cfg with subcommands = cfg.subcommands @ xs }
+ func =
+ fun args ->
+ let sc =
+ match args with
+ | h :: _ ->
+ List.tryFind (fun (x:Command<_>) -> x.Summary().name = h) xs
+ | _ -> None
+ if sc.IsSome then
+ let (code, _) = sc.Value.func (List.tail args)
+ RequestExit code |> raise
+ else
+ co.func args
+ }
+
+
+namespace FSharp.CommandLine
+
+open FSharp.CommandLine.Internals
+
+[]
+module Builders =
+ let helpText = new HelpBuilder()
+ let commandOption<'a> =
+ new CommandOptionBuilder<'a>(fun () -> CommandOption<'a>.defaultOption)
+ let commandFlag =
+ new CommandOptionBuilder<_>(fun () -> CommandOption.defaultFlag)
+ let command = CommandBuilder ()
\ No newline at end of file
diff --git a/src/commands.fs b/src/commands.fs
new file mode 100644
index 0000000..f523bc0
--- /dev/null
+++ b/src/commands.fs
@@ -0,0 +1,80 @@
+namespace FSharp.CommandLine
+
+open System
+open FSharp.CommandLine.Generators
+open FSharp.CommandLine.Internals
+
+module Command =
+ let args : Command = StateConfig.args
+ let bind (f: 'a -> Command<'b>) (m: Command<'a>) : Command<'b> = StateConfig.bind f m
+ let returnValue (x: 'a) : Command<'a> = StateConfig.returnValue x
+ let returnWith (f: unit -> 'a) : Command<'a> = StateConfig.returnWith f
+ let map (f: 'a -> 'b) (m: Command<'a>) : Command<'b> = StateConfig.map f m
+ let mapInfo (f: CommandInfo -> CommandInfo) (m: Command<'a>) : Command<'a> = StateConfig.mapConfig f m
+ let zip (a: Command<'a>) (b: Command<'b>) (f: 'a -> 'b -> 'c) : Command<'c> = StateConfig.zip a b f
+ let combine (a: Command<'a>) (b: Command<'b>) : Command<'b> = StateConfig.combine a b
+
+ let private runMain args (cmd: Command) =
+ match args |> List.ofArray with
+ | CommandOption.Parse ReservedCommandOptions.suggestOption (sug, rest) ->
+ Suggestions.generate rest cmd
+ |> Suggestions.print (SuggestionBackends.findByName sug)
+ |> printfn "%A"
+ (0, [])
+ | CommandOption.Parse ReservedCommandOptions.helpOption (true, rest) ->
+ for line in Help.generate rest cmd do
+ printfn "%s" line
+ (0, [])
+ | args ->
+ cmd.func args
+
+ #if DEBUG
+ let runAsEntryPointDebug args (cmd: Command) = runMain args cmd
+ #endif
+
+ /// executes the command as an entry point:
+ ///
+ /// ```
+ /// []
+ /// let main argv =
+ /// Command.runAsEntryPoint argv command
+ /// ```
+ let runAsEntryPoint args (cmd: Command) =
+ try
+ runMain args cmd |> fst
+ with
+ | RequestExit code -> code
+ | RequestShowHelp msg ->
+ cprintfn ConsoleColor.Red "error: %s\n" msg
+ for line in Help.generate (args |> List.ofArray) cmd do
+ printfn "%s" line
+ -1
+ | OptionParseFailed (_, msg)
+ | CommandExecutionFailed msg -> cprintfn ConsoleColor.Red "error: %s\n" msg; -1
+ | e -> reraise' e
+
+ /// stops the execution immediately and then exits with the specified code.
+ let exit code = RequestExit code |> raise
+
+ /// stops the execution immediately and then exits with the specified error message and code `-1`.
+ let fail msg = CommandExecutionFailed msg |> raise
+
+ /// stops the execution immediately and then exits with the specified error message and code `-1`.
+ let failf fmt = Printf.kprintf (fun msg -> CommandExecutionFailed msg |> raise ) fmt
+
+ /// if there are remaining unknown options, then stops the execution
+ /// immediately and then exits with code `-1`.
+ let failOnUnknownOptions () =
+ args |> bind (fun argv ->
+ let unknownOptions = CommandOption.getRemainingOptions argv
+ if List.isEmpty unknownOptions then returnValue ()
+ else
+ unknownOptions
+ |> List.head
+ |> sprintf "unknown option: '%s'"
+ |> CommandExecutionFailed
+ |> raise
+ )
+
+ /// shows the error message and the help of the current (sub)command, then exits with code `-1`.
+ let failShowingHelp message = RequestShowHelp message |> raise
\ No newline at end of file
diff --git a/src/common/Version.fs b/src/common/Version.fs
deleted file mode 100644
index c767a7a..0000000
--- a/src/common/Version.fs
+++ /dev/null
@@ -1,11 +0,0 @@
-// Auto-Generated by FAKE; do not edit
-namespace System
-open System.Reflection
-
-[]
-[]
-do ()
-
-module internal AssemblyVersionInformation =
- let [] AssemblyVersion = "3.3.3805.29705"
- let [] AssemblyFileVersion = "3.3.3805.29705"
diff --git a/src/FSharp.CommandLine/exceptions.fs b/src/exceptions.fs
old mode 100755
new mode 100644
similarity index 100%
rename from src/FSharp.CommandLine/exceptions.fs
rename to src/exceptions.fs
diff --git a/src/extensions.fs b/src/extensions.fs
new file mode 100644
index 0000000..58c792f
--- /dev/null
+++ b/src/extensions.fs
@@ -0,0 +1,22 @@
+namespace FSharp.CommandLine.Internals
+
+open Microsoft.FSharp.Quotations
+open Microsoft.FSharp.Quotations.Patterns
+open Microsoft.FSharp.Linq.RuntimeHelpers
+
+type FuncHelper = private | FuncHelper with
+ static member compileFunc (x: Expr<'a -> 'b>) =
+ LeafExpressionConverter.EvaluateQuotation x :?> ('a -> 'b)
+
+ static member getFirstArgumentName (x: Expr<'a -> 'b>) =
+ let rec gn tupleArgName = function
+ | Let (v, TupleGet(Var tn, index), body) when (tupleArgName = tn.Name) ->
+ (index, v.Name) :: gn tupleArgName body
+ | _ -> []
+ in
+ match x with
+ | Lambda (v, e) ->
+ match (gn v.Name e) with
+ | [] -> Some [v.Name]
+ | xs -> xs |> List.sortBy fst |> List.map snd |> Some
+ | _ -> None
diff --git a/src/FSharp.CommandLine/generators.fs b/src/generators.fs
old mode 100755
new mode 100644
similarity index 92%
rename from src/FSharp.CommandLine/generators.fs
rename to src/generators.fs
index 8ee45e4..7023f58
--- a/src/FSharp.CommandLine/generators.fs
+++ b/src/generators.fs
@@ -14,7 +14,7 @@ module Generators =
match config.subcommands |> List.tryFind (fun sc -> sc.Summary().name = List.head args) with
| Some sc -> dig (List.tail args) sc
| None -> (cmd, args)
-
+
let private getCommandInfo (cmd: Command<_>) =
let config = (cmd.config CommandInfo.empty)
(config.summary, config.subcommands, config.options)
@@ -40,7 +40,7 @@ module Generators =
yield! (bLines.Tail |> List.map (sprintf "%s %s" indent))
}
- let private genParamNames pns subs options =
+ let private genParamNames pns subs options =
match pns with
| Some xs -> xs |> String.concat " "
| None ->
@@ -51,7 +51,7 @@ module Generators =
| (false, false) -> "[options] "
/// given a help generator and a command, generates the help text.
- let interpret (generator: Command<_> -> #seq) (cmd: Command<_>) =
+ let interpret (generator: Command<_> -> HelpText) (cmd: Command<_>) =
let (smry, scs, opts) = getCommandInfo cmd
let dn = smry.displayName ?| smry.name
let rec print elems =
@@ -103,26 +103,21 @@ module Generators =
generator cmd |> print
/// a default help generator for the command.
- let defaultGenerator (cmd: Command<_>) =
+ let defaultGenerator (cmd: Command<_>) : HelpText =
let (smry, scs, opts) = getCommandInfo cmd
- helpText {
- defaultUsage
- emptyLine
- text smry.description
- emptyLine
- conditionalSection "commands" (fun () -> scs |> List.isEmpty |> not) (
- helpText {
- allSubcommands
- emptyLine
- }
- )
- conditionalSection "options" (fun () -> opts |> List.isEmpty |> not) (
- helpText {
- allOptions
- }
- )
+ seq {
+ yield HelpUsage
+ yield HelpEmptyLine
+ yield HelpRawString smry.description
+ yield HelpEmptyLine
+ if scs |> List.isEmpty |> not then
+ yield HelpAllSubcommands
+ yield HelpEmptyLine
+ if opts |> List.isEmpty |> not then
+ yield HelpAllOptions
+ yield HelpEmptyLine
}
-
+
/// generates a help text from the arguments and the command.
let generate args cmd =
let (cmd, _) = dig args cmd
@@ -187,7 +182,7 @@ module Generators =
| Values xs ->
"_values" :: "-w" :: "'values'" :: (xs |> List.map (escape >> quote))
| ValuesWithDescription xs ->
- "_values" :: "-w" :: "'values'" :: (xs |> List.map (fun (v, descr) -> sprintf "%s[%s]" v descr)
+ "_values" :: "-w" :: "'values'" :: (xs |> List.map (fun (v, descr) -> sprintf "%s[%s]" v descr)
|> List.map (escape >> quote))
| Files (Some pattern) -> "_files" :: "-g" :: [pattern |> quote]
| Files None -> ["_files"]
diff --git a/src/optionValues.fs b/src/optionValues.fs
new file mode 100644
index 0000000..a87e205
--- /dev/null
+++ b/src/optionValues.fs
@@ -0,0 +1,106 @@
+namespace FSharp.CommandLine
+
+open System
+open System.Text.RegularExpressions
+open FSharp.Scanf
+open FSharp.Scanf.Internals.Parser
+open FSharp.CommandLine.Internals
+open Microsoft.FSharp.Quotations
+
+type ValueFormat<'p,'st,'rd,'rl,'t,'a> = {
+ format: PrintfFormat<'p,'st,'rd,'rl,'t>
+ paramNames: (string list) option
+ handler: 't -> 'a
+}
+with
+ static member inline construct (this: ValueFormat<_,_,_,_,_,_>) =
+ let parser s =
+ s |> tryKsscanf this.format this.handler
+ |> function Ok x -> Some x | _ -> None
+ in
+ let formatTokens =
+ let defaultNames =
+ this.format.GetFormatterNames()
+ |> List.map (String.replace ' ' '_' >> String.toUpperInvariant)
+ |> List.map (sprintf "%s_VALUE")
+ in
+ let names = (this.paramNames ?| defaultNames) |> List.map (sprintf "<%s>") in
+ this.format.PrettyTokenize names
+ in
+ (parser, formatTokens)
+
+ member this.map ([]mapper: Expr<'a -> 'b>) =
+ let mf x = (FuncHelper.compileFunc mapper) x in
+ let pns = FuncHelper.getFirstArgumentName mapper in
+ { format = this.format; handler = this.handler >> mf; paramNames = pns }
+
+ member this.withNames names =
+ { this with paramNames = Some names }
+
+ member this.asConst value =
+ { format = this.format; handler = (fun _ -> value); paramNames = this.paramNames }
+
+type ValueRegex<'a> = {
+ regex: Regex
+ handler: string list -> 'a
+}
+with
+ static member construct (this: ValueRegex<_>) =
+ let parser (str: string) =
+ let m: Match = this.regex.Match(str)
+ if m.Success then
+ m.Groups
+ |> Seq.cast
+ |> List.ofSeq
+ |> List.zip (this.regex.GetGroupNames() |> List.ofArray)
+ |> List.filter (fun (name, _) -> name |> String.forall Char.IsDigit |> not)
+ |> List.map (fun (_, x) -> x.Value)
+ |> this.handler |> Some
+ else None
+ let tokens = [string this.regex]
+ (parser, tokens)
+
+ member this.map mapper =
+ { regex = this.regex; handler = this.handler >> mapper }
+
+ member this.asConst value =
+ { regex = this.regex; handler = fun _ -> value }
+
+type ValueTypedRegex<'a, '_Regex, '_Match > = {
+ typedRegex: '_Regex
+ handler: '_Match -> 'a
+}
+with
+ static member inline construct (this: ValueTypedRegex<_, ^Regex, ^Match>) : _
+ when ^Match :> Match =
+ let parser str =
+ let m = (^Regex: (member TypedMatch: string -> ^Match) this.typedRegex,str)
+ if m.Success then
+ this.handler m |> Some
+ else None
+ let tokens = [string this.typedRegex]
+ (parser, tokens)
+
+ member inline this.map mapper =
+ { typedRegex = this.typedRegex; handler = this.handler >> mapper }
+
+ member inline this.asConst value =
+ { typedRegex = this.typedRegex; handler = fun _ -> value }
+
+[]
+module OptionValues =
+ let inline format (fmt: PrintfFormat<_,_,_,_,'t>) : ValueFormat<_,_,_,_,'t,'t> =
+ { format = fmt; handler = id; paramNames = None }
+
+ let inline regex r =
+ { regex = Regex(r); handler = id }
+
+ let inline typedRegex< ^Regex, ^Match when ^Regex: (new: unit -> ^Regex) and ^Regex: (member TypedMatch: string -> ^Match) > : ValueTypedRegex< ^Match, ^Regex, ^Match > =
+ { typedRegex = new ^Regex(); handler = id }
+
+ let inline asConst value (optionValue: ^X) =
+ (^X: (member asConst: _ -> _) optionValue,value)
+
+ let inline internal construct (optionValue: ^X) =
+ (^X: (static member construct: _ -> _) optionValue)
+
diff --git a/src/options.fs b/src/options.fs
new file mode 100644
index 0000000..fc73062
--- /dev/null
+++ b/src/options.fs
@@ -0,0 +1,332 @@
+namespace rec FSharp.CommandLine
+
+open FSharp.Scanf
+open OptionParser
+
+/// specify how to treat options like ```-abcd```
+type SingleHyphenStyle =
+ /// treat ```-abcd``` as ```--abcd```
+ | SingleLong
+ /// treat ```-abcd``` as ```-a bcd```
+ | SingleShort
+ /// treat ```-abcd``` as ```-a -b -c -d```
+ | MergedShort
+
+type CommandOptionNoArgProvided<'a> =
+ | UseDefault of 'a
+ | JustFail
+
+type CommandOptionKind<'a> =
+ | Flag of (bool -> 'a)
+ | TakingValueWith of CommandOptionNoArgProvided<'a> * (string -> 'a option) list
+
+type ICommandOption<'a> =
+ abstract member Parse: string list -> ('a * string list)
+ abstract member Config: CommandInfo -> CommandInfo
+ abstract member Summary: CommandOptionSummary
+
+/// represents a command option parser that tries to parse the arguments
+/// and returns an optional result value.
+type CommandOption<'a> = {
+ baseSummary: CommandOptionSummary
+ kind: CommandOptionKind<'a>
+ style: SingleHyphenStyle
+}
+with
+ member this.Summary =
+ let self = this
+ {
+ this.baseSummary with
+ isMatch =
+ fun argv ->
+ match (parseImpl self argv) with
+ | (Some _, rem) -> Some rem
+ | (None, _) -> None
+ }
+ member this.Parse argv = parseImpl this argv
+
+ static member internal defaultOption : CommandOption<'a> = {
+ baseSummary = {
+ names = []
+ description = ""
+ isFlag = false
+ paramNames = []
+ isMatch = (fun _ -> None)
+ genSuggestions = (fun _ -> [])
+ }
+ kind = TakingValueWith (JustFail, [])
+ style = MergedShort
+ }
+
+ static member internal defaultFlag : CommandOption = {
+ baseSummary = {
+ names = []
+ description = ""
+ isFlag = true
+ paramNames = []
+ isMatch = (fun _ -> None)
+ genSuggestions = (fun _ -> [])
+ }
+ kind = Flag id
+ style = MergedShort
+ }
+
+ interface ICommandOption<'a option> with
+ member this.Summary = this.Summary
+ member this.Parse argv = parseImpl this argv
+ member this.Config cfg =
+ {
+ cfg with
+ options = this.Summary :: cfg.options
+ }
+
+/// represents a command option of which behavior and/or functionality are augmented.
+/// (e.g. can parse multiple occurrence of the option at once)
+type AugmentedCommandOption<'a, 'b> = {
+ orig: ICommandOption<'a>
+ augmenter: ICommandOption<'a> -> Args -> ('b * Args)
+}
+with
+ interface ICommandOption<'b> with
+ member this.Summary = this.orig.Summary
+ member this.Parse argv = this.augmenter this.orig argv
+ member this.Config cfg = (this.orig :> ICommandOption<_>).Config cfg
+
+module CommandOption =
+ /// gets the arguments which look like (will potentially be recognized by the parser as)
+ /// a command option.
+ let getRemainingOptions argv =
+ argv |> tokenize |> List.ofSeq
+ |> List.choose (function RIgnoreAfter | RValue _ -> None | x -> Some x)
+ |> List.map string
+
+ /// given a command option and arguments, applies the parser to the arguments
+ /// and returns the parsed result and the remaining arguments.
+ let inline parse (opt: #ICommandOption<_>) argv = opt.Parse argv
+
+ /// given a command option and arguments, applies the parser to the arguments until it fails
+ /// and returns the results and the remaining arguments.
+ let parseMany (opt: #ICommandOption<_>) argv =
+ let rec p xs =
+ seq {
+ yield!
+ match (opt.Parse xs) with
+ | (Some x, rest) ->
+ seq { yield (x, rest); yield! p rest }
+ | (None, _) ->
+ Seq.empty
+ }
+ let x = p argv
+ (x |> Seq.map fst |> List.ofSeq, x |> Seq.map snd |> Seq.tryLast ?| argv)
+
+ /// given a command option, augments its functionality by modifying
+ /// its behavior. both the original command option and the arguments which
+ /// will be passed at the execution time are available.
+ let inline augment f c = { orig=c; augmenter=f }
+ let inline map f c =
+ let ac = augment (fun c args -> c.Parse args) c
+ {
+ orig=ac.orig;
+ augmenter=(fun o x -> ac.augmenter o x |> Tuple.map2 f id)
+ }
+
+ /// given a command option, returns a new command option that parses
+ /// zero or more occurrence of that command option.
+ let inline zeroOrMore co =
+ co |> augment parseMany
+
+ /// given a command option, returns a new command option that fails
+ /// if there are more than one occurrence of that command option.
+ let inline zeroOrExactlyOne co =
+ co
+ |> zeroOrMore
+ |> map (function
+ | [] -> None
+ | x :: [] -> Some x
+ | _ ->
+ let msg = sprintf "the option '%s' should be provided only once"
+ (co.Summary.NameRepresentations |> List.head)
+ OptionParseFailed (co.Summary, msg) |> raise)
+
+ /// given a command option, returns a new command option that returns
+ /// the specified default value if there is no occurence.
+ let inline whenMissingUse defaultValue co =
+ co |> map (function Some x -> x | None -> defaultValue)
+
+ /// an active pattern to parse the arguments using the command option
+ /// and gets the result and the remaining arguments.
+ let inline (|Parse|_|) opt argv =
+ let (reso, argv') = parse opt argv
+ reso |> Option.map (fun x -> (x, argv'))
+
+module ReservedCommandOptions =
+ let helpOption =
+ {
+ baseSummary =
+ {
+ names = ["?"; "h"; "help"]
+ description = "display this help usage."
+ isFlag = false
+ paramNames = []
+ isMatch = fun _ -> None
+ genSuggestions = (fun _ -> [])
+ }
+ kind = Flag id
+ style = MergedShort
+ }
+
+ let suggestOption =
+ {
+ baseSummary =
+ {
+ names = ["generate-suggestions"; "generate-suggestions-incomplete"]
+ description = ""
+ isFlag = false
+ paramNames = [["name"]]
+ isMatch = fun _ -> None
+ genSuggestions = (fun _ -> [])
+ }
+ kind = TakingValueWith (UseDefault "zsh", [Some])
+ style = MergedShort
+ }
+
+module private OptionParser =
+ type RefinedToken =
+ | RFlag of string
+ | RFlagDisable of string
+ | RFlagAndValue of string * string
+ | RMaybeCombinedFlag of string
+ | RMaybeCombinedFlagAndValue of string * string
+ | RValue of string
+ | RIgnoreAfter
+ with
+ override this.ToString() =
+ match this with
+ | RFlag s -> sprintf "--%s" s
+ | RFlagDisable s -> sprintf "-%s-" s
+ | RFlagAndValue (s, v) -> sprintf "--%s=%s" s v
+ | RMaybeCombinedFlag s -> sprintf "-%s" s
+ | RMaybeCombinedFlagAndValue (s, v) -> sprintf "-%s=%s" s v
+ | RValue s -> s
+ | RIgnoreAfter -> "--"
+
+ let optionForms = [
+ tryKsscanf "--" (fun () -> RIgnoreAfter)
+ tryKsscanf "-%c" (RFlag << string);
+ tryKsscanf "-%c=%s" (Tuple.map2 string id >> RFlagAndValue);
+ tryKsscanf "--%s=%s" RFlagAndValue;
+ tryKsscanf "/%s=%s" RFlagAndValue;
+ tryKsscanf "--%s" RFlag;
+ tryKsscanf "-%c+" (RFlag << string);
+ tryKsscanf "-%c-" (RFlagDisable << string);
+ tryKsscanf "-%s=%s" RMaybeCombinedFlagAndValue;
+ tryKsscanf "-%s" RMaybeCombinedFlag;
+ tryKsscanf "/%s" RFlag;
+ tryKsscanf "%s" RValue
+ ]
+
+ let rec tokenize argv =
+ seq {
+ if List.isEmpty argv then
+ yield! Seq.empty
+ else
+ let (h, t) = (List.head argv, List.tail argv)
+ let ro = optionForms |> List.map (fun f -> f h)
+ |> List.choose (function Ok x -> Some x | _ -> None)
+ |> List.tryHead
+ if Option.isSome ro then
+ yield ro.Value;
+ yield!
+ match ro.Value with
+ | RIgnoreAfter -> t |> Seq.map RValue
+ | _ -> tokenize t
+ else
+ yield! Seq.empty
+ }
+
+ let parseImpl (opt: CommandOption<'a>) argv =
+ let inline isSingle s = String.length s = 1
+ let inline matches x = opt.baseSummary.names |> List.contains x
+ let shortNames = opt.baseSummary.names |> List.filter isSingle
+ let opf msg = OptionParseFailed(opt.baseSummary, msg)
+
+ let tokens = tokenize argv |> List.ofSeq
+ let rec find ts =
+ match opt.kind with
+ | Flag f ->
+ let inline f x = f x |> Some
+ match ts with
+ | RFlag x :: rest when matches x -> (f true, rest)
+ | RFlagDisable x :: rest when matches x -> (f false, rest)
+ | RFlagAndValue (x, _) :: _ when matches x ->
+ sprintf "'%s' is a flag and does not take an argument" x |> opf |> raise
+ | RMaybeCombinedFlag xs :: rest & x :: _ ->
+ match opt.style with
+ | MergedShort when shortNames |> List.exists xs.Contains ->
+ let c = shortNames |> List.find xs.Contains
+ (f true, RMaybeCombinedFlag (xs.Replace(c, "")) :: rest)
+ | SingleLong when matches xs -> (f true, rest)
+ | SingleShort when shortNames |> List.exists xs.StartsWith ->
+ sprintf "'%c' is a flag and does not take an argument" (xs.[0]) |> opf |> raise
+ | _ -> find rest |> Tuple.map2 id (fun rest' -> x :: rest')
+ | RMaybeCombinedFlagAndValue (xs, v) :: rest & x :: _ ->
+ match opt.style with
+ | MergedShort when shortNames |> List.exists xs.Contains ->
+ let c = shortNames |> List.find xs.Contains
+ if shortNames |> List.exists xs.EndsWith then
+ sprintf "'%s' is a flag and does not take an argument" c |> opf |> raise
+ else
+ (f true, RMaybeCombinedFlagAndValue(xs.Replace(c, ""), v) :: rest)
+ | SingleLong when matches xs ->
+ sprintf "'%s' is a flag and does not take an argument" xs |> opf |> raise
+ | SingleShort -> sprintf "invalid option: '-%s=%s'" xs v |> opf |> raise
+ | _ -> find rest |> Tuple.map2 id (fun rest' -> x :: rest')
+ | x :: rest -> find rest |> Tuple.map2 id (fun rest' -> x :: rest')
+ | [] -> (None, [])
+ | TakingValueWith (na, fs) ->
+ let inline tryReturn v name =
+ match (fs |> List.map (fun f -> f v) |> List.choose id |> List.tryHead) with
+ | Some x -> Some x
+ | None ->
+ sprintf "the value '%s' is invalid for the option '%s'" v name |> opf |> raise
+ let inline tryDefault name =
+ match na with
+ | UseDefault x -> Some x
+ | JustFail ->
+ sprintf "a value is missing for the option '%s'" name |> opf |> raise
+ match ts with
+ | RFlag x :: RValue v :: rest
+ | RFlagAndValue (x, v) :: rest when matches x -> (tryReturn v x, rest)
+ | RFlag x :: rest when matches x -> (tryDefault x, rest)
+ | RFlagDisable x :: _ when matches x ->
+ sprintf "a value is missing for the option '%s'" x |> opf |> raise
+ | RMaybeCombinedFlag xs :: RValue v :: rest & x :: _ :: _->
+ match opt.style with
+ | MergedShort when shortNames |> List.exists xs.EndsWith ->
+ let c = shortNames |> List.find xs.EndsWith
+ (tryReturn v c, RMaybeCombinedFlag (xs.Replace(c, "")) :: rest)
+ | MergedShort when shortNames |> List.exists xs.Contains ->
+ let c = shortNames |> List.find xs.Contains
+ (tryDefault c, RMaybeCombinedFlag (xs.Replace(c, "")) :: RValue v :: rest)
+ | SingleShort when shortNames |> List.exists xs.StartsWith ->
+ let c = shortNames |> List.find xs.StartsWith
+ let v' = xs.Substring(1)
+ (tryReturn v' c, RValue v :: rest)
+ | SingleLong when matches xs ->
+ (tryReturn v xs, rest)
+ | _ -> find rest |> Tuple.map2 id (fun rest' -> x :: RValue v :: rest')
+ | RMaybeCombinedFlagAndValue (xs, v) :: rest & x :: _ ->
+ match opt.style with
+ | MergedShort when shortNames |> List.exists xs.EndsWith ->
+ let c = shortNames |> List.find xs.EndsWith
+ (tryReturn v c, RMaybeCombinedFlag (xs.Replace(c, "")) :: rest)
+ | MergedShort when shortNames |> List.exists xs.Contains ->
+ let c = shortNames |> List.find xs.Contains
+ (tryDefault c, RMaybeCombinedFlagAndValue (xs.Replace(c, ""), v) :: rest)
+ | SingleLong when matches xs ->
+ (tryReturn v xs, rest)
+ | SingleShort -> sprintf "invalid option: '-%s=%s'" xs v |> opf |> raise
+ | _ -> find rest |> Tuple.map2 id (fun rest' -> x :: rest')
+ | x :: rest -> find rest |> Tuple.map2 id (fun rest' -> x :: rest')
+ | [] -> (None, [])
+ find tokens |> Tuple.map2 id (List.map string)
diff --git a/src/common/prelude.fs b/src/prelude.fs
old mode 100755
new mode 100644
similarity index 97%
rename from src/common/prelude.fs
rename to src/prelude.fs
index 3db31c8..a4d9be0
--- a/src/common/prelude.fs
+++ b/src/prelude.fs
@@ -29,13 +29,12 @@ module internal Prelude
[]
module ToplevelOperators =
open System
- let inline to_s x = x.ToString()
let inline (?|) opt df = defaultArg opt df
let inline (!!) (x: Lazy<'a>) = x.Value
- let inline undefined (x: 'a) : 'b = NotImplementedException(to_s x) |> raise
+ let inline undefined (x: 'a) : 'b = NotImplementedException(string x) |> raise
let inline reraise' ex = System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw(); failwith "impossible"
@@ -88,7 +87,7 @@ module Flag =
xs |> Seq.fold (|||) (Unchecked.defaultof< ^flag >)
let inline contains (x: ^flag) (flags: ^flag) : bool
when ^flag: enum =
- (x &&& flags) = x
+ (x &&& flags) = x
module Number =
open System.Globalization
@@ -123,7 +122,7 @@ module Patterns =
match x with
| Some v -> v
| None -> dv
-
+
[]
module Kvp =
open System.Collections.Generic
@@ -151,16 +150,16 @@ module String =
let inline contains (s: ^a) (str: ^String) : bool = (^String: (member IndexOf: ^a -> int) str, s) <> -1
- let inline findIndex (q: ^T) (str: ^String) =
+ let inline findIndex (q: ^T) (str: ^String) =
(^String: (member IndexOf: ^T -> int) (str, q))
- let inline findIndexAfter (q: ^T) i (str: ^String) =
+ let inline findIndexAfter (q: ^T) i (str: ^String) =
(^String: (member IndexOf: ^T -> int -> int) (str, q, i))
- let inline findLastIndex (q: ^T) (str: ^String) =
+ let inline findLastIndex (q: ^T) (str: ^String) =
(^String: (member LastIndexOf: ^T -> int) (str, q))
- let inline findLastIndexAfter (q: ^T) i (str: ^String) =
+ let inline findLastIndexAfter (q: ^T) i (str: ^String) =
(^String: (member LastIndexOf: ^T -> int -> int) (str, q, i))
let inline insertAt s i (str: string) = str.Insert(i, s)
@@ -173,7 +172,7 @@ module String =
let inline substring startIndex endIndex (str: string) = str.Substring(startIndex, endIndex)
- let inline normalize (nfo: NormalizationForm option) (str: string) =
+ let inline normalize (nfo: NormalizationForm option) (str: string) =
match nfo with Some nf -> str.Normalize nf | None -> str.Normalize()
let inline toLower (ci: CultureInfo) (str: string) = str.ToLower ci
@@ -187,7 +186,7 @@ module String =
let inline padLeft i (str: string) = str.PadLeft i
let inline padLeftBy i c (str: string) = str.PadLeft(i, c)
-
+
let inline padRight i (str: string) = str.PadRight i
let inline padRightBy i c (str: string) = str.PadRight(i, c)
@@ -199,15 +198,15 @@ module String =
let inline trimEnd (str: string) = str.TrimEnd()
let inline trimBy (trimChar: char) (str: string) = str.Trim(trimChar)
-
+
let inline trimBySeq (trimChars: char seq) (str: string) = str.Trim(trimChars |> Seq.toArray)
let inline trimStartBy (trimChar: char) (str: string) = str.TrimStart(trimChar)
-
+
let inline trimStartBySeq (trimChars: char seq) (str: string) = str.TrimStart(trimChars |> Seq.toArray)
let inline trimEndBy (trimChar: char) (str: string) = str.TrimEnd(trimChar)
-
+
let inline trimEndBySeq (trimChars: char seq) (str: string) = str.TrimEnd(trimChars |> Seq.toArray)
let inline replace (before: ^T) (after: ^T) (s: ^String) =
@@ -227,7 +226,7 @@ module String =
let inline nth i (str: string) = str.[i]
- let inline rev (str: string) =
+ let inline rev (str: string) =
new String(str.ToCharArray() |> Array.rev)
let inline private whileBase pred act str =
@@ -275,7 +274,7 @@ module StringExtensions =
open System.Collections.Generic
type array2d<'t> = 't[,]
-type array3d<'t> = 't[,,]
+type array3d<'t> = 't[,,]
module List =
let inline splitWith predicate xs =
@@ -309,10 +308,10 @@ module Seq =
xs |> Seq.groupBy (fun x -> if predicate x then incr i; 0 else !i)
|> Seq.filter (fst >> ((<>) 0))
|> Seq.map snd
-
+
let inline split separator xs = splitWith ((=) separator) xs
- let inline skipSafe length xs =
+ let inline skipSafe length xs =
xs |> Seq.indexed
|> Seq.skipWhile (fst >> ((>) length))
|> Seq.map snd
@@ -322,7 +321,7 @@ module Seq =
if xs' |> Seq.exists (fst >> ((=) (length - 1))) then
xs' |> Seq.take length |> Seq.map snd |> Some
else None
-
+
let inline foldi folder state xs =
Seq.fold (fun (i, state) x -> (i + 1, folder i state x)) (0, state) xs |> snd
@@ -365,12 +364,12 @@ module Map =
/// will be called: the first parameter is the key, the second is the value
/// found in the formar map `m1`, and the third is the one found in `m2`.
let inline merge merger m1 m2 =
- Map.fold (fun m k v1 ->
+ Map.fold (fun m k v1 ->
match m |> Map.tryFind k with
| Some v2 -> Map.add k (merger k v1 v2) m
| None -> Map.add k v1 m
) m1 m2
-
+
/// Merges multiple maps. If there is a duplicate key, the `merger` function
/// will be called: the first parameter is the key, the second is the value
/// already found in the earlier maps, and the third is the value newly found.
@@ -420,7 +419,7 @@ module Lazy =
let inline run (x: Lazy<_>) = x.Value
let inline force (x: Lazy<_>) = x.Force()
-
+
let inline bind (f: 'a -> Lazy<'b>) (x: Lazy<'a>) : Lazy<'b> =
Lazy<_>.Create (fun () -> x |> force |> f |> force)
@@ -451,7 +450,7 @@ module Result =
match res with
| Ok x -> Some x
| Error _ -> None
-
+
let inline toChoice res =
match res with
| Ok x -> Choice1Of2 x
@@ -512,10 +511,10 @@ module ComputationExpressions =
member inline this.Undelay f = f()
member inline this.TryWith (f, h) = try f() with exn -> h exn
member inline this.TryFinally (f, h) = try f() finally h()
-
+
// boilerplate for any monad to add for/while
-
+
member inline this.Zero () = this.Return ()
member inline this.Using (disp: #System.IDisposable, m) =
this.TryFinally(
@@ -542,7 +541,7 @@ module ComputationExpressions =
member inline this.Bind(m, f) = Option.bind f m
member inline this.Return x = Some x
member inline this.ReturnFrom x = x
-
+
member inline this.Delay f = f
member inline this.Undelay f = f()
member inline this.TryWith (f, h) = try f() with exn -> h exn
@@ -568,17 +567,17 @@ module ComputationExpressions =
en.MoveNext,
this.Delay(fun () -> exec en.Current))
)
-
+
type ResultBuilder() =
member inline this.Bind(m, f) = Result.bind f m
member inline this.Return x = Ok x
member inline this.ReturnFrom x = x
-
+
member inline this.Delay f = f
member inline this.Undelay f = f()
member inline this.TryWith (f, h) = try f() with exn -> h exn
member inline this.TryFinally (f, h) = try f() finally h()
-
+
member inline this.Zero () = this.Return ()
member inline this.Using (disp: #System.IDisposable, m) =
this.TryFinally(
@@ -599,7 +598,7 @@ module ComputationExpressions =
en.MoveNext,
this.Delay(fun () -> exec en.Current))
)
-
+
type LazyBuilder() =
member inline this.Bind(m, f) = Lazy.bind f m
@@ -612,7 +611,7 @@ module ComputationExpressions =
lazy (try Lazy.force m with exn -> f exn)
member inline this.TryFinally (m, f) =
lazy (try Lazy.force m finally f() )
-
+
member inline this.Zero () = this.Return ()
member inline this.Using (disp: #System.IDisposable, m) =
this.TryFinally(
@@ -636,9 +635,9 @@ module ComputationExpressions =
open System.Threading.Tasks
type AsyncBuilder with
- member inline this.Bind(t:Task<'T>, f:'T -> Async<'R>) : Async<'R> =
+ member inline this.Bind(t:Task<'T>, f:'T -> Async<'R>) : Async<'R> =
async.Bind(Async.AwaitTask t, f)
- member inline this.Bind(t:Task, f:unit -> Async<'R>) : Async<'R> =
+ member inline this.Bind(t:Task, f:unit -> Async<'R>) : Async<'R> =
async.Bind(Async.AwaitTask t, f)
[]
@@ -662,14 +661,14 @@ module Path =
let filePath = new Uri(file)
let path =
new Uri (
- if (parentDir |> String.endsWith (to_s Path.DirectorySeparatorChar) |> not) then
+ if (parentDir |> String.endsWith (string Path.DirectorySeparatorChar) |> not) then
sprintf "%s%c" parentDir Path.DirectorySeparatorChar
else
parentDir
)
Uri.UnescapeDataString(
path.MakeRelativeUri(filePath)
- |> to_s
+ |> string
|> String.replace '/' Path.DirectorySeparatorChar)
module File =
@@ -679,7 +678,7 @@ module File =
module Directory =
let inline isHidden dir =
DirectoryInfo(dir).Attributes.HasFlag(FileAttributes.Hidden)
-
+
let rec enumerateFilesRecursively includeHidden dir =
seq {
for x in Directory.EnumerateFiles dir do
@@ -710,8 +709,8 @@ module Task =
let inline bind (f: 'a -> 'b task) (t: 'a task) : 'b task =
t.ContinueWith(fun (x: _ task) -> f x.Result).Unwrap()
- let inline returnValue x : _ task=
- let s = TaskCompletionSource()
+ let inline returnValue x : 'a task =
+ let s = new TaskCompletionSource<'a>()
s.SetResult x
s.Task
@@ -832,7 +831,7 @@ module Shell =
do p.StartInfo.FileName <- cmd
do p.StartInfo.Arguments <- args |> String.concat " "
do p.Start() |> ignore
- do p.WaitForExit()
+ do p.WaitForExit()
return p.ExitCode
}
diff --git a/src/version.fs b/src/version.fs
new file mode 100644
index 0000000..05753b2
--- /dev/null
+++ b/src/version.fs
@@ -0,0 +1,11 @@
+// Auto-Generated by FAKE; do not edit
+namespace System
+open System.Reflection
+
+[]
+[]
+do ()
+
+module internal AssemblyVersionInformation =
+ let [] AssemblyVersion = "4.0.0"
+ let [] AssemblyFileVersion = "4.0.0"