1

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#?

psfinaki
  • 1,814
  • 15
  • 29

1 Answers1

2

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.

psfinaki
  • 1,814
  • 15
  • 29