defmodule Igniter.Config do require Igniter.Common alias Igniter.Common alias Sourceror.Zipper def configure(igniter, file_path, app_name, config_path, value, updater \\ nil) do file_path = Path.join("config", file_path) config_path = List.wrap(config_path) value = Macro.escape(value) updater = updater || fn zipper -> Zipper.replace(zipper, value) end igniter |> Igniter.include_or_create_elixir_file(file_path, "import Config\n") |> Igniter.update_file(file_path, fn source -> quoted = Rewrite.Source.get(source, :quoted) zipper = Zipper.zip(quoted) case try_update_three_arg(zipper, config_path, app_name, updater) do {:ok, zipper} -> Rewrite.Source.update(source, :configure, :quoted, Zipper.root(zipper)) :error -> case try_update_two_arg(zipper, config_path, app_name, value, updater) do {:ok, zipper} -> Rewrite.Source.update(source, :configure, :quoted, Zipper.root(zipper)) :error -> # add new code here config = if Enum.count(config_path) == 1 do quote do config unquote(app_name), unquote(Enum.at(config_path, 0)), unquote(value) end else {:config, [], [app_name, Igniter.Common.keywordify(config_path, value)]} end code = zipper |> Igniter.Common.add_code(config) |> Zipper.root() Rewrite.Source.update( source, :configure, :quoted, code ) end end end) end defp try_update_three_arg(zipper, config_path, app_name, updater) do if Enum.count(config_path) == 1 do config_item = Enum.at(config_path, 0) case Common.find_function_call_in_current_scope(zipper, :config, 3, fn function_call -> Common.argument_matches_pattern?(function_call, 0, ^app_name) Common.argument_matches_pattern?(function_call, 1, ^config_item) end) do nil -> :error zipper -> case Common.update_nth_argument(zipper, 2, updater) do nil -> :error zipper -> {:ok, zipper} end end else :error end end defp try_update_two_arg(zipper, config_path, app_name, value, updater) do case Common.find_function_call_in_current_scope(zipper, :config, 2, fn function_call -> Common.argument_matches_pattern?(function_call, 0, ^app_name) end) do nil -> :error zipper -> Common.update_nth_argument(zipper, 1, fn zipper -> Igniter.Common.put_in_keyword(zipper, config_path, value, updater) end) |> case do nil -> nil zipper -> {:ok, zipper} end end end end