Current section

Files

Jump to
ra lib ra.ex
Raw

lib/ra.ex

defmodule Ra do
require Logger
@doc """
Defines the banner to use when showing the help.
"""
defmacro banner(banner) do
quote do
@banner unquote(banner)
end
end
@doc """
Defines and describes a subcommand.
You have do provide at least the `name` of the command as a string and the
function `f` that shall be called when this command is given.
Also you can provide an optional `description` which will be displayed when
showing the help.
The function `f` needs to accept a single argument, beeing a three-tuple:
`{arguments, options, config}`.
"""
defmacro command(name, description \\ "", f) do
quote do
@commands @commands ++ [{ unquote(to_string name), unquote(description) }]
def _command([unquote(to_string name)|args], opts) do
rc = Ra.RcFile.load(__MODULE__)
{args, opts, rc} |> unquote(f)
end
end
end
@doc """
Defines and describes an option.
You have to provide at least the `name` of the option, also you can define
its `type` (`:string` is assumed as a default) and also you can optionally
provide an `description`, the description is shown when the help is printed.
Remember, when you want to have a `description`, you also need to provide the
`type`.
`type` may be one of the following atoms:
* `:string` if the options value is supposed to be a string (default)
* `:integer` if the options value is supposed to be an integer
* `:float` if the options value is supposed to be a float
* `:boolean` if the option is meant to be an on/off-switch. One can use
`--opt`/`--no-opt` syntax for them.
"""
defmacro option(name, type \\ :string, description \\ "") do
quote do
@options Map.put(@options, unquote(name), { unquote(type), unquote(description) })
@opt_dict Map.put(@opt_dict, unquote(name), unquote(type))
end
end
defmacro rc_file(dict) do
quote do
@commands @commands ++ [{ "initrc", "Initialize the runtime configuration file." }]
def init_rc, do: _init_rc(unquote(dict), Ra.RcFile.exist?(__MODULE__))
def _init_rc(_, true), do: nil
def _init_rc(d, _), do: Ra.RcFile.touch(d, __MODULE__)
def _command(["initrc"|_], _), do: init_rc()
end
end
@doc """
**This macro is deprecated**: Reassembles all the stuff configured beforehand.
This macro needs to be used last in the module, as of version 0.3.3 its
functionality is applied automatically by using a before_compile hook. **As of
version 0.4.0 this macro will be removed!**
It is also responsible for creating the `run` function needed by Elixir.
"""
defmacro parse do
IO.warn("Explicit usage of Ra.parse/0 is deprecated. The macro will be removed in 0.4.0.", Macro.Env.stacktrace(__CALLER__))
quote do
@commands @commands ++ [{ "help", "View this help information." }]
def _command(["help"|_], _), do: help()
def _command(_, _) do
IO.puts "Command unknown."
help()
end
def help do
IO.puts "#{@banner}\n"
IO.puts "OPTIONS:\n"
@options
|> Map.keys
|> Enum.map(&(" --#{to_string &1} [#{Map.get(@options, &1) |> elem(0) |> to_string}] - #{Map.get(@options, &1) |> elem(1) |> to_string}"))
|> Enum.join("\n")
|> IO.puts
IO.puts "\nCOMMANDS:\n"
@commands
|> Enum.map(&(" #{elem(&1, 0)} - #{elem(&1, 1)}"))
|> Enum.join("\n")
|> IO.puts
end
def run(args) do
opts = OptionParser.parse(args, strict: @opt_dict)
_command(elem(opts, 1), elem(opts, 0))
end
end
end
defmacro __using__(_opts) do
quote do
import unquote(__MODULE__)
@banner ""
@commands []
@options %{}
@opt_dict %{}
end
end
end