mmag

ハマったことメモなど

ElixirのOptionParser

について述べます。

準備

まずは今回使うサンプルをば。この辺にはあんまり触れません。 mix new optsみたいなことして、

# lib/opts.ex

defmodule Opts do
  def main(args) do
    OptionParser.parse(args) |> IO.inspect
  end
end
# mix.exs

defmodule Opts.Mixfile do
  use Mix.Project

  def project do
    [app: :opts,
     version: "0.0.1",
     elixir: "~> 0.15.0",
     escript: [main_module: Opts]  # <- これ大切
     deps: deps]
  end

  # 以下略

end

これつくって、

$ mix escript.build

すると、optsという実行ファイルができる。こいつにオプションをパシパシ渡していきます。

パース

試しにテキトーな引数を与えてみましょ。

$ ./opts --abc def some.txt -b 1 --help
{[abc: "def", help: true], ["some.txt"], [{"-b", "1"}]}

OptionParser.parseの戻り値は、3つのリストを含むタプルです。こんな感じ。

{[解析できたやつら], [引数たち], [パースできなかった者ども]}

--abc def:abcをキーとして"def"を値に持つリストになり、最後に付けた--helphelp: trueとしてパースされています。このようなオプションは--abc=defと書いても同じ結果になります。 some.txtはちゃんと2つ目のリストに放り込まれていますね。

注目すべきは-b 1が解析できていないところ。これは困ります。コイツをパースするには、OptionParser.parseに第2引数aliases: [...]を与えます。

iex> OptionParser.parse(["-b", "1"], aliases: [b: :bytes])
{[bytes: "1"], [], []}

これで短縮形が使えるようになりました。しかしながら、1が文字列の"1"になっちゃってますね。 型を指定する場合はstrict: [...]を与えます。

iex> OptionParser.parse(["-b", "1"], aliases: [b: :bytes], strict: [bytes: :integer])
{[bytes: 1], [], []}

ここの:integerの部分は、:float, :string, :booleanも使えます。

最後に便利なswitchesを書くと、

iex> OptionParser.parse(["--no-ff"], switches: [ff: :boolean])
{[ff: false], [], []}
iex> OptionParser.parse(["--ff"], switches: [ff: :boolean])
{[ff: true], [], []}

という動きをします。

はい、淡々としてますね。朝だからですかね。