defmodule Nexus.CLI do
@moduledoc """
Define callback that a CLI module needs to follow to be able
to be runned and also define helper functions to parse a single
command againts a raw input.
"""
alias Nexus.Parser
@callback version :: String.t()
@callback banner :: String.t()
@callback handle_input(cmd) :: :ok
when cmd: atom
@callback handle_input(cmd, args) :: :ok
when cmd: atom,
args: Nexus.Command.Input.t()
@optional_callbacks banner: 0, handle_input: 2, handle_input: 1
@type t :: map
@spec build(list(binary), module) :: {:ok, Nexus.CLI.t()} | {:error, atom}
def build(raw, module) do
cmds = module.__commands__()
acc = {%{}, raw}
{cli, _raw} =
Enum.reduce_while(cmds, acc, fn spec, {cli, raw} ->
try do
input = Parser.run!(raw, spec)
{:halt, {Map.put(cli, spec.name, input), raw}}
rescue
_ -> {:cont, {cli, raw}}
end
end)
{:ok, struct(module, cli)}
end
end