![CI](https://github.com/rzcastilho/do_it/workflows/CI/badge.svg)
![Coverage Status](https://coveralls.io/repos/github/rzcastilho/do_it/badge.svg)
# Do It
Elixir Command Line Interface Framework.
A framework that helps to develop command line tools with Elixir.
## Installation
The package can be installed by adding `do_it` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:do_it, "~> 0.4.0"}
]
end
```
## Usage
**_Do It_** have two main components:
* `DoIt.Command` - represents a single command.
* `DoIt.MainCommand` - find all defined commands in project and generate all functions to match all commands in a single module, must be used as `main_module` in `escript` definition.
The commands `version` and `help` are automatic generated for the client.
The version number is obtained from `mix.exs` or option `version` in `MainCommand`.
So, if you have a client named `cli`, you can type `cli version` and `cli help` to get the version number and the list of commands respectively from the client.
### Command
We can define a new command as follows:
```elixir
defmodule Hello do
use DoIt.Command,
description: "Useless hello command"
argument(:message, :string, "Say hello to...")
option(:template, :string, "Hello message template", alias: :t, default: "Hello <%= @message %>!!!")
def run(%{message: message}, %{template: template}, _) do
IO.puts EEx.eval_string(template, assigns: [message: message])
end
end
```
A `help` option is automatically added to the command to describe its usage.
```shell
$ ./cli hello --help
Usage: cli hello [OPTIONS] <message>
Useless hello command
Arguments:
message Hello nice message
Options:
--help Print this help
-t, --template Hello message template (Default: "Hello <%= @message %>!!!")
```
Use `DoIt.Command` and provide a required `description`, the command name is the module name, you can override that name using the `name` option.
```elixir
defmodule Hello do
use DoIt.Command,
name: "olleh",
description: "Useless hello command"
...
end
```
### MainCommand
It's the entrypoint of your CLI, it generates functions matching all defined commands in the project, delegating the call to the matched command.
A `MainCommand` could be defined as follows:
```elixir
defmodule Cli do
use DoIt.MainCommand,
description: "My useless CLI"
end
```
## Package
There are two ways to generate the binaries.
- [escript](https://hexdocs.pm/mix/Mix.Tasks.Escript.Build.html)
- [burrito-elixir](https://github.com/burrito-elixir/burrito)
### escript
To generate an application using the escript, you have to add a `:escript` key with the `:main_module` option to your project properties in your `mix.exs` file.
The `:main_module` is the module that you defined as `DoIt.MainCommand`.
```elixir
...
def project do
[
app: :hello_world,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps(),
escript: [main_module: Cli]
]
end
...
```
Build the binary running the mix task bellow.
```shell
$ mix escript.build
==> do_it
Compiling 4 files (.ex)
Generated do_it app
==> hello_world
Compiling 1 file (.ex)
Generated escript hello_world with MIX_ENV=dev
```
A binary with the application name will be generated in the project root.
```shell
$ ./hello_world help ─╯
Usage: hello_world COMMAND
My useless CLI
Commands:
say Useless hello command
```
### burrito-elixir
> #### Experimental {: .warning}
>
> See the elixir-burrito [readme](https://github.com/burrito-elixir/burrito) about some limitations and other configurations.
To configure the application to use the `burrito-elixir` you have to add the `burrito-elixir` dependency in your project, add the `:mod` property in the `application` function, and the `:releases` key with the releases configuration to your project properties in you `mix.exs` file.
The `:mod` property value is the module that you defined as `DoIt.MainCommand`.
```elixir
defmodule CoinGeckoCli.MixProject do
use Mix.Project
def project do
[
app: :coin_gecko_cli,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps(),
releases: releases()
]
end
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger],
mod: {CoinGeckoCli, []}
]
end
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:tesla, "~> 1.7"},
{:jason, "~> 1.4"},
{:do_it, "~> 0.4"},
{:burrito, github: "burrito-elixir/burrito"},
{:tableize, "~> 0.1.0"}
]
end
def releases do
[
coin_gecko_cli: [
steps: [:assemble, &Burrito.wrap/1],
burrito: [
targets: [
macos: [os: :darwin, cpu: :x86_64],
linux: [os: :linux, cpu: :x86_64],
windows: [os: :windows, cpu: :x86_64]
],
]
]
]
end
end
```
Generate the binaries using the mix task bellow, a binary of each target will be generated in the `burrito_out` folder of your root application.
```shell
$ MIX_ENV=prod mix release
...
...
...
$ cd burrito_out
$ ls -c1 ─╯
coin_gecko_cli_linux
coin_gecko_cli_macos
coin_gecko_cli_windows
$ ./coin_gecko_cli_linux help ─╯
Usage: coin_gecko_cli COMMAND
CoinGecko CLI
Commands:
list List assets
```
## License
DoIt is released under the Apache License 2.0 - see the [LICENSE](LICENSE) file.