Command Line Subcommands in Erlang
Here’s the translation of the Go code example to Erlang, formatted in Markdown suitable for Hugo:
Our first program demonstrates how to create command-line subcommands with their own set of flags. This is similar to tools like git
where different subcommands (e.g., git commit
, git push
) have their own flags.
-module(command_line_subcommands).
-export([main/1]).
main(Args) ->
case Args of
["foo" | FooArgs] ->
handle_foo(FooArgs);
["bar" | BarArgs] ->
handle_bar(BarArgs);
_ ->
io:format("expected 'foo' or 'bar' subcommands~n"),
halt(1)
end.
handle_foo(Args) ->
{FooOpts, FooArgs} = parse_foo_args(Args),
io:format("subcommand 'foo'~n"),
io:format(" enable: ~p~n", [proplists:get_value(enable, FooOpts)]),
io:format(" name: ~p~n", [proplists:get_value(name, FooOpts)]),
io:format(" tail: ~p~n", [FooArgs]).
handle_bar(Args) ->
{BarOpts, BarArgs} = parse_bar_args(Args),
io:format("subcommand 'bar'~n"),
io:format(" level: ~p~n", [proplists:get_value(level, BarOpts)]),
io:format(" tail: ~p~n", [BarArgs]).
parse_foo_args(Args) ->
parse_foo_args(Args, [], []).
parse_foo_args([], Opts, Rest) ->
{lists:reverse(Opts), lists:reverse(Rest)};
parse_foo_args(["-enable" | Rest], Opts, Acc) ->
parse_foo_args(Rest, [{enable, true} | Opts], Acc);
parse_foo_args(["-name", Name | Rest], Opts, Acc) ->
parse_foo_args(Rest, [{name, Name} | Opts], Acc);
parse_foo_args([Arg | Rest], Opts, Acc) ->
parse_foo_args(Rest, Opts, [Arg | Acc]).
parse_bar_args(Args) ->
parse_bar_args(Args, [], []).
parse_bar_args([], Opts, Rest) ->
{lists:reverse(Opts), lists:reverse(Rest)};
parse_bar_args(["-level", Level | Rest], Opts, Acc) ->
parse_bar_args(Rest, [{level, list_to_integer(Level)} | Opts], Acc);
parse_bar_args([Arg | Rest], Opts, Acc) ->
parse_bar_args(Rest, Opts, [Arg | Acc]).
To compile and run the program:
$ erlc command_line_subcommands.erl
$ erl -noshell -s command_line_subcommands main foo -enable -name joe a1 a2 -s init stop
subcommand 'foo'
enable: true
name: "joe"
tail: ["a1","a2"]
$ erl -noshell -s command_line_subcommands main bar -level 8 a1 -s init stop
subcommand 'bar'
level: 8
tail: ["a1"]
In this Erlang version, we’ve implemented a basic command-line argument parser to handle subcommands and their respective flags. The main/1
function acts as the entry point and dispatches to the appropriate handler based on the subcommand.
Each subcommand (foo
and bar
) has its own parsing function to handle its specific flags. The parsing functions return a tuple with the parsed options and the remaining arguments.
Note that Erlang doesn’t have a built-in flag parsing library like Go’s flag
package, so we’ve implemented a simple custom parser. In a real-world application, you might want to use a more robust argument parsing library.
This example demonstrates how to structure a command-line application with subcommands in Erlang, providing similar functionality to the original Go example.