商店值如何在宏中传递?

时间:2017-02-15 12:37:26

标签: elixir metaprogramming

我有一个定义宏的下一个模块:

defmodule BServer.Command do

  defmacro __using__(_)do
    quote do
      @before_compile unquote(__MODULE__)
      import BServer.Command, only: [command: 1, command: 2,
                                     command_description: 1]
      Agent.start(fn -> %{} end, name: unquote(__MODULE__))
    end
  end

  defmacro command(command_name, args \\[]) do
    quote do
      name = unquote(Atom.to_string(command_name))
      @command_name Keyword.get(unquote(args), :name, name)
      Agent.update(unquote(__MODULE__), &(Map.put(&1, unquote(command_name), __MODULE__)))
    end
  end

  defmacro __before_compile__(_env) do
    quote do
      def desc(), do: @command_desc
    end
  end

  def all do
      Agent.get(__MODULE__, &(&1))
  end


  def get(name) when is_atom(name) do
    Agent.get(__MODULE__, &(&1[name]), 100)
  end

  def get(name) when is_binary(name) do
    {command, _args} = parse(name)
    String.to_atom(command)
      |> get
  end

  def parse(message) do
    case Regex.run(~r/\w+\b/, message) do
      nil -> 
        {"", []}
      [command | args ] ->
        {command, args }
      [command] ->
        {command, []}   
    end
  end

  defmacro command_description(description) do
    quote do
      @command_desc unquote(description)
    end
  end
end

下一个模块中使用的BServer.Command:

defmodule BServer.Command.Help do
  use BServer.Command

  command :help
  command_description """
    List of available commands
  """

  def process(user) do
    commands = 
      BServer.Command.all
        |> Enum.map(fn ({command, module}) -> 
          "#{command} - #{module.desc}"
        end)
        |> Enum.join("\n")
  end
end

在其他地方,我动态定义用于进程接收命令的模块:

    case BServer.Command.get(message) do
        nil -> false
        command ->
            BServr.User.get(user_attributes)
                |> command.process
    end

面对代理在编译时启动但在重新启动应用程序时无法启动的问题。 如何存储地图"命令" => "负责处理的模块"在宏指定命令名称的条件下?或者可以提示另一种方式动态选择模块来处理命令。我想将所有命令保存在单独的模块中,以便更好地维护和添加新的简单方法。

0 个答案:

没有答案