defmodule Hangman.Text.Client.Prompter do @moduledoc """ Prompts a player for a move. """ alias IO.ANSI.Plus, as: ANSI alias Hangman.Text.Client.{Player, State} @doc """ Accepts a player's move. """ @spec accept_move(State.t()) :: State.t() | no_return def accept_move(%State{} = state) do IO.gets("Your guess (or stop): ") |> check_input(state) end ## Private functions # "Player's input" @typep input :: String.t() | {:error, atom} | :eof @spec check_input(input, State.t()) :: State.t() | no_return defp check_input({:error, reason}, state) do Player.end_game(state, [:light_yellow, "Game ended: #{inspect(reason)}."]) end defp check_input(:eof, state) do Player.end_game(state, [:light_yellow, "Looks like you gave up somehow."]) end defp check_input(input, state) do case String.trim(input) do "stop" -> Player.end_game(state, [:light_yellow, "Looks like you gave up."]) <> = guess when byte in ?a..?z -> put_in(state.guess, guess) _bad_input -> ANSI.puts([:light_yellow, "Please enter a letter between a and z.\n"]) accept_move(state) end end end