Current section

Files

Jump to
ra lib ra.ex
Raw

lib/ra.ex

defmodule Ra do
@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 Dict.put(@options, unquote(name), { unquote(type), unquote(description) })
@opt_dict Dict.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 """
Reassembles all the stuff configured beforehand.
This macro needs to be used last in the module.
It is also responsible for creating the `run` function needed by Elixir.
## WARNING
This is only an interims solution and will be removed until version 0.4.0,
since there is currently no alternative implemented, there is also no
deprecation warning raised!
"""
defmacro parse do
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
|> Dict.keys
|> Enum.map(&(" --#{to_string &1} [#{Dict.get(@options, &1) |> elem(0) |> to_string}] - #{Dict.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