what we blog

Writing a command line application in Elixir

During the last days I got the chance to spend a bit of time playing around with Elixir. Elixir is, compared to other languages still a very new one. It has a Ruby-like syntax and compiles to Erlang VM bytecode. It is available for all major Linux distributions, Mac OS X and Windows.

For install instructions, please check their guide here.

At first, check your installed version:

$ elixir -v
Elixir 1.0.3

Everything >= 1.0 is fine.

We start with a scaffold by running mix new. mix basically does the job of Ruby’s bundler and rake. mix new creates a folder structure and places some files in there which are necessary to build an Elixir application.

$ mix new example

This creates a new folder example with the following structure:

$ tree example
example
├── README.md
├── config
│   └── config.exs
├── lib
│   └── example.ex
├── mix.exs
└── test
    ├── example_test.exs
    └── test_helper.exs

3 directories, 6 files

There is a lib folder which contains all application code. mix.exs holds the metadata and dependencies of your application. Now run mix to compile your app the first time.

Elixir uses escript to build an executable. Its only dependency is Erlang installed on your machine. Elixir is not necessary, since escript embedds Elixir into the compiled app. At first we need to set the main_module in mix.exs by extending the existing function:

def project do
  [app: :example,
  version: "0.0.1",
  elixir: "~> 1.0",
  escript: [main_module: Example],  # <- add this line
  deps: deps]
end

This require a main function in your main module:

defmodule Example do
  def main(args) do
    IO.puts "Hello world"
  end
end

The main function gets some args containing all arguments passed from the command line. args is a list holding all passed arguments or in case the user didn't pass anything, it's empty. Elixir ships with builtin support for option parsing. The module is called OptionParser:

  defp parse_args(args) do
    {options, _, _} = OptionParser.parse(args,
      switches: [foo: :string]
    )
    options
  end

This function is also defined in the Example module. It takes the command line arguments and parses them. We need to tell OptionParser what switches we expect. parse/2 returns a tuple containing three values where we're only interested in the first one. The second element holds remaining arguments and the last one invalid options. options is a Keyword list containing all options converted to atoms with their associated value.

The following example handles a name option and prints out a greeting if given or another string if not.

defmodule Example do
  def main(args) do
    args |> parse_args |> process
  end

  def process([]) do
    IO.puts "No arguments given"
  end

  def process(options) do
    IO.puts "Hello #{options[:name]}"
  end

  defp parse_args(args) do
    {options, _, _} = OptionParser.parse(args,
      switches: [name: :string]
    )
    options
  end
end

Then create an executable and run it with an argument:

$ mix escript.build
$ ./example --name=Jan

The main function of the module takes all arguments, parses them and outputs a string to stdout. The functions use pattern matching to determine if option name is available or not and prints a string accordingly.