Создание консольных приложений на Elixir

Разработчики ПО, как правило, не представляют себе жизни без командной строки, а консольные приложения используются везде, где только можно. Python, Ruby, Erlang и Elixir дают разработчикам замечательные инструменты командной строки, называемые как раз консольными приложениями.

В этой статье рассказывается, как создавать свои консольные приложения, для чего Elixir подходит как нельзя лучше.

Создание приложения

Создадим новый проект с помощью mix.

$> mix new awesome_cli
$> cd awesome_cli

Откройте файл lib/awesome_cli.ex, где вы увидите нечто подобное:

defmodule AwesomeCli do
  use Application.Behaviour

  # See http://elixir-lang.org/docs/stable/elixir/Application.html
  # for more information on OTP Applications
  def start(_type, _args) do
    AwesomeCli.Supervisor.start_link
  end
end

Покажите, кто тут крутой программист: добавьте в проект вывод сообщения «Hello World».

defmodule AwesomeCli do
  use Application.Behaviour

  # See http://elixir-lang.org/docs/stable/elixir/Application.html
  # for more information on OTP Applications
  def start(_type, _args) do
    AwesomeCli.Supervisor.start_link
  end

  def main(args) do
    IO.puts "Hello, world!"
  end
end

После этого запустите mix escript.build для сборки проекта.

$> mix escript.build

Возможно, возникнет такая ошибка:

** (Mix) Could not generate escript, please set :escript in your project configuration
to a function that returns the escript configuration for our application.
So let's do that by openingmix.exs` file.

Попробуем пойти другим путём — откроем файл mix.exs.

defmodule AwesomeCli.Mixfile do
  use Mix.Project

  def project do
    [app: :awesome_cli,
    version: "0.0.1",
    elixir: "~> 1.0.4",
    escript: escript,
    deps: deps]
  end

  def escript do
    [main_module: AwesomeCli]
  end


  def application do
    [ applications: [],
      mod: { AwesomeCli, [] } ]
  end

  defp deps do
    []
  end
end

Перезапустим mix escript.build, после чего mix выполнит компиляцию файла awesome_cli.ex и создаст файл Elixir.AwesomeCli.beam и исполняемый файл awesome_cli в директории _build/dev/lib/awesome_cli/ebin. Откроем исполняемый файл.

$> ./awesome_cli
Hello, world!

Вот вы и создали своё первое работающее приложение на Elixir!

Парсинг аргументов

Нам повезло, что для парсинга аргументов интерфейса командной строки в Elixir имеется модуль OptionParser. Воспользуемся им, чтобы создать хитроумный инструмент командной строки, который бы получал один или два аргумента от пользователя.

Первым делом научим инструмент приветствовать пользователя с заданным именем. Вот что мы сделаем:

./awesome_cli --name ElixirFriend

Откройте файл lib/awesome_cli.ex и добавьте в него следующий код:

def main(args) do
  args |> parse_args
end

def parse_args(args) do
  {[name: name], _, _} = OptionParser.parse(args)

  IO.puts "Hello, #{name}! You're awesome!!"
end

Оператор |> используется для передачи аргумента в функцию parse_args, а парсинг аргументов проводится с помощью OptionParser.parse. Вывод осуществлён для одного из аргументов. Если сейчас снова запустить mix escript.build, то получится следующее:

$> mix escript.build
$> ./awesome_cli --name ElixirFriend
Hello, ElixirFriend! You're awesome!!

Здорово, правда? Теперь, чтобы сделать CLI ещё круче, добавим в него справочное сообщение. Так пользователь поймёт, как с ним обращаться. Для этого воспользуемся конструкцией case и проведём сопоставление с образцом.

def parse_args(args) do
  options = OptionParser.parse(args)

  case options do
    {[name: name], _, _} -> IO.puts "Hello, #{name}! You're awesome!!"
    {[help: true], _, _} -> IO.puts "This is help message"

  end
end

Перезапустим mix escript.build ещё раз и выполним файл с помощью --help.

$> ./awesome_cli --name ElixirFriend
Hello, ElixirFriend! You're awesome!!
$> ./awesome_cli --help
This is help message

Последний штрих

Давайте немного перестроим код. Сначала, сделаем так, чтобы функция parse_args выполняла только парсинг аргументов и возвращаемый ею результат можно было бы использовать в другой функции.

def main(args) do
  args |> parse_args |> do_process
end

def parse_args(args) do
  options = OptionParser.parse(args)

  case options do
    {[name: name], _, _} -> [name]
    {[help: true], _, _} -> :help
    _ -> :help

  end
end

def do_process([name]) do
  IO.puts "Hello, #{name}! You're awesome!!"
end

def do_process(:help) do
  IO.puts """
    Usage:
    ./awesome_cli --name [your name]

    Options:
    --help  Show this help message.

    Description:
    Prints out an awesome message.
  """

  System.halt(0)
end

Перезапустите mix escript.build и попробуйте его выполнить.

$> mix escript.build
$> ./awesome_cli --name ElixirFriend
Hello, ElixirFriend! You're awesome!!
$> ./awesome_cli --help
Usage:
./awesome_cli --name [your name]

Options:
--help  Show this help message.

Description:
Prints out an awesome message.
$> ./awesome_cli
Usage:
./awesome_cli --name [your name]

Options:
--help  Show this help message.

Description:
Prints out an awesome message.

Заключение

Мы рассмотрели, как создавать простые консольные приложения посредством OptionParser и как заставить код работать с помощью mix escript.build. И пусть приведённый пример не изобилует сложными конструкциями, но даже на нём видно, что создавать консольные приложения в Elixir — просто и очень удобно.

© 2020 / Россия Любые мысли и вопросы пишите на elixir@wunsh.ru.