Search code examples
elixirelixir-mix

How to pass named arguments into a Mix Task?


I have this code:

defmodule Mix.Tasks.Echo do
  use Mix.Task

  @impl Mix.Task
  def run(args) do
    IO.puts("running!")
    Mix.shell().info(Enum.join(args, " "))
    IO.inspect(args, label: "Received args")
  end
end

Which can be used like this:


$ mix echo foo.bar 123
running!
foo.bar 123
Received args: ["foo.bar", "123"]

How to change the code so that I'd be able to pass and get access to, by name named arguments?

$ mix echo --arg1=123 --my_arg2="fdsafdsafds"

===>

Received args: %{"arg1" => 123, "my_arg2" => "fdsafdsafds"}

?


Solution

  • I think you are searching for the OptionParser module.

    defmodule Mix.Tasks.Echo do
      use Mix.Task
    
      @impl Mix.Task
      def run(args) do
        {parsed, _, _} = OptionParser.parse(args, strict: [my_arg1: :string, my_arg2: :boolean])
        IO.inspect(parsed, label: "Received args")
      end
    end
    

    This will give you a keyword list instead, which makes sense since it preserves order and allows for duplicate arguments. From there you can use Enum.into/1 if you really need a map. You can also see that it allows for types.