defmodule Moar.Opts do # @related [test](/test/opts_test.exs) @moduledoc """ Extracts keys and values from enumerables, especially from function options. There are two main functions, each of which takes an opts enumerable as input. `get/2` and `get/3` each extract one value from the opts. `take/2` extracts multiple values from the opts. `get/3` and `take/2` allow the specification of default values. Example using `get/2` and `get/3`: ```elixir def build_url(path, opts \\\\ []) do %URI{ path: path, host: Moar.Opts.get(opts, :host, "localhost"), port: Moar.Opts.get(opts, :port), scheme: "https" } |> URI.to_string() end ``` Examples using `take/2`: ```elixir # example using pattern matching def build_url(path, opts \\ []) do %{host: h, port: p} = Moar.Opts.take(opts, [:port, host: "localhost"]) %URI{path: path, host: h, port: p, scheme: "https"} |> URI.to_string() end #example rebinding `opts` to the parsed opts def build_url(path, opts \\ []) do opts = Moar.Opts.take(opts, [:port, host: "localhost"]) %URI{path: path, host: opts.host, port: opts.port, scheme: "https"} |> URI.to_string() end ``` """ @doc """ Get the value of `key` from `input`, falling back to optional `default` if the key does not exist. ```elixir iex> [a: 1, b: 2] |> Moar.Opts.get(:a) 1 iex> [a: 1, b: 2] |> Moar.Opts.get(:c) nil iex> [a: 1, b: 2] |> Moar.Opts.get(:c, 300) 300 ``` """ @spec get(Enum.t(), binary() | atom(), any()) :: any() def get(input, key, default \\ nil), do: input |> Enum.into(%{}) |> Map.get(key) |> Moar.Term.presence(default) @doc """ Get each key in `keys` from `input`. `keys` is a list of keys, a keyword list of keys and default values, or a hybrid list/keyword list. ```elixir iex> [a: 1, b: 2] |> Moar.Opts.take([:a, :c]) %{a: 1, c: nil} iex> [a: 1, b: 2] |> Moar.Opts.take([:a, b: 0, c: 3]) %{a: 1, b: 2, c: 3} ``` """ @spec take(Enum.t(), list()) :: map() def take(input, keys) do input = Enum.into(input, %{}) Enum.reduce(keys, %{}, fn {key, default}, acc -> Map.put(acc, key, get(input, key, default)) key, acc -> Map.put(acc, key, get(input, key)) end) end end