Просмотр исходного кода

added variables preset option at compile time

Roberto Saccon 17 лет назад
Родитель
Сommit
d2ef8f685e

+ 13 - 0
demo/out/test_var_preset.html

@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <title>Test variable</title>								 
+  </head>
+  <body>
+	foostring1
+	preset-var1
+	foostring2
+	preset-var2
+  </body>
+</html>

+ 13 - 0
demo/templates/test_var_preset.html

@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <title>Test variable</title>								 
+  </head>
+  <body>
+	{{ var1 }}
+	{{ preset_var1 }}
+	<!--{{ var2 }}-->
+	{{ preset_var2 }}
+  </body>
+</html>

+ 36 - 10
src/demo/erlydtl_demo.erl

@@ -34,7 +34,7 @@
 -author('rsaccon@gmail.com').
 
 %% API
--export([compile/0, compile/1, compile/2, render/0, render/1]).
+-export([compile/0, compile/1, compile/2, render/0, render/1, preset/1]).
 
 %%====================================================================
 %% API
@@ -51,7 +51,12 @@ compile() ->
         true,
         fun(Path, _Acc) ->
             Module = filename:rootname(filename:basename(Path)),
-            erlydtl_server:compile(Path, DocRoot, Module)
+            case erlydtl_server:compile(Path, DocRoot, Module, {?MODULE, preset}) of
+                ok ->
+                    io:format("compile success: ~p~n",[Module]);
+                _ ->
+                    io:format("compile failure: ~p~n",[Module])
+            end
         end,
         []).
 
@@ -82,7 +87,10 @@ compile("htmltags" = Name) ->
                     
 compile("csstags" = Name) ->
      compile(Name, ".css");
-      
+
+compile("var_preset" = Name) ->
+     compile(Name, ".html");
+               
 compile(Name) ->
     io:format("No such template: ~p~n",[Name]).
                
@@ -97,7 +105,12 @@ compile(Name, Ext) ->
     DocRoot = filename:join([filename:dirname(code:which(?MODULE)),"..", "demo", "templates"]),
     Module = "test_" ++ Name,
     Path = filename:join([DocRoot, Module ++ Ext]),
-    erlydtl_server:compile(Path, DocRoot, Module).
+    case erlydtl_server:compile(Path, DocRoot, Module, {?MODULE, preset}) of
+        ok ->
+            io:format("compile success: ~p~n",[Module]);
+        _ ->
+            io:format("compile failure: ~p~n",[Module])
+    end.
 
 
 %%--------------------------------------------------------------------
@@ -112,7 +125,8 @@ render() ->
     render("for"),
     render("for_records"),
     render("htmltags"),
-    render("csstags").
+    render("csstags"),
+    render("var_preset").
         
 
 %%--------------------------------------------------------------------
@@ -143,7 +157,10 @@ render("htmltags" = Name) ->
     
 render("csstags" = Name) ->
     render(Name, ".css");
-    
+  
+render("var_preset" = Name) ->
+    render(Name, ".html", [{var1, "foostring1"}, {var2, "foostring2"}]);
+          
 render(Name) ->
     io:format("No such template: ~p~n",[Name]).  
                 
@@ -168,6 +185,14 @@ render(Name, Ext, Args) ->
     render2(OutDir, list_to_atom("test_" ++ Name), Ext, Args).
             
 
+%%--------------------------------------------------------------------
+%% @spec (atom()) -> proplist()
+%% @doc returns template preset variables
+%% @end 
+%%--------------------------------------------------------------------
+preset(test_var_preset) ->
+    [{preset_var1, "preset-var1"}, {preset_var2, "preset-var2"}].
+           
               
 %%====================================================================
 %% Internal functions
@@ -181,9 +206,10 @@ render2(OutDir, Module, Ext, Arg) ->
             case file:open(filename:join([OutDir, lists:concat([Module, Ext])]), [write]) of
         		{ok, IoDev} ->
         		    file:write(IoDev, Val),
-        		    file:close(IoDev);        		    
+        		    file:close(IoDev),
+        		    io:format("render success: ~p~n",[Module]);        		    
         		_ ->
