Command Line Subcommands in Elm
Here’s the translation of the Go code to Elm, formatted in Markdown suitable for Hugo:
Our first program will demonstrate how to create a command-line application with subcommands in Elm. Here’s the full source code:
module Main exposing (main)
import Platform exposing (Program)
import Platform.Cmd as Cmd
import Platform.Sub as Sub
import Arg.Parser as Parser exposing (Parser)
import Arg.Parser.OptionsParser as OptionsParser
type alias Model =
{ subcommand : Maybe Subcommand
}
type Subcommand
= Foo { enable : Bool, name : String }
| Bar { level : Int }
type Msg
= NoOp
init : List String -> ( Model, Cmd Msg )
init args =
let
parsedArgs =
Parser.parse subcommandParser args
in
case parsedArgs of
Ok subcommand ->
( { subcommand = Just subcommand }, Cmd.none )
Err _ ->
( { subcommand = Nothing }, Cmd.none )
subcommandParser : Parser Subcommand
subcommandParser =
Parser.oneOf
[ Parser.map Foo (Parser.commandWithOptions "foo" fooOptionsParser)
, Parser.map Bar (Parser.commandWithOptions "bar" barOptionsParser)
]
fooOptionsParser : OptionsParser.Parser { enable : Bool, name : String }
fooOptionsParser =
OptionsParser.build (\enable name -> { enable = enable, name = name })
|> OptionsParser.with (OptionsParser.flag "enable")
|> OptionsParser.with (OptionsParser.optionalKeywordArg "name" "")
barOptionsParser : OptionsParser.Parser { level : Int }
barOptionsParser =
OptionsParser.build (\level -> { level = level })
|> OptionsParser.with (OptionsParser.optionalKeywordArg "level" "0" |> OptionsParser.map (String.toInt >> Maybe.withDefault 0))
update : Msg -> Model -> ( Model, Cmd Msg )
update _ model =
( model, Cmd.none )
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
main : Program (List String) Model Msg
main =
Platform.worker
{ init = init
, update = update
, subscriptions = subscriptions
}
In this Elm program, we’re using the Arg.Parser
library to parse command-line arguments and define subcommands.
We define two subcommands: foo
and bar
. The foo
subcommand has enable
and name
options, while the bar
subcommand has a level
option.
The subcommandParser
function defines how to parse these subcommands and their options.
To run this program, you would compile it to JavaScript and then run it with Node.js, passing the subcommand and its options as command-line arguments.
$ elm make Main.elm --output=main.js
$ node main.js foo --enable --name=joe a1 a2
This would parse the foo
subcommand with the enable
flag set to true, the name
set to “joe”, and additional arguments “a1” and “a2”.
$ node main.js bar --level=8 a1
This would parse the bar
subcommand with the level
set to 8 and an additional argument “a1”.
Note that Elm is primarily designed for web applications, so running it as a command-line application is not its typical use case. In a real-world scenario, you might consider using a language more suited for command-line applications.
This example demonstrates how to structure a program with subcommands in Elm, even though the actual execution and output would require additional setup.