lib/client/handler/list.ex

defmodule ExCrawlzy.Client.Handlers.List do
  @moduledoc """
  Internal module to handle json fields, mainly helps to create modules with defined list selector match on compile

  add to the module the `use` and use the macro `list_selector/1` to specify the multiple selector and `list_size/1` to
  specify the amount of elements to take

  ```elixir
  defmodule Some.Module do
    use ExCrawlzy.Client.Handlers.List

    list_size(5)
    list_selector("div.element-1/3")
    ...
  ```

  and adds the functions `list_size/0` and `get_list_selector_selector/0` to the module

  ```elixir
  > Some.Module.list_size()
  5
  > Some.Module.get_list_selector_selector()
  "div.element-1/3"
  ```
  """

  defmacro __using__(_) do
    quote do
      import ExCrawlzy.Client.Handlers.List

      Module.register_attribute(__MODULE__, :list_size, accumulate: false)
      Module.register_attribute(__MODULE__, :list_selector, accumulate: false)
      @before_compile ExCrawlzy.Client.Handlers.List
    end
  end

  defmacro __before_compile__(env) do
    list_size = Module.get_attribute(env.module, :list_size)
    list_size = if is_nil(list_size), do: 20, else: list_size
    list_selector = Module.get_attribute(env.module, :list_selector)

    quote do
      def list_size(), do: unquote(list_size)
      def get_list_selector_selector(), do: unquote(list_selector)
    end
  end

  @doc """
  To specify the number of elements to take on the crawl
  """
  defmacro list_size(selector) do
    quote do
      @list_size unquote(selector)
    end
  end

  @doc """
  Add the a selector to multiple items
  """
  defmacro list_selector(selector) do
    quote do
      @list_selector unquote(selector)
    end
  end

end