-        		    io:format("TRACE ~p:~p ~p: file write failure~n",[?MODULE, ?LINE, Module])
+        		    io:format("render failure: ~p~n",[Module])
         	end
     end.
     
@@ -196,8 +222,8 @@ render2(OutDir, Module, Ext) ->
         		{ok, IoDev} ->
         		    file:write(IoDev, Val),
         		    file:close(IoDev),
-        		    io:format("TRACE ~p:~p ~p: success~n",[?MODULE, ?LINE, Module]);
+        		    io:format("render success: ~p~n",[Module]);
         		_ ->
-        		    io:format("TRACE ~p:~p ~p: file write failure~n",[?MODULE, ?LINE, Module])
+        		    io:format("render failure: ~p~n",[Module])
         	end
     end.

+ 27 - 41
src/erlydtl/erlydtl_base.erl

@@ -46,11 +46,11 @@
     build_tree/3, 
     build_tree/4, 
     build_tree/5,  
-    parse_transform/3, 
-    parse_transform/2, 
     parse_transform/1, 
+    parse_transform/2, 
     rel_dir/2, 
-    new_var/2]).
+    new_var/2,
+    binary_string/1]).
 
 
 build_tree(H, T, Ext) ->
@@ -73,37 +73,23 @@ parse(File) ->
                 {ok, Tokens} ->
                     erlydtl_parser:parse(Tokens);
                 Err ->
-                    io:format("TRACE ~p:~p ~p~n",[?MODULE, ?LINE, File ++ " Scanner failure:"]),
-                    io:format("TRACE ~p:~p ~p~n",[?MODULE, ?LINE, Err]),
                     Err
             end;
-        Err ->
-            io:format("TRACE ~p:~p ~p: ~p~n",[?MODULE, ?LINE, "File read error with:", File]),
-            Err   
+        _ ->
+            {error, "reading " ++ File ++ " failed"} 
     end.
-    
-
-parse_transform({var, Line, Val}, Var, Val) when is_atom(Var) ->
-    io:format("TRACE ~p:~p var_parse_transform1atom: ~p~n",[?MODULE, ?LINE, "Val"]),
-    {var, Line, Var}.
 
                                                
 parse_transform({tree, variable, _, Var}, Args) ->
-    %% io:format("TRACE ~p:~p var_parse_transform2 ~p~n",[?MODULE, ?LINE, "variable"]),
     Var2 = list_to_atom(tl(atom_to_list(Var))),
     binary_string(proplists:get_value(Var2, Args));      
 parse_transform(Other, _) ->    
-    %% io:format("TRACE ~p:~p var_parse_transform2 ~p~n",[?MODULE, ?LINE, "Other"]),
     Other.
         
 
 parse_transform({block, _Line , _Name, [nil, T]}) ->
 	parse_transform(T); 
-parse_transform({var, _Line, Val}) ->
-    io:format("TRACE ~p:~p var_parse_transform1: ~p~n",[?MODULE, ?LINE, Val]),    
-    erl_syntax:variable(Val);
-parse_transform(Other) -> 
-    io:format("TRACE ~p:~p ~p~n",[?MODULE, ?LINE, other]),   
+parse_transform(Other) ->   
     Other.   	
 
 
@@ -122,7 +108,12 @@ new_var(List, Acc) ->
         _ ->
             new_var(List, Acc + 1)
     end.
-        
+
+
+binary_string(String) ->
+    erl_syntax:binary([erl_syntax:binary_field(erl_syntax:integer(X)) || X <- String]).
+    %erl_syntax:string(String).  %% less verbose for debugging        
+
 
 %%====================================================================
 %% Internal functions
@@ -132,28 +123,31 @@ build_tree2(nil, [{extends, Line, Name}], Dtl) ->
     case parse(filename:join([DocRoot, Name])) of
         {ok, [AstH | AstT]} ->
 			{_, BaseBuffer, BaseArgs, _} = build_tree(AstH, AstT, DocRoot, Ext),			 
