lib/key.ex

defmodule Key do
  @moduledoc """
  Documentation for `Key`.
  """

  defmacro keywords!({_, _, context} = opts, defaults) do
    first = quote do
      case Keyword.drop(unquote(opts), unquote(Keyword.keys(defaults))) do
        [] -> true
        [{wrong_opt, default}] -> raise "#{wrong_opt} is not a valid keyword argument"
        wrong_opts -> raise "#{inspect wrong_opts} are invalid keyword arguments"
      end
    end
    assignments = for {opt, default} <- defaults do
      opt_var = Macro.var(opt, context)
      quote do
        unquote(opt_var) = Keyword.get(unquote(opts), unquote(opt), unquote(default))
      end
    end
    [first | assignments]
  end
end