@ -1,2 +1,2 @@ | |||||
{description, "Makefile for building C/C++ in c_src"}. | {description, "Makefile for building C/C++ in c_src"}. | ||||
{template, "Makefile.dtl", "c_src/Makefile"}. | |||||
{template, "Makefile", "c_src/Makefile"}. |
@ -0,0 +1,230 @@ | |||||
%% The MIT License | |||||
%% | |||||
%% Copyright (c) 2009 Tom Preston-Werner <tom@mojombo.com> | |||||
%% | |||||
%% 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. | |||||
%% See the README at http://github.com/mojombo/mustache.erl for additional | |||||
%% documentation and usage examples. | |||||
-module(rebar_mustache). %% v0.1.0 | |||||
-author("Tom Preston-Werner"). | |||||
-export([compile/1, compile/2, render/1, render/2, render/3, get/2, get/3, escape/1, start/1]). | |||||
-record(mstate, {mod = undefined, | |||||
section_re = undefined, | |||||
tag_re = undefined}). | |||||
-define(MUSTACHE_STR, "rebar_mustache"). | |||||
compile(Body) when is_list(Body) -> | |||||
State = #mstate{}, | |||||
CompiledTemplate = pre_compile(Body, State), | |||||
% io:format("~p~n~n", [CompiledTemplate]), | |||||
% io:format(CompiledTemplate ++ "~n", []), | |||||
{ok, Tokens, _} = erl_scan:string(CompiledTemplate), | |||||
{ok, [Form]} = erl_parse:parse_exprs(Tokens), | |||||
Bindings = erl_eval:new_bindings(), | |||||
{value, Fun, _} = erl_eval:expr(Form, Bindings), | |||||
Fun; | |||||
compile(Mod) -> | |||||
TemplatePath = template_path(Mod), | |||||
compile(Mod, TemplatePath). | |||||
compile(Mod, File) -> | |||||
code:purge(Mod), | |||||
{module, _} = code:load_file(Mod), | |||||
{ok, TemplateBin} = file:read_file(File), | |||||
Template = re:replace(TemplateBin, "\"", "\\\\\"", [global, {return,list}]), | |||||
State = #mstate{mod = Mod}, | |||||
CompiledTemplate = pre_compile(Template, State), | |||||
% io:format("~p~n~n", [CompiledTemplate]), | |||||
% io:format(CompiledTemplate ++ "~n", []), | |||||
{ok, Tokens, _} = erl_scan:string(CompiledTemplate), | |||||
{ok, [Form]} = erl_parse:parse_exprs(Tokens), | |||||
Bindings = erl_eval:new_bindings(), | |||||
{value, Fun, _} = erl_eval:expr(Form, Bindings), | |||||
Fun. | |||||
render(Mod) -> | |||||
TemplatePath = template_path(Mod), | |||||
render(Mod, TemplatePath). | |||||
render(Body, Ctx) when is_list(Body) -> | |||||
TFun = compile(Body), | |||||
render(undefined, TFun, Ctx); | |||||
render(Mod, File) when is_list(File) -> | |||||
render(Mod, File, dict:new()); | |||||
render(Mod, CompiledTemplate) -> | |||||
render(Mod, CompiledTemplate, dict:new()). | |||||
render(Mod, File, Ctx) when is_list(File) -> | |||||
CompiledTemplate = compile(Mod, File), | |||||
render(Mod, CompiledTemplate, Ctx); | |||||
render(Mod, CompiledTemplate, Ctx) -> | |||||
Ctx2 = dict:store('__mod__', Mod, Ctx), | |||||
lists:flatten(CompiledTemplate(Ctx2)). | |||||
pre_compile(T, State) -> | |||||
SectionRE = "\{\{\#([^\}]*)}}\s*(.+?){{\/\\1\}\}\s*", | |||||
{ok, CompiledSectionRE} = re:compile(SectionRE, [dotall]), | |||||
TagRE = "\{\{(#|=|!|<|>|\{)?(.+?)\\1?\}\}+", | |||||
{ok, CompiledTagRE} = re:compile(TagRE, [dotall]), | |||||
State2 = State#mstate{section_re = CompiledSectionRE, tag_re = CompiledTagRE}, | |||||
"fun(Ctx) -> " ++ | |||||
"CFun = fun(A, B) -> A end, " ++ | |||||
compiler(T, State2) ++ " end.". | |||||
compiler(T, State) -> | |||||
Res = re:run(T, State#mstate.section_re), | |||||
case Res of | |||||
{match, [{M0, M1}, {N0, N1}, {C0, C1}]} -> | |||||
Front = string:substr(T, 1, M0), | |||||
Back = string:substr(T, M0 + M1 + 1), | |||||
Name = string:substr(T, N0 + 1, N1), | |||||
Content = string:substr(T, C0 + 1, C1), | |||||
"[" ++ compile_tags(Front, State) ++ | |||||
" | [" ++ compile_section(Name, Content, State) ++ | |||||
" | [" ++ compiler(Back, State) ++ "]]]"; | |||||
nomatch -> | |||||
compile_tags(T, State) | |||||
end. | |||||
compile_section(Name, Content, State) -> | |||||
Mod = State#mstate.mod, | |||||
Result = compiler(Content, State), | |||||
"fun() -> " ++ | |||||
"case " ++ ?MUSTACHE_STR ++ ":get(" ++ Name ++ ", Ctx, " ++ atom_to_list(Mod) ++ ") of " ++ | |||||
"\"true\" -> " ++ | |||||
Result ++ "; " ++ | |||||
"\"false\" -> " ++ | |||||
"[]; " ++ | |||||
"List when is_list(List) -> " ++ | |||||
"[fun(Ctx) -> " ++ Result ++ " end(dict:merge(CFun, SubCtx, Ctx)) || SubCtx <- List]; " ++ | |||||
"Else -> " ++ | |||||
"throw({template, io_lib:format(\"Bad context for ~p: ~p\", [" ++ Name ++ ", Else])}) " ++ | |||||
"end " ++ | |||||
"end()". | |||||
compile_tags(T, State) -> | |||||
Res = re:run(T, State#mstate.tag_re), | |||||
case Res of | |||||
{match, [{M0, M1}, K, {C0, C1}]} -> | |||||
Front = string:substr(T, 1, M0), | |||||
Back = string:substr(T, M0 + M1 + 1), | |||||
Content = string:substr(T, C0 + 1, C1), | |||||
Kind = tag_kind(T, K), | |||||
Result = compile_tag(Kind, Content, State), | |||||
"[\"" ++ Front ++ | |||||
"\" | [" ++ Result ++ | |||||
" | " ++ compile_tags(Back, State) ++ "]]"; | |||||
nomatch -> | |||||
"[\"" ++ T ++ "\"]" | |||||
end. | |||||
tag_kind(_T, {-1, 0}) -> | |||||
none; | |||||
tag_kind(T, {K0, K1}) -> | |||||
string:substr(T, K0 + 1, K1). | |||||
compile_tag(none, Content, State) -> | |||||
Mod = State#mstate.mod, | |||||
?MUSTACHE_STR ++ ":escape(" ++ ?MUSTACHE_STR ++ ":get(" ++ Content ++ ", Ctx, " ++ atom_to_list(Mod) ++ "))"; | |||||
compile_tag("{", Content, State) -> | |||||
Mod = State#mstate.mod, | |||||
?MUSTACHE_STR ++ ":get(" ++ Content ++ ", Ctx, " ++ atom_to_list(Mod) ++ ")"; | |||||
compile_tag("!", _Content, _State) -> | |||||
"[]". | |||||
template_dir(Mod) -> | |||||
DefaultDirPath = filename:dirname(code:which(Mod)), | |||||
case application:get_env(mustache, templates_dir) of | |||||
{ok, DirPath} when is_list(DirPath) -> | |||||
case filelib:ensure_dir(DirPath) of | |||||
ok -> DirPath; | |||||
_ -> DefaultDirPath | |||||
end; | |||||
_ -> | |||||
DefaultDirPath | |||||
end. | |||||
template_path(Mod) -> | |||||
DirPath = template_dir(Mod), | |||||
Basename = atom_to_list(Mod), | |||||
filename:join(DirPath, Basename ++ ".mustache"). | |||||
get(Key, Ctx) when is_list(Key) -> | |||||
{ok, Mod} = dict:find('__mod__', Ctx), | |||||
get(list_to_atom(Key), Ctx, Mod); | |||||
get(Key, Ctx) -> | |||||
{ok, Mod} = dict:find('__mod__', Ctx), | |||||
get(Key, Ctx, Mod). | |||||
get(Key, Ctx, Mod) when is_list(Key) -> | |||||
get(list_to_atom(Key), Ctx, Mod); | |||||
get(Key, Ctx, Mod) -> | |||||
case dict:find(Key, Ctx) of | |||||
{ok, Val} -> | |||||
% io:format("From Ctx {~p, ~p}~n", [Key, Val]), | |||||
to_s(Val); | |||||
error -> | |||||
case erlang:function_exported(Mod, Key, 1) of | |||||
true -> | |||||
Val = to_s(Mod:Key(Ctx)), | |||||
% io:format("From Mod/1 {~p, ~p}~n", [Key, Val]), | |||||
Val; | |||||
false -> | |||||
case erlang:function_exported(Mod, Key, 0) of | |||||
true -> | |||||
Val = to_s(Mod:Key()), | |||||
% io:format("From Mod/0 {~p, ~p}~n", [Key, Val]), | |||||
Val; | |||||
false -> | |||||
[] | |||||
end | |||||
end | |||||
end. | |||||
to_s(Val) when is_integer(Val) -> | |||||
integer_to_list(Val); | |||||
to_s(Val) when is_float(Val) -> | |||||
io_lib:format("~.2f", [Val]); | |||||
to_s(Val) when is_atom(Val) -> | |||||
atom_to_list(Val); | |||||
to_s(Val) -> | |||||
Val. | |||||
escape(HTML) -> | |||||
escape(HTML, []). | |||||
escape([], Acc) -> | |||||
lists:reverse(Acc); | |||||
escape(["<" | Rest], Acc) -> | |||||
escape(Rest, lists:reverse("<", Acc)); | |||||
escape([">" | Rest], Acc) -> | |||||
escape(Rest, lists:reverse(">", Acc)); | |||||
escape(["&" | Rest], Acc) -> | |||||
escape(Rest, lists:reverse("&", Acc)); | |||||
escape([X | Rest], Acc) -> | |||||
escape(Rest, [X | Acc]). | |||||
%%--------------------------------------------------------------------------- | |||||
start([T]) -> | |||||
Out = render(list_to_atom(T)), | |||||
io:format(Out ++ "~n", []). |
@ -1,270 +0,0 @@ | |||||
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- | |||||
%% ex: ts=4 sw=4 et | |||||
%% ------------------------------------------------------------------- | |||||
%% | |||||
%% rebar: Erlang Build Tools | |||||
%% | |||||
%% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com), | |||||
%% Bryan Fink (bryan@basho.com) | |||||
%% | |||||
%% 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. | |||||
%% ------------------------------------------------------------------- | |||||
%% The rebar_erlydtl_compiler module is a plugin for rebar that compiles | |||||
%% ErlyDTL templates. By default, it compiles all templates/*.dtl | |||||
%% to ebin/*_dtl.beam. | |||||
%% | |||||
%% Configuration options should be placed in rebar.config under | |||||
%% 'erlydtl_opts'. It can be a list of name-value tuples or a list of | |||||
%% lists of name-value tuples if you have multiple template directories | |||||
%% that need to have different settings (see example below). | |||||
%% | |||||
%% Available options include: | |||||
%% | |||||
%% doc_root: where to find templates to compile | |||||
%% "templates" by default | |||||
%% | |||||
%% out_dir: where to put compiled template beam files | |||||
%% "ebin" by default | |||||
%% | |||||
%% source_ext: the file extension the template sources have | |||||
%% ".dtl" by default | |||||
%% | |||||
%% module_ext: characters to append to the template's module name | |||||
%% "_dtl" by default | |||||
%% | |||||
%% recursive: boolean that determines if doc_root(s) need to be | |||||
%% scanned recursively for matching template file names | |||||
%% (default: true). | |||||
%% For example, if you had: | |||||
%% /t_src/ | |||||
%% base.html | |||||
%% foo.html | |||||
%% | |||||
%% And you wanted them compiled to: | |||||
%% /priv/ | |||||
%% base.beam | |||||
%% foo.beam | |||||
%% | |||||
%% You would add to your rebar.config: | |||||
%% {erlydtl_opts, [ | |||||
%% {doc_root, "t_src"}, | |||||
%% {out_dir, "priv"}, | |||||
%% {source_ext, ".html"}, | |||||
%% {module_ext, ""} | |||||
%% ]}. | |||||
%% | |||||
%% The default settings are the equivalent of: | |||||
%% {erlydtl_opts, [ | |||||
%% {doc_root, "templates"}, | |||||
%% {out_dir, "ebin"}, | |||||
%% {source_ext, ".dtl"}, | |||||
%% {module_ext, "_dtl"} | |||||
%% ]}. | |||||
%% | |||||
%% The following example will compile the following templates: | |||||
%% "src/*.dtl" files into "ebin/*_dtl.beam" and | |||||
%% "templates/*.html" into "ebin/*.beam". Note that any tuple option | |||||
%% (such as 'out_dir') in the outer list is added to each inner list: | |||||
%% {erlydtl_opts, [ | |||||
%% {out_dir, "ebin"}, | |||||
%% {recursive, false}, | |||||
%% [ | |||||
%% {doc_root, "src"}, {module_ext, "_dtl"} | |||||
%% ], | |||||
%% [ | |||||
%% {doc_root, "templates"}, {module_ext, ""}, {source_ext, ".html"} | |||||
%% ] | |||||
%% ]}. | |||||
-module(rebar_prv_erlydtl_compiler). | |||||
-behaviour(provider). | |||||
-export([init/1, | |||||
do/1, | |||||
format_error/1]). | |||||
-include("rebar.hrl"). | |||||
-include_lib("providers/include/providers.hrl"). | |||||
-define(PROVIDER, compile). | |||||
-define(DEPS, [{default, compile}]). | |||||
%% =================================================================== | |||||
%% Public API | |||||
%% =================================================================== | |||||
-spec init(rebar_state:t()) -> {ok, rebar_state:t()}. | |||||
init(State) -> | |||||
State1 = rebar_state:add_provider(State, providers:create([{name, ?PROVIDER}, | |||||
{module, ?MODULE}, | |||||
{namespace, erlydtl}, | |||||
{bare, false}, | |||||
{deps, ?DEPS}, | |||||
{example, "rebar3 erlydtl compile"}, | |||||
{short_desc, "Compile erlydtl templates."}, | |||||
{desc, "Compile erlydtl templates."}, | |||||
{opts, []}])), | |||||
{ok, State1}. | |||||
do(State) -> | |||||
?INFO("Running erlydtl...", []), | |||||
case rebar_state:get(State, escript_main_app, undefined) of | |||||
undefined -> | |||||
Dir = rebar_state:dir(State), | |||||
case rebar_app_discover:find_app(Dir, all) of | |||||
{true, AppInfo} -> | |||||
AllApps = rebar_state:project_apps(State) ++ rebar_state:all_deps(State), | |||||
case rebar_app_utils:find(rebar_app_info:name(AppInfo), AllApps) of | |||||
{ok, AppInfo1} -> | |||||
%% Use the existing app info instead of newly created one | |||||
run_erlydtl(AppInfo1, State); | |||||
_ -> | |||||
run_erlydtl(AppInfo, State) | |||||
end, | |||||
{ok, State}; | |||||
_ -> | |||||
?PRV_ERROR(no_main_app) | |||||
end; | |||||
Name -> | |||||
AllApps = rebar_state:project_apps(State) ++ rebar_state:all_deps(State), | |||||
{ok, App} = rebar_app_utils:find(Name, AllApps), | |||||
run_erlydtl(App, State), | |||||
{ok, State} | |||||
end. | |||||
run_erlydtl(App, State) -> | |||||
Dir = rebar_state:dir(State), | |||||
DtlOpts = proplists:unfold(rebar_state:get(State, erlydtl_opts, [])), | |||||
TemplateDir = filename:join(Dir, option(doc_root, DtlOpts)), | |||||
DtlOpts2 = [{doc_root, TemplateDir} | proplists:delete(doc_root, DtlOpts)], | |||||
OutDir = rebar_app_info:ebin_dir(App), | |||||
filelib:ensure_dir(filename:join(OutDir, "dummy.beam")), | |||||
rebar_base_compiler:run(State, | |||||
[], | |||||
TemplateDir, | |||||
option(source_ext, DtlOpts2), | |||||
OutDir, | |||||
option(module_ext, DtlOpts2) ++ ".beam", | |||||
fun(S, T, C) -> | |||||
compile_dtl(C, S, T, DtlOpts2, Dir, OutDir) | |||||
end, | |||||
[{check_last_mod, false}, | |||||
{recursive, option(recursive, DtlOpts2)}]). | |||||
-spec format_error(any()) -> iolist(). | |||||
format_error(no_main_app) -> | |||||
"Erlydtl Error: Multiple project apps found and no {app, atom()} option found in erlydtl_opts."; | |||||
format_error(Reason) -> | |||||
io_lib:format("~p", [Reason]). | |||||
%% =================================================================== | |||||
%% Internal functions | |||||
%% =================================================================== | |||||
option(Opt, DtlOpts) -> | |||||
proplists:get_value(Opt, DtlOpts, default(Opt)). | |||||
default(app) -> undefined; | |||||
default(doc_root) -> "priv/templates"; | |||||
default(source_ext) -> ".dtl"; | |||||
default(module_ext) -> "_dtl"; | |||||
default(custom_tags_dir) -> ""; | |||||
default(compiler_options) -> [return]; | |||||
default(recursive) -> true. | |||||
compile_dtl(State, Source, Target, DtlOpts, Dir, OutDir) -> | |||||
case needs_compile(Source, Target, DtlOpts) of | |||||
true -> | |||||
do_compile(State, Source, Target, DtlOpts, Dir, OutDir); | |||||
false -> | |||||
skipped | |||||
end. | |||||
do_compile(State, Source, Target, DtlOpts, Dir, OutDir) -> | |||||
CompilerOptions = option(compiler_options, DtlOpts), | |||||
Sorted = proplists:unfold( | |||||
lists:sort( | |||||
[{out_dir, OutDir}, | |||||
{doc_root, filename:join(Dir, option(doc_root, DtlOpts))}, | |||||
{custom_tags_dir, option(custom_tags_dir, DtlOpts)}, | |||||
{compiler_options, CompilerOptions}])), | |||||
%% ensure that doc_root and out_dir are defined, | |||||
%% using defaults if necessary | |||||
Opts = lists:ukeymerge(1, DtlOpts, Sorted), | |||||
?DEBUG("Compiling \"~s\" -> \"~s\" with options:~n ~s", | |||||
[Source, Target, io_lib:format("~p", [Opts])]), | |||||
case erlydtl:compile_file(ec_cnv:to_list(Source), | |||||
list_to_atom(module_name(Target)), | |||||
Opts) of | |||||
{ok, _Mod} -> | |||||
ok; | |||||
{ok, _Mod, Ws} -> | |||||
rebar_base_compiler:ok_tuple(State, Source, Ws); | |||||
error -> | |||||
rebar_base_compiler:error_tuple(State, Source, [], [], Opts); | |||||
{error, Es, Ws} -> | |||||
rebar_base_compiler:error_tuple(State, Source, Es, Ws, Opts) | |||||
end. | |||||
module_name(Target) -> | |||||
filename:rootname(filename:basename(Target), ".beam"). | |||||
needs_compile(Source, Target, DtlOpts) -> | |||||
LM = filelib:last_modified(Target), | |||||
LM < filelib:last_modified(Source) orelse | |||||
lists:any(fun(D) -> LM < filelib:last_modified(D) end, | |||||
referenced_dtls(Source, DtlOpts)). | |||||
referenced_dtls(Source, DtlOpts) -> | |||||
DtlOpts1 = lists:keyreplace(doc_root, 1, DtlOpts, | |||||
{doc_root, filename:dirname(Source)}), | |||||
Set = referenced_dtls1([Source], DtlOpts1, | |||||
sets:add_element(Source, sets:new())), | |||||
sets:to_list(sets:del_element(Source, Set)). | |||||
referenced_dtls1(Step, DtlOpts, Seen) -> | |||||
ExtMatch = re:replace(option(source_ext, DtlOpts), "\.", "\\\\\\\\.", | |||||
[{return, list}]), | |||||
ShOpts = [{use_stdout, false}, return_on_error], | |||||
AllRefs = | |||||
lists:append( | |||||
[begin | |||||
Cmd = lists:flatten(["grep -o [^\\\"]*\\", | |||||
ExtMatch, "[^\\\"]* ", F]), | |||||
case rebar_utils:sh(Cmd, ShOpts) of | |||||
{ok, Res} -> | |||||
string:tokens(Res, "\n"); | |||||
{error, _} -> | |||||
"" | |||||
end | |||||
end || F <- Step]), | |||||
DocRoot = option(doc_root, DtlOpts), | |||||
WithPaths = [ filename:join([DocRoot, F]) || F <- AllRefs ], | |||||
?DEBUG("All deps: ~p\n", [WithPaths]), | |||||
Existing = [F || F <- WithPaths, filelib:is_regular(F)], | |||||
New = sets:subtract(sets:from_list(Existing), Seen), | |||||
case sets:size(New) of | |||||
0 -> Seen; | |||||
_ -> referenced_dtls1(sets:to_list(New), DtlOpts, | |||||
sets:union(New, Seen)) | |||||
end. |
@ -1,72 +0,0 @@ | |||||
%% -*- erlang-indent-level: 4;indent-tabs-mode: nil -*- | |||||
%% ex: ts=4 sw=4 et | |||||
-module(rebar_erlydtl_SUITE). | |||||
-export([suite/0, | |||||
init_per_suite/1, | |||||
end_per_suite/1, | |||||
init_per_testcase/2, | |||||
end_per_testcase/2, | |||||
all/0, | |||||
compile/1]). | |||||
-include_lib("common_test/include/ct.hrl"). | |||||
-include_lib("eunit/include/eunit.hrl"). | |||||
-include_lib("kernel/include/file.hrl"). | |||||
%% =================================================================== | |||||
%% common_test callbacks | |||||
%% =================================================================== | |||||
suite() -> | |||||
[]. | |||||
init_per_suite(Config) -> | |||||
Config. | |||||
end_per_suite(_Config) -> | |||||
ok. | |||||
init_per_testcase(_, Config) -> | |||||
UpdConfig = rebar_test_utils:init_rebar_state(Config), | |||||
AppDir = ?config(apps, UpdConfig), | |||||
Name = rebar_test_utils:create_random_name("erlydtlapp_"), | |||||
Vsn = rebar_test_utils:create_random_vsn(), | |||||
rebar_test_utils:create_app(AppDir, Name, Vsn, [kernel, stdlib]), | |||||
write_dtl_file(AppDir, Name), | |||||
RebarConfig = [{erl_opts, [debug_info]}, | |||||
{erlydtl_opts, []}], | |||||
[{app_name, Name}, | |||||
{rebar_config, RebarConfig} | UpdConfig]. | |||||
end_per_testcase(_, _Config) -> | |||||
ok. | |||||
all() -> | |||||
[compile]. | |||||
compile(Config) -> | |||||
AppDir = ?config(apps, Config), | |||||
AppName = ?config(app_name, Config), | |||||
RebarConfig = ?config(rebar_config, Config), | |||||
Beam = beam_file(AppDir, AppName), | |||||
rebar_test_utils:run_and_check( | |||||
Config, RebarConfig, ["erlydtl", "compile"], | |||||
{ok, [{file, Beam}]} | |||||
). | |||||
beam_file(AppDir, AppName) -> | |||||
filename:join([AppDir, "_build", "default", "lib", | |||||
AppName, "ebin", AppName++"_template_dtl.beam"]). | |||||
write_dtl_file(Dir, AppName) -> | |||||
Erl = filename:join([Dir, "priv", "templates", AppName++"_template.dtl"]), | |||||
ok = filelib:ensure_dir(Erl), | |||||
ok = ec_file:write(Erl, get_body()). | |||||
get_body() -> | |||||
["[]"]. |