-			{Buffer1, Args1} = lists:foldl(fun(X, {AccBuffer, AccArgs}) ->   
+			Out = lists:foldl(fun(X, {AccBuffer, AccArgs, Status}) ->   
                     case X of
-                        {block, _, BlockName, _} ->
+                        {block, Line1, BlockName, _} ->
                             case lists:keysearch(BlockName, 3, Buffer) of
                         		{value, {block, _, BlockName, [H | T]}} ->
                         		    {_, Buffer2, Args2, _Props2} = build_tree(H, T, Ext),
                         		    Buffer3 = [lists:reverse(Buffer2), AccBuffer],
                         		    Args3 = [Args2, AccArgs],
-                        		    {lists:flatten(Buffer3), lists:flatten(Args3)};
+                        		    {lists:flatten(Buffer3), lists:flatten(Args3), Status};
                         		_ ->
-                            	    io:format("TRACE ~p:~p wrong-block: ~p~n~n",[?MODULE, ?LINE, X]),
-                            	    % create error message
-                            	    {AccBuffer, AccArgs}                        		     
+                            	    {AccBuffer, AccArgs, {block, Line1, Name}}                        		     
                             end;
                         _ ->
-                            io:format("TRACE ~p:~p other-not-block: ~p~n~n",[?MODULE, ?LINE, X]),
-                            {[X | AccBuffer], AccArgs}
+                            {[X | AccBuffer], AccArgs, Status}
                     end
                 end, 
-                {[], BaseArgs}, 
-                BaseBuffer),           		   
-		    {inherited, lists:reverse(lists:flatten([Buffer1])), lists:flatten(Args1), []};
+                {[], BaseArgs, ok}, 
+                BaseBuffer),   
+            case Out of
+                {Buffer1, Args1, ok} ->       		   
+		            Buffer2 = lists:reverse(lists:flatten([Buffer1])),
+		            {inherited, Buffer2, lists:flatten(Args1), []};
+		        {_, _, Err} ->
+		            {error, Err}
+		    end;
 	    {error, _} ->
 		     {error, {extends, Line, "file not found"}}		
     end;
@@ -187,7 +181,6 @@ build_tree2(nil, [{for, _, It, Var, [HFor | TFor]}], #dtl{buffer = Buffer, props
     {regular, lists:flatten([Buffer1, Buffer]), Args1, Props};     
 
 build_tree2(nil, [Token], #dtl{buffer = Buffer, args = Args, props = Props}) ->
-    %io:format("TRACE ~p:~p other1-Token: ~p~n",[?MODULE, ?LINE, Token]),
     {regular, [Token | Buffer], Args, Props}; 
   
 build_tree2([H | T], [{var, _, Var}], #dtl{buffer = Buffer, var = Var} = Dtl) ->
@@ -224,7 +217,6 @@ build_tree2([H | T], [{for, _, It, Var, [HFor | TFor]}], #dtl{buffer = Buffer} =
     build_tree2(H, T, Dtl#dtl{buffer = lists:flatten([Buffer1, Buffer]), args = Args1});
         	
 build_tree2([H | T], [Token], #dtl{buffer = Buffer} = Dtl) ->
-    %io:format("TRACE ~p:~p other2-Token: ~p~n",[?MODULE, ?LINE, Token]),
     build_tree2(H, T, Dtl#dtl{buffer = [Token | Buffer]}).
     
 
@@ -259,7 +251,6 @@ handle_for(It, Var, HFor, TFor, #dtl{args = Args, ext = Ext}) ->
     
            	        	
 handle_tag(TagName, Line, TagArgs, Acc0, Ext) ->
-    io:format("TRACE ~p:~p ~p~n",[?MODULE, ?LINE, TagArgs]),
     case parse(filename:join([erlydtl_deps:get_base_dir(), "priv", "tags", atom_to_list(TagName) ++ Ext])) of
         {ok, ParentAst} ->
 		    [H|T]=ParentAst,
@@ -272,9 +263,4 @@ handle_tag(TagName, Line, TagArgs, Acc0, Ext) ->
 			{ok, List1};
 		_ ->
     	    {error, {TagName, Line, "loading tag source template failed"}}
-    end.
-  
-    
-binary_string(String) ->
-    % erl_syntax:binary([erl_syntax:binary_field(erl_syntax:integer(X)) || X <- String]).
-    erl_syntax:string(String).
+    end.

+ 3 - 2
src/erlydtl/erlydtl_parser.erl

@@ -5,6 +5,7 @@
 string({_, String}) ->
     %erl_syntax:binary([erl_syntax:binary_field(erl_syntax:integer(X)) || X <- String]).
     erl_syntax:string(String).
+    
 
 var({_, Line, Var}) ->
     case string:tokens(Var, ".") of
@@ -139,7 +140,7 @@ yecctoken2string(Other) ->
 
 
 
--file("src/erlydtl/erlydtl_parser.erl", 142).
+-file("src/erlydtl/erlydtl_parser.erl", 143).
 
 yeccpars2(0, __Cat, __Ss, __Stack, __T, __Ts, __Tzr) ->
  __NewStack = yeccpars2_0_(__Stack),
@@ -311,4 +312,4 @@ yeccpars2_12_([__3,__2,__1 | __Stack]) ->
   end | __Stack].
 
 
--file("src/erlydtl/erlydtl_parser.yrl", 113).
+-file("src/erlydtl/erlydtl_parser.yrl", 114).

+ 2 - 2
src/erlydtl/erlydtl_parser.yrl

@@ -68,8 +68,8 @@ Element -> for Elements endfor : for('$1', '$2').
 Erlang code.
 
 string({_, String}) ->
-    %erl_syntax:binary([erl_syntax:binary_field(erl_syntax:integer(X)) || X <- String]).
-    erl_syntax:string(String).
+    erl_syntax:binary([erl_syntax:binary_field(erl_syntax:integer(X)) || X <- String]).
+    %erl_syntax:string(String).  %% less verbose for debugging 
     
 
 var({_, Line, Var}) ->

+ 51 - 19
src/erlydtl/erlydtl_server.erl

@@ -36,7 +36,7 @@
 -behaviour(gen_server).
 	
 %% API
--export([start_link/0, compile/1, compile/3, compile/4]).
+-export([start_link/0, compile/1, compile/3, compile/4, compile/5]).
 
 %% gen_server callbacks
 -export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@@ -56,8 +56,8 @@
 %%--------------------------------------------------------------------
 start_link() ->
     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
-    
-
+        
+        
 %%--------------------------------------------------------------------
 %% @spec (File::string()) -> 
 %%     {Ok::atom, Ast::tuple() | {Error::atom(), Msg::string()}
@@ -68,25 +68,42 @@ compile(File) ->
     compile(File, todo, todo).
         
 %%--------------------------------------------------------------------
-%% @spec (File::string(), DocRoot::string(), Module::string()) -> 
+%% @spec (File::string(), DocRoot::string(), Mod::string()) -> 
 %%     {Ok::atom, Ast::tuple() | {Error::atom(), Msg:string()}
 %% @doc compiles a template to a beam file
 %% @end 
 %%--------------------------------------------------------------------
-compile(File, DocRoot, Module) ->
-    compile(File, DocRoot, Module, "render").
+compile(File, DocRoot, Mod) ->
+    compile(File, DocRoot, Mod, "render").
     
 
 %%--------------------------------------------------------------------
-%% @spec (File::string(), DocRoot::string(), Module::string(), Function::atom()) -> 
+%% @spec (File::string(), DocRoot::string(), Mod::string(), Vars::tuple()) -> 
 %%     {Ok::atom, Ast::tuple() | {Error::atom(), Msg:string()}
 %% @doc compiles a template to a beam file
 %% @end 
 %%--------------------------------------------------------------------
-compile(File, DocRoot, Module, Function) ->   
-    gen_server:call(?MODULE, {compile, File, DocRoot, Module, Function}).
+compile(File, DocRoot, Mod, VarsCallback) when is_tuple(VarsCallback)->
+    compile(File, DocRoot, Mod, "render", VarsCallback);
+compile(File, DocRoot, Mod, Func) ->   
+    gen_server:call(?MODULE, {compile, File, DocRoot, Mod, Func, []}).
+        
+%%--------------------------------------------------------------------
+%% @spec (File::string(), DocRoot::string(), Mod::string(), Func::atom(),
+%%         Vars::tuple()) -> 
+%%     {Ok::atom, Ast::tuple() | {Error::atom(), Msg:string()}
+%% @doc compiles a template to a beam file
+%% @end 
+%%--------------------------------------------------------------------            
+compile(File, DocRoot, Mod, Func, {VarsMod, VarsFunc}) ->   
+    case catch VarsMod:VarsFunc(list_to_atom(Mod)) of
+        Vars when is_list(Vars) ->
+            gen_server:call(?MODULE, {compile, File, DocRoot, Mod, Func, Vars});
+        _ -> 
+            gen_server:call(?MODULE, {compile, File, DocRoot, Mod, Func, []})
+    end.
+    
         
-
 %%====================================================================
 %% gen_server callbacks
 %%====================================================================
@@ -113,16 +130,16 @@ init([]) ->
 %% @doc Handling call messages
 %% @end 
 %%--------------------------------------------------------------------
-handle_call({compile, File, DocRoot, Module, Function}, _From, State) ->
+handle_call({compile, File, DocRoot, Mod, Func, Vars}, _From, State) ->
     Reply = case erlydtl_base:parse(File) of
         {ok, Ast} ->
 		    DocRoot2 = erlydtl_base:rel_dir(filename:dirname(File), DocRoot),
 		    Ext = filename:extension(File),
-            compile(Ast, Module, Function, DocRoot2, Ext, State#state.reload);
+		    compile(Ast, Mod, Func, DocRoot2, Ext, Vars, State#state.reload);
         Err ->
             Err
     end,
-    {reply, Reply, State};
+    {reply, Reply, State};       
 
 handle_call(_Request, _From, State) ->
     Reply = ok,
@@ -171,19 +188,34 @@ code_change(_OldVsn, State, _Extra) ->
 %%====================================================================
 %% Internal functions
 %%====================================================================
-compile([H | T], Module, Function, DocRoot, Ext, Reload) ->
+compile([H | T], Module, Function, DocRoot, Ext, Presets, Reload) ->
     case erlydtl_base:build_tree(H, T, DocRoot, Ext) of
         {regular, Out, Args, _} ->
             Out1 = [erlydtl_base:parse_transform(X) ||  X <- Out],
-            create_module(Out1, Args, Module, Function, Reload);
+            create_module(Out1, Args, Module, Function, Presets, Reload);
         {inherited, Out, Args, _} ->
-            create_module(Out, Args, Module, Function, Reload);
+            create_module(Out, Args, Module, Function, Presets, Reload);
         {error, Reason} ->
-            % check whether Reason contains Linenumber
+            % check whether Reason contains Linenumber ??
             {error, Reason}
     end.   
     
-
+create_module(List, Args, Module, Function, [], Reload) ->
+    create_module(List, Args, Module, Function, Reload);      
+            
+create_module(List, Args, Module, Function, Presets,  Reload) ->
+    {List1, Args1} = lists:foldl(fun({Prop, Val}, {List2, Args2}) ->
+            Key = list_to_atom(lists:concat(["A", Prop])),
+            Bin = erlydtl_base:binary_string(Val),
+            List3 = lists:keyreplace(Key, 4, List2, Bin),
+            Args3 = lists:delete(Key, Args2),
+            {List3, Args3}
+        end,
+        {List, Args},
+        Presets),
+    create_module(List1, Args1, Module, Function, Reload).
+       
+            
 create_module(List, Args, Module, Function, Reload) ->
     {BodyAST, Args1} = case Args of 
         []  ->
@@ -206,7 +238,7 @@ create_module(List, Args, Module, Function, Reload) ->
     [ModAST, CmpAST] = [erl_syntax:attribute(erl_syntax:atom(X), [erl_syntax:atom(Y)]) ||
         {X, Y} <- [{"module", Module}, {"compile", "export_all"}]],
     Forms = [erl_syntax:revert(X) || X <- [ModAST, CmpAST, FuncAST]],
-%io:format("TRACE ~p:~p Forms: ~p~n",[?MODULE, ?LINE, Forms]),
+    %io:format("TRACE ~p:~p Forms: ~p~n",[?MODULE, ?LINE, Forms]),
     case compile:forms(Forms) of
         {ok, Module1, Bin} ->
             case erlydtl:write_beam(Module1, Bin, "ebin") of