Current section

Files

Jump to
artificery lib console prompt.ex
Raw

lib/console/prompt.ex

defmodule Artificery.Console.Prompt do
@moduledoc false
alias Artificery.Console
alias Artificery.Console.Color
@type validator :: (String.t -> :ok | {:error, String.t})
@type transform :: (String.t -> term)
@type ask_option :: {:default, term}
| {:validator, validator}
| {:transform, transform}
@type ask_options :: [ask_option]
@spec yes?(String.t) :: boolean
def yes?(question) when is_binary(question) do
prompt = Color.style("? ", [:green]) <> question <> " (Y/n) "
reply = IO.gets(prompt)
is_binary(reply) and String.trim(reply) in ["", "y", "Y", "yes", "Yes", "YES"]
end
@spec ask(String.t) :: term
@spec ask(String.t, ask_options) :: term
def ask(question, opts \\ []) do
validator = Keyword.get(opts, :validator)
transform = Keyword.get(opts, :transform)
default = Keyword.get(opts, :default)
# TODO: Provide mechanism for inputting secrets
# masked? = Keyword.get(opts, :masked, false)
# Ask question
prompt = Color.style("? ", [:green]) <> question <> ": " <> IO.ANSI.cyan
answer = IO.gets(prompt)
# Reset color
IO.write IO.ANSI.reset
# Validate answer
validation =
if is_function(validator, 1) do
validator.(answer)
else
:ok
end
case answer do
"" when validation == :ok ->
default
s when is_binary(s) and validation == :ok ->
if is_function(transform, 1) do
transform.(s)
else
s
end
_ ->
# Invalid
{:error, message} = validation
# Clear current line
Console.erase_line
# Write validation error
Console.write(">>> #{message}", [:red])
# Go back to question line and erase it
Console.cursor_prev_line
Console.erase_line
# Ask the question again
ask(question, opts)
end
end
# TODO: Open EDITOR to a temp file, read in result when closed
@doc false
@spec edit() :: String.t
def edit(), do: exit(:not_implemented)
# TODO: Choose from a selection of options
@doc false
@spec choose(String.t, [String.t]) :: String.t
def choose(question, choices) when is_binary(question) and is_list(choices) do
exit(:not_implemented)
end
end