Não tive muita sorte em encontrar um exemplo completo de análise de linha de comando no Elixir, então pensei em compartilhar o que descobri até agora.
Este exemplo mostra o uso de um mapa para armazenar as opções como pares de chave e valor. Isso significa que pode haver apenas um valor para qualquer opção.
def main(args) do
args |> parse_args |> process
end
Esta função define o fluxo principal de controle no programa.
def parse_args(args) do
options = %{ :count => @max_ofiles ,
:type => @default_type
}
cmd_opts = OptionParser.parse(args,
switches: [help: :boolean , count: :integer],
aliases: [h: :help, c: :count])
case cmd_opts do
{ [ help: true], _, _} -> :help
{ [], args, [] } -> { options, args }
{ opts, args, [] } -> { Enum.into(opts,options), args }
{ opts, args, bad_opts} -> {
Enum.into(merge_opts(opts,bad_opts),
options),
args
}
_ -> :help
end
end
A principal função de análise do argumento da linha de comando. Ele configura um mapa de opções com valores padrão e, a seguir, mescla quaisquer valores da linha de comando. Também permite opções indefinidas, veja rehabilitate_args
abaixo.
def merge_opts(opts,bad_opts) do
bad_opts |> rehabilitate_args |> Keyword.merge(opts)
end
Uma função auxiliar simples para tornar a rotina de análise principal menos complicada.
def rehabilitate_args(bad_args) do
bad_args
|>
Enum.flat_map(fn(x) -> Tuple.to_list(x) end)
|>
Enum.filter_map(fn(str) -> str end,
fn(str) ->
String.replace(str, ~r/^-([^-]+)/, "--\1")
end )
|>
OptionParser.parse
|>
Tuple.to_list
|>
List.first
end
A função rehabilitate_args
é algo que incluí, já que meu aplicativo usará plug-ins e gostaria que os autores do plug-in pudessem simplesmente usar argumentos de linha de comando sem uma interface complicada. Isso pode ou não ser uma boa ideia e é principalmente incluído como um exemplo de como lidar com bad_args se você quiser. Se você usar em vez de OptionParser.parse, chamar opções indefinidas gerará automaticamente um erro.:strict
:switches
def process(:help) do
IO.puts @module_doc
System.halt(0)
end
def process({options,args}) do
AllTheRealWork.start
end
Este é um exemplo do uso de correspondência de padrões do elixir em definições de função para permitir que ele direcione o fluxo de controle no programa. O valor retornado da parse_args
chamada determinará qual versão da função do processo será executada.