Current section

Files

Jump to
igniter lib igniter util io.ex
Raw

lib/igniter/util/io.ex

defmodule Igniter.Util.IO do
@moduledoc "Helpers for working with input/output"
@doc "Prompts the user for yes or no, repeating the prompt until a satisfactory answer is given"
def yes?(prompt) do
case String.trim(Mix.shell().prompt(prompt <> " [Y/n]")) do
# default answer Y
"" ->
true
yes when yes in ["y", "Y", "yes", "YES"] ->
true
no when no in ["n", "N", "no", "NO"] ->
false
value ->
Mix.shell().info("Please enter one of [y/n]. Got: #{value}")
yes?(prompt)
end
end
@doc """
Prompts the user to select from a list, repeating until an item is selected
## Options
- `display`: A function that takes an item and returns a string to display
"""
def select(prompt, items, opts \\ [])
def select(_prompt, [], _opts), do: nil
def select(_prompt, [item], _opts), do: item
def select(prompt, items, opts) do
display = Keyword.get(opts, :display, &to_string/1)
item_numbers =
items
|> Enum.with_index()
|> Enum.map_join("\n", fn {item, index} ->
"#{index}. #{display.(item)}"
end)
case String.trim(Mix.shell().prompt(prompt <> "\n" <> item_numbers <> "\nInput number ❯ ")) do
"" ->
select(prompt, items, opts)
item ->
case Integer.parse(item) do
{int, ""} ->
case Enum.at(items, int) do
nil ->
Mix.shell().info("Expected one of the provided numbers, got: #{item}")
select(prompt, items, opts)
value ->
value
end
_ ->
Mix.shell().info("Expected a number, got: #{item}")
select(prompt, items, opts)
end
end
end
end