diff options
Diffstat (limited to 'src/rebar_prv_new.erl')
-rw-r--r-- | src/rebar_prv_new.erl | 98 |
1 files changed, 84 insertions, 14 deletions
diff --git a/src/rebar_prv_new.erl b/src/rebar_prv_new.erl index 698b14e..e432371 100644 --- a/src/rebar_prv_new.erl +++ b/src/rebar_prv_new.erl @@ -17,28 +17,34 @@ -spec init(rebar_state:t()) -> {ok, rebar_state:t()}. init(State) -> - State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER}, - {module, ?MODULE}, - {bare, false}, - {deps, ?DEPS}, - {example, "rebar new <template>"}, - {short_desc, "Create new project from templates."}, - {desc, info()}, - {opts, []}])), + Provider = providers:create([ + {name, ?PROVIDER}, + {module, ?MODULE}, + {bare, false}, + {deps, ?DEPS}, + {example, "rebar new <template>"}, + {short_desc, "Create new project from templates."}, + {desc, info()}, + {opts, [{force, $f, "force", undefined, "overwrite existing files"}]} + ]), + State1 = rebar_state:add_provider(State, Provider), {ok, State1}. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. do(State) -> case rebar_state:command_args(State) of - [TemplateName] -> - Template = list_to_atom(TemplateName), - rebar_templater:new(Template, "", State), + ["help", TemplateName] -> + case lists:keyfind(TemplateName, 1, rebar_templater:list_templates(State)) of + false -> io:format("template not found.~n"); + Term -> show_template(Term) + end, {ok, State}; - [TemplateName, DirName] -> - Template = list_to_atom(TemplateName), - rebar_templater:new(Template, DirName, State), + [TemplateName | Opts] -> + Force = is_forced(State), + ok = rebar_templater:new(TemplateName, parse_opts(Opts), Force, State), {ok, State}; [] -> + show_short_templates(rebar_templater:list_templates(State)), {ok, State} end. @@ -56,3 +62,67 @@ info() -> "~n" "Valid command line options:~n" " template= [var=foo,...]~n", []). + +is_forced(State) -> + {Args, _} = rebar_state:command_parsed_args(State), + case proplists:get_value(force, Args) of + undefined -> false; + _ -> true + end. + +parse_opts([]) -> []; +parse_opts([Opt|Opts]) -> [parse_first_opt(Opt, "") | parse_opts1(Opts)]. + +parse_opts1([]) -> []; +parse_opts1([Opt|Opts]) -> [parse_opt(Opt, "") | parse_opts1(Opts)]. + +%% If the first argument meets no '=', we got a default 'name' argument +parse_first_opt("", Acc) -> {name, lists:reverse(Acc)}; +parse_first_opt("="++Rest, Acc) -> parse_opt("="++Rest, Acc); +parse_first_opt([H|Str], Acc) -> parse_first_opt(Str, [H|Acc]). + +%% We convert to atoms dynamically. Horrible in general, but fine in a +%% build system's templating tool. +parse_opt("", Acc) -> {list_to_atom(lists:reverse(Acc)), "true"}; +parse_opt("="++Rest, Acc) -> {list_to_atom(lists:reverse(Acc)), Rest}; +parse_opt([H|Str], Acc) -> parse_opt(Str, [H|Acc]). + +show_short_templates(List) -> + lists:map(fun show_short_template/1, lists:sort(List)). + +show_short_template({Name, Type, _Location, Description, _Vars}) -> + io:format("~s (~s): ~s~n", + [Name, + format_type(Type), + format_description(Description)]). + +show_template({Name, Type, Location, Description, Vars}) -> + io:format("~s:~n" + "\t~s~n" + "\tDescription: ~s~n" + "\tVariables:~n~s~n", + [Name, + format_type(Type, Location), + format_description(Description), + format_vars(Vars)]). + +format_type(escript) -> "built-in"; +format_type(file) -> "custom". + +format_type(escript, _) -> + "built-in template"; +format_type(file, Loc) -> + io_lib:format("custom template (~s)", [Loc]). + +format_description(Description) -> + case Description of + undefined -> "<missing description>"; + _ -> Description + end. + +format_vars(Vars) -> [format_var(Var) || Var <- Vars]. + +format_var({Var, Default}) -> + io_lib:format("\t\t~p=~p~n",[Var, Default]); +format_var({Var, Default, Doc}) -> + io_lib:format("\t\t~p=~p (~s)~n", [Var, Default, Doc]). |