Current section
Files
Jump to
Current section
Files
src/ec_talk.erl
%% -*- mode: Erlang; fill-column: 79; comment-column: 70; -*-%% vi:ts=4 sw=4 et%%%---------------------------------------------------------------------------%%% Permission is hereby granted, free of charge, to any person%%% obtaining a copy of this software and associated documentation%%% files (the "Software"), to deal in the Software without%%% restriction, including without limitation the rights to use, copy,%%% modify, merge, publish, distribute, sublicense, and/or sell copies%%% of the Software, and to permit persons to whom the Software is%%% furnished to do so, subject to the following conditions:%%%%%% The above copyright notice and this permission notice shall be%%% included in all copies or substantial portions of the Software.%%%%%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,%%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF%%% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND%%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT%%% HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,%%% WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,%%% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER%%% DEALINGS IN THE SOFTWARE.%%%---------------------------------------------------------------------------%%% @author Eric Merritt%%% @doc%%% Provides the ability to ask questions of the user and%%% get a response.%%% @end%%% @copyright Erlware 2006-2011%%%----------------------------------------------------------------------------module(ec_talk).%% API-export([ask/1, ask/2, ask_default/2, ask_default/3, ask/3, say/1, say/2]).-ifdef(TEST).-export([get_boolean/1, get_integer/1]).-endif.-export_type([prompt/0, type/0, supported/0]).%%============================================================================%% Types%%============================================================================-type prompt() :: string().-type type() :: boolean | number | string.-type supported() :: boolean() | number() | string().%%============================================================================%% API%%============================================================================%% @doc Outputs the line to the screen-spec say(string()) -> ok.say(Say) -> io:format(lists:flatten([Say, "~n"])).-spec say(string(), [term()] | term()) -> ok.say(Say, Args) when is_list(Args) -> io:format(lists:flatten([Say, "~n"]), Args);say(Say, Args) -> io:format(lists:flatten([Say, "~n"]), [Args]).%% @doc Asks the user for a response to the specified prompt.-spec ask(prompt()) -> string().ask(Prompt) -> ask_convert(Prompt, fun get_string/1, string, none).%% @doc Asks the user for a response to the specified prompt.-spec ask_default(prompt(), string()) -> string().ask_default(Prompt, Default) -> ask_convert(Prompt, fun get_string/1, string, Default).%% @doc Asks the user to respond to the prompt. Tries to return the%% value in the format specified by 'Type'.-spec ask(prompt(), type()) -> supported().ask(Prompt, boolean) -> ask_convert(Prompt, fun get_boolean/1, boolean, none);ask(Prompt, number) -> ask_convert(Prompt, fun get_integer/1, number, none);ask(Prompt, string) -> ask_convert(Prompt, fun get_string/1, string, none).%% @doc Asks the user to respond to the prompt. Tries to return the%% value in the format specified by 'Type'.-spec ask_default(prompt(), type(), supported()) -> supported().ask_default(Prompt, boolean, Default) -> ask_convert(Prompt, fun get_boolean/1, boolean, Default);ask_default(Prompt, number, Default) -> ask_convert(Prompt, fun get_integer/1, number, Default);ask_default(Prompt, string, Default) -> ask_convert(Prompt, fun get_string/1, string, Default).%% @doc Asks the user to respond to the number prompt with a value%% between min and max.-spec ask(prompt(), number(), number()) -> number().ask(Prompt, Min, Max) when erlang:is_list(Prompt), erlang:is_number(Min), erlang:is_number(Max), Min =< Max -> Res = ask_convert(Prompt, fun get_integer/1, number, none), case (Res >= Min andalso Res =< Max) of true -> Res; false -> say("Your answer must be between ~w and ~w!", [Min, Max]), ask(Prompt, Min, Max) end.%%============================================================================%% Internal functions%% ============================================================================%% @doc Actually does the work of asking, checking result and%% translating result into the requested format.-spec ask_convert(prompt(), fun((any()) -> any()), type(), supported() | none) -> supported().ask_convert(Prompt, TransFun, Type, Default) -> NewPrompt = erlang:binary_to_list(erlang:iolist_to_binary([Prompt, case Default of none -> []; Default -> [" (", io_lib:format("~p", [Default]) , ")"] end, "> "])), Data = string:trim(string:trim(io:get_line(NewPrompt)), both, [$\n]), Ret = TransFun(Data), case Ret of no_data -> case Default of none -> say("I didn't get that. This ~p kind of question.~n", [Type]), ask_convert(Prompt, TransFun, Type, Default); Default -> TransFun(Default) end; no_clue -> say("I didn't get that. This ~p kind of question.~n", [Type]), ask_convert(Prompt, TransFun, Type, Default); _ -> Ret end.%% @doc Tries to translate the result into a boolean-spec get_boolean(string()) -> boolean().get_boolean([]) -> no_data;get_boolean([$T | _]) -> true;get_boolean([$t | _]) -> true;get_boolean("ok") -> true;get_boolean("OK") -> true;get_boolean([$Y | _]) -> true;get_boolean([$y | _]) -> true;get_boolean([$f | _]) -> false;get_boolean([$F | _]) -> false;get_boolean([$n | _]) -> false;get_boolean([$N | _]) -> false;get_boolean(_) -> no_clue.%% @doc Tries to translate the result into an integer-spec get_integer(string()) -> integer().get_integer([]) -> no_data;get_integer(String) -> case (catch list_to_integer(String)) of {'Exit', _} -> no_clue; Integer -> Integer end.%% @doc Solely returns a string give the string. This is so the same%% translate function can be used across the board-spec get_string(string()) -> string().get_string([]) -> no_data;get_string(String) -> case is_list(String) of true -> String; false -> no_clue end.