// = Elixir - 0x02 Command Line Fun - LBA Game :id: 7e0d4239-2382-427d-9497-0767657a5fe0 :author: Andrei Clinciu :website: https://andreiclinciu.net/ :publish_at: 2018-02-22 18:24:00Z :heading_image: /images/blog/old_uploads/elixir-command-line-fun-825x510.jpg :description: \N :type: article :tags: :keywords: :toc: left :imagesdir: ../assets/
image::{heading_image}[] link:/blog/learning-elixir-and-otp-through-a-project-life-beyond-apocalypse/[This is part of the Elixir Life Beyond Apocalypse Zombie Game creation tutorial.] + Refer to the introduction for more information.
We said we were going to make a commandline game. + So let’s implement it in a commandline fashion!
First edit mix.exs so we can use escript. Escript is just Erlang Script which will create a self contained script file with our full project.
…. def project do [ app: :life_beyond_apocalypse, version: “0.1.0”, elixir: “~> 1.5”, start_permanent: Mix.env == :prod, deps: deps(), escript: escript(), ] end#…. defp escript do [main_module: LifeBeyondApocalypse.CLI] end ….
Now we can create a cli.ex file in our library. + Note the ~S sigil with the heredoc means that we don’t want any interpolation/interpretation, or else you would get a weird looking tag
defmodule LifeBeyondApocalypse.CLI do
[source,lang:default,decode:true]
@tag ~S""" _ _ __ ____ | | ()/ | ___ | __ ) ___ _ _ ___ _ __ | || | | | | / _ \ | _ \ / _ \ | | |/ _ \| ‘ \ / || |___| | _| __/ | |_) | __/ |_| | (_) | | | | (_| ||_____|_|_| \\___| |____/ \\___|\\__, |\\___/|_| |_|\\__,_| |___/ _ _ / \\ _ __ ___ ___ __ _| |_ _ _ __ ___ ___ / _ \\ | '_ \\ / _ \\ / __/ _
| | | | | ‘ \/ __|/ _ \ / ___ \| |) | () | (| (| | | || | |) \__ \ __/// \\ ./ \/ \\,||\, | ./|/\| || |__/||"""
We can run it directly with mix + mix run -e ‘LifeBeyondApocalypse.CLI.main("")’
Or we could compile our script +
+mix escript.build+
+
+Compiling 5 files (.ex)+
+
+Generated life_beyond_apocalypse app+
+
+Generated escript life_beyond_apocalypse with MIX_ENV=dev+
This will generate a file life_beyond_apocalypse which we can run.
+./life_beyond_apocalypse+
….
| | ()/ | ___ | __ ) ___ _ _ ___ _ __ | || | | | | / _ \ | _ \ / _ \ | | |/ _ \| ‘ \ / || |___| | _| __/ | |_) | __/ |_| | (_) | | | | (_| ||_____|_|_| \\___| |____/ \\___|\\__, |\\___/|_| |_|\\__,_| |___/ _ _ / \\ _ __ ___ ___ __ _| |_ _ _ __ ___ ___ / _ \\ | '_ \\ / _ \\ / __/ _
| | | | | ‘ \/ __|/ _ \ / ___ \| |) | () | (| (| | | || | |) \__ \ /// \\ ./ \/ \\,||\, | ./|/\| || |_/||
….
You can copy the script to any machine that has Erlang installed and it will run.
== Adding a way to read commands
What we’ll do it create a module variable with a map of commands and their description.
We will develop a function to read the user input. And one to execute various commands based on the user input.
….
@commands %{“quit” => “Quits the game”,“help” => “?
Our read_command function removes the newline with String.trim, then puts everything in downcase and splits the command in an array and at last executes it. + This makes it possible for us to do pattern matching on the input.
Let’s try to add the user structure somewhere and work our way to use the show and move commands we created in the last lesson.
….
@commands %{“quit” => “Quits the game”,“help” => “?
Let’s test it and see how everything behaves together.
{empty}[caption id=“attachment_481” align=“alignnone” width=“956”]image:/images/blog/old_uploads/screenshot_2018-01-26-202527.png[elixir life beyond apocalypse commandline example game] elixir life beyond apocalypse commandline example game[/caption]
We see that the colours aren’t right yet and that we have some IO.puts commands still lying around from the debugging session. + Appart from that, everything seems to work just fine.
https://andreiclinciu.net/wp-content/uploads/2018/02/0x02-Elixir-commandline.tar.gz[Download the full sourcecode for 0x02 here.]
=== Conclusion
You can run any function as a starting point with mix run -e . + Whenever you need to create a simple script executable you can use escript.
There is one small problem, we always pass the user around. This makes our code ugly and complicated. + In the next tutorial we’ll address this problem and refactor the code.