For F# apps, I've traditionally used different functional-friendly command line parsers like Argu and CommandLineParser.
Now that Microsoft has come up with System.CommandLine (with potentially brings better support and documentation), is it usable from F#?
Functional-friendliness is subjective, but I found the API rather convenient for F#:
open System.CommandLine
open System.CommandLine.Invocation
[<EntryPoint>]
let main argv =
let option1 = Option<string> "--option1"
let option2 = Option<string> "--option2"
let option3 = Option<string> "--option3"
let option4 = Option<string> "--option4"
let command1 = Command "command 1"
command1.AddOption option1
command1.AddOption option2
command1.Handler <- CommandHandler.Create (fun option1 option2 -> Operation1.run option1 option2)
let command2 = Command "command 2"
command2.AddOption option3
command2.AddOption option4
command2.Handler <- CommandHandler.Create (fun option3 option4 -> Operation1.run option3 option4)
let rootCommand = RootCommand "My tool."
rootCommand.AddCommand command1
rootCommand.AddCommand command2
rootCommand.Invoke argv
To make code more fun, some trivial helpers can help:
open System.CommandLine
let addCommand subCommand (command: Command) =
command.AddCommand subCommand
command
let addOption option (command: Command) =
command.AddOption option
command
let setHandler handler (command: Command) =
command.Handler <- handler
command
To be used like:
open System.CommandLine
open System.CommandLine.Invocation
[<EntryPoint>]
let main argv =
let option1 = Option<string> "--option1"
let option2 = Option<string> "--option2"
let option3 = Option<string> "--option3"
let option4 = Option<string> "--option4"
let command1 =
Command "command 1"
|> addOption option1
|> addOption option2
|> setHandler (CommandHandler.Create (fun option1 option2 -> Operation1.run option1 option2))
let command2 =
Command "command 2"
|> addOption option3
|> addOption option4
|> setHandler (CommandHandler.Create (fun option3 option4 -> Operation2.run option3 option4))
let rootCommand =
RootCommand "My tool."
|> addCommand command1
|> addCommand command2
rootCommand.Invoke argv
This also seems to be a dedicated library for having System.CommandLine
in the F# way.
F# was likely taken into mind during the library design, although there are some caveats, e.g. this one for command handler binding.
In general, the library is still in the preview so the API might substantially change in the future.