OptionParser and CLI

I was studying Programming Elixir 1.6. In this book, the author uses the module OptionParser without further explanations.
I read the elixir documentation, but I still cannot understand what every function does. Is there any easier resource in order to grasp all this (CLI and options parsing) ?

There is this post:
Writing a Command Line Application in Elixir (Intermediate level)

You’re likely talking about this:
https://media.pragprog.com/titles/elixir16/code/project/0/issues/lib/issues/cli.ex

and it only uses parse/2 which features a bunch of examples.

If this is your first exposure to command line parsing there might other non-Elixir, non-OptionParser gaps that need to be filled - can you highlight any specific areas that are giving you trouble?

1 Like

Most people learning Elixir started with ruby or Erlang so CLI is obvious for them. For me it’s different, Elixir is my first programming language. It’s normal that I will not understand some modules in Elixir. I had trouble understanding what parsing is ? what strict mode is ? what switches are ? etc.

Maybe I have picked a language not suitable for beginners.

This is the module explained in python website. Compare the level of details. Python Website has more details which makes understanding things easier.

It’s less of a programming thing and more of a scripting thing - lots of RoR developers have never crafted a CLI, others live in IDEs creating logic that doesn’t rely on the command line. Now when it comes to shell scripting command line interface terminology is important - and Python is often used as a shell language replacement.

In your case I think Dave’s test first approach is leaving you hanging without a mental model of what is actually going on. Try this:

defmodule Issues.CLI do
  def main(argv) do
    IO.inspect argv
  end
end

Then modify the mix.exs:

  def project do
    [
      app: :issues,
      escript: [main_module: Issues.CLI], # ADD THIS LINE
      version: "0.1.0",
      elixir: "~> 1.6",
      start_permanent: Mix.env() == :prod,
      deps: deps()
    ]
  end

And then run this:

$ mix escript.build
Compiling 2 files (.ex)
Generated issues app
Generated escript issues with MIX_ENV=dev

$ ./issues pragdave earmark 4
["pragdave", "earmark", "4"]
$ 

So the first thing you should notice is that the parameters are supplied to you as a list of strings - the arguments on the command line are white space delimited.

Now update cli.ex:

defmodule Issues.CLI do
  def main(argv) do
    IO.inspect(
      OptionParser.parse(
        argv,
        switches: [ help: :boolean],
        aliases: [ h: :help ]
      ))
  end
end

And run

$ mix escript.build
Compiling 1 file (.ex)
Generated escript issues with MIX_ENV=dev
$ ./issues pragdave earmark 4
{[], ["pragdave", "earmark", "4"], []}
$ ./issues --help
{[help: true], [], []}
$ ./issues -h
{[help: true], [], []}
$ ./issues -h pragdave earmark 4
{[help: true], ["pragdave", "earmark", "4"], []}
$ 
3 Likes

Now update cli.ex:

defmodule Issues.CLI do
  def main(argv) do
    IO.inspect(
      OptionParser.parse(
        argv,
        switches: [ help: :boolean],
        aliases: [ h: :help ]
      ))
  end
end

And run

$ mix escript.build
Compiling 1 file (.ex)
Generated escript issues with MIX_ENV=dev
$ ./issues pragdave earmark 4
{[], ["pragdave", "earmark", "4"], []}
$ ./issues --help
{[help: true], [], []}
$ ./issues -h
{[help: true], [], []}
$ ./issues -h pragdave earmark 4
{[help: true], ["pragdave", "earmark", "4"], []}
$ 
  • parse returns a tuple of three lists, the first contains the result generated by parse, the second arguments not processed by parse and the third one any errors.
  • --help is a switch of type :boolean as it does not need any of the arguments that follow it. Its mere presence is meaningful - often used to turn features on or off. If the type was :string the next argument would be used to create a tuple, e.g. {:help, "pragdave"}.
  • -h is a different way of specifying --help - so it’s an alias as both result in a {:help, true} tuple.
3 Likes

Okay Thanks.
But the cause of my question is more about understanding what is behind the scenes. I knew that the author chose this project ( Crafting a CLI ) just to explain how to use mix. But i was wondering why he didn’t focus also on explaining well the algorithm and the functions used. Othewise the readers will just copy-paste code.

You mean the OptionParser module and it’s functions? He’s not setting out to teach what the module does - he is more interested in demonstrating test first development to drive towards a finished product.

And given that most Elixir tools are on the command line he’s probably assuming that the reader is very familiar with working the command line and providing varying arguments to programs to alter their behaviour.