I want to create something fairly simple and play with some of the Elixir concepts. I don’t have much experience with Elixir yet so I’ll try to keep things simple. I started reading through this article:
I’ll stick to it and build up my own implementation with the help of what’s done there.
Let’s mix it up.
I’m asked to start up by running the auto-generated tests. So let’s do so.
Fair enough - two successful tests. I’m rather curious to see those. Running mix test with –trace option shows me who they are.
AwesomeCliTest
* test greets the world (0.00ms)
* test doc at AwesomeCli.hello/0 (1) (0.00ms)
So, there is one that greets the world and one that test doc. Looking at the test directory I found two files.
test/test_helper.exs
test/awesome_cli_test.exs
Nothing fancy about them. The actual app code is in lib.
lib/awesome_cli.ex
I want to call this “hello” function on my own so I’ll fire the Interactive Elixir and call mix inside. Then I’ll run the function just like it’s done in the test.
The great thing about iex is that I can recompile my code without getting out of it. Let’s add another simple function.
Now in order to run this function all I have to do is recompile AwesomeCli using the “r” command.
And there - I have the hello_again function I just wrote. Now let’s move on and add some actual cli functions.
Now it’s time to do some cleaning. I’ll remove the hello function and the auto-generated test. And soon enough here’s what I have:
lib/awesome_cli.ex
test/awesome_cli_test.exs
That looks like a good starting point. Now let’s add two more functions.
lib/awesome_cli.ex
A supervisor is a process which supervises other processes, which we refer to as child processes.
More on the use of this supervisor comes later but now we just define it. That’s something you can find in the documentation over here. Now let’s fire the REPL and check our main function.
Now our function takes an argument but it doesn’t do anything with it. Before we continue with cli functions let’s make an executable.
That failed but the nice thing about Elixir is that it keeps telling what we should do next. So let’s follow the advice and add :main_module to the configuration. We will add this piece of code to mix.exs in the root directory:
Here’s how mix.exs will look like afterwards:
mix.exs
Notice also the “escript: escript” that we added to the project definition. Now we can build.
Now let’s update lib/awesome_cli.ex with the following:
Rebuild with “mix escript.build” and you’ll get the first cli option available for use.
Now let’s introduce a quick fix. If you’re following along you probably noticed this warning:
warning: variable "escript" does not exist and is being expanded to "escript()", please use parentheses to remove the ambiguity or change the variable name
mix.exs:10
Let’s fix this real quick by adding () in mix.exs after escript just like we were adviced to do. I really love Elixir for helping me in such a way. Great, now that the warning is gone let’s keep updating our lib/awesome_cli.ex.
It’s all great but you might have noticed what’s happening when we run our cli app with no arguments.
Ouch… Let’s introduce some more updates.
lib/awesome_cli.ex
Alright. Now it works but the first time I saw this code I found it hard to read. If you’re like me by now you’re probably confused. Elixir is supposed to be very helpful so let’s ask the REPL what’s going on.
Looking at the main function we see the following:
args
> parse_args
> do_process
That’s standard piping just like in the Linux shell. So, we start with some arguments, then we parse them, then we do process.
Let’s test the parse_args first. We will use myargs although we know that it will not match it.
It replies with :help because there is no match. Let’s see if we put “–name” instead.
Nice, so it responds to “–name”. If we provide second argument we’ll see it returned.
Why? Let’s bring back the implementation.
And here’s the answer:
{[name: name], _, _} -> [name]
When –name gets matched the function returns the name. Let’s test the do_process function.