1
\$\begingroup\$

I am new to Elixir and experimenting a bit with my knowledge so far. I wrote a skeleton for a basic commandline application and I am looking for feedback (e.g. whether the code is ideomatic). The code is a bit abstract, but I try to explain, what I wanted to accomplish so far:

The usage of the app is $name $command $options. Only exception when the user calls it with the --help flag. There are two commands command and other with options opt1 and opt2 / opt3. The use of opt2 is optional.

Valid usages would be:

./playground --help

./playground --opt1 blah

defmodule Playground do
  @moduledoc """
  Documentation for Playground.
  """

  @doc """
  Hello world.

  ## Examples

      iex> Playground.hello
      :world

  """

  @command "command"
  @othercommand "other"
  @helpcommand "--help"

  def main([]) do
    app(:usage)
  end

  def main([@helpcommand]) do
    app(:help)
  end

  def main(args) do
    args
    |> parse_args
    |> app
  end

  def parse_args(args) do
    [command|options] = args
    parsed = OptionParser.parse(options, strict: [opt1: :string, opt2: :string, opt3: :string])
    case {command, parsed} do
      {@command, {[opt1: opt1], [], []}} -> {:command, %{:opt1=>opt1, :opt2=> "default"}}
      {@command, {[opt1: opt1, opt2: opt2], [], []}} -> {:command, %{:opt1=>opt1, :opt2=>opt2}}
      {@othercommand, {[opt3: otheroptions], [], []}} -> {:other, otheroptions}
      _-> :usage
    end
  end

  def app(:help) do
    IO.puts("Helptext")
  end

  def app(:usage) do
    IO.puts("Usage")
  end

  def app({:other, options}) do
    IO.puts("Other #{options}")
  end

  def app({:command, options}) do
    IO.puts("Command #{options[:opt1]} #{options[:opt2]}")
  end
end

I am mainly interested in:

  1. Is it okay/best practice to have "multiple" main entries (depending on the number of arguments given)? In an earlier version, I had one main but an additional case statement, which I found annoying.

  2. Is it good practice to have a Map containing options for the function called after option parsing, or would it be better to separate each parameter. The latter makes it unnecessary to "unpack" options in the function via options[:option].

  3. Is my way of patern matching to parse different commands/options a good way to do it, or is there a better way?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.