(from: jelly-beam/rebar3_ex_doc#67)
This little Gist shows how to achieve simple AST walk + update to change a module attribute, that defines a version (in the example), in mix.exs
.
# up_version.exs
defmodule UpVersion do
@mix_exs "mix.exs"
@vsn_attr :dep_version
def up(new_vsn) do
content_up =
@mix_exs
|> File.read!()
|> up(new_vsn)
File.write!(@mix_exs, "#{content_up}\n")
end
defp up(mix_exs, new_vsn) do
mix_exs
|> Code.string_to_quoted!()
|> Macro.prewalk(fn
{:@, anno, [{@vsn_attr, anno, [_cur_vsn]}]} ->
{:@, anno, [{@vsn_attr, anno, [new_vsn]}]}
node ->
node
end)
|> Macro.to_string()
end
end
[new_vsn] = System.argv()
:ok = UpVersion.up(new_vsn)
Here's an example from that reference (comments added for readibility, since the above script will strip them out).
defmodule Rebar3ExDoc.MixProject do
use Mix.Project
@ex_doc_version "0.30.5" # Here's the module attribute (:dep_version would become :ex_doc_version, above)
def project do
[
app: :rebar3_ex_doc,
version: "0.2.20",
elixir: "~> 1.13",
deps: [ex_doc: "~> #{@ex_doc_version}"],
escript: [main_module: ExDoc.CLI, name: "ex_doc", path: "priv/ex_doc"],
docs: [main: "readme", extras: ["README.md"]]
]
end
end
After running elixir up_version.exs 0.30.6
the file's content would be updated to show @ex_doc_version "0.30.6"
, instead.