Showing posts with label template. Show all posts
Showing posts with label template. Show all posts

Monday, August 6, 2007

More things about the blogger API...

I've reworked many times the atom template I use to post things to blogger, and what I'll describe here is a design I found simple and efficient, so here's the code :

This is the main function:

entry_new(Title, Author, { Content, ContentType }, Tags) when is_list(Tags) ->
NTitle = post_title(Title),
NContent = post_content(Content, ContentType),
NTags = post_tags(Tags),
NAuthor = post_author(Author),
[
entry_header(),
NTitle,
NContent,
NAuthor,
NTags,
entry_footer()
];

The main idea is to use a list of binary, using this simple methods we don't mess with multiple copies or padding or strings management... This is quick and clean.

Here's some little function to create simple tempates:

entry_new(Title, Author, Content, Tags) ->
entry_new(Title, Author, {Content, text}, Tags).

entry_header() ->
<<"<entry xmlns=\"http://www.w3.org/2005/Atom\">">>.

entry_footer() ->
<<"</entry>">>.

post_title(Title) ->
[ <<"<title type=\"text\">">>, list_to_binary(Title), <<"</title>">> ].

post_author({ AuthorName, AuthorEmail }) ->
[
<<"<author><name>">>, list_to_binary(AuthorName), <<"</name><email>">>,
list_to_binary(AuthorEmail), <<"</email></author>">> ];
post_author(AuthorEmail) ->
post_author({ "", AuthorEmail }).



Here's some other function to carefully set the content-type with the post content:

post_content(Content, ContentType) when is_list(Content) ->
post_content(list_to_binary(Content), ContentType);
post_content(Content, html) ->
post_content(Content, "html");
post_content(Content, xhtml) ->
post_content(Content, "xhtml");
post_content(Content, text) ->
post_content(Content, "text");
post_content(Content, ContentType) ->
[ <<"<content type=\"">>, list_to_binary(ContentType), <<"\">">>,
Content,
<<"</content>">> ].


And now the code the post 'tags':

post_tags([]) ->
<<>>;
post_tags(List) ->
lists:map(
fun(X) ->
[ <<"<category scheme='http://www.blogger.com/atom/ns#' term='">>,
list_to_binary(X) ,
<<"'/>">> ]
end,
List).

The magic stands in the 'category' atom tag.

Tuesday, June 26, 2007

Using ports for fast templating...

I find myself many times searching for fast templating system, and I always stop my search by developing one myself. ( the one is done using flex generated code, which means that it is very fast... )

Here, I need some fast (rather simple) template system that gives me some data to send later to an SMTP server (the body of the mail).

First the code:
get(Template, Args) ->
NewArgs = list_to_shell(Args),
Cmd = lists:flatten([ ?engine, $ , "conf/template/", Template, $ , NewArgs ]),
Port = open_port({spawn, Cmd}, [ {cd, code:lib_dir(mmailer)}, stream, binary]),
process_flag(trap_exit, true),
loop(Port).
You'll find some unknown notation: '?engine' and $.
  • ?engine is a macro, defined like this -define(engine, "templater").
  • $ is the character notation, the character that follows the dollar sign is the character I want. Actually I need the space character...
Now the function list_to_shell:
list_to_shell(Args) ->
L = lists:map(fun(X) -> [X, $ ] end, Args),
lists:flatten(L).
This function add a space after after element of the array passed as parameter. I construct the shell command this way.

The call to open_port is the main part of the code:
Port = open_port({spawn, Cmd}, [ {cd, code:lib_dir(mmailer)}, stream, binary]),
The following describe what the above line does:
  • spawn the command 'Cmd'
  • in the directory code:lib_dir(mmailer),
  • this command will write data as a stream
  • and I want erlang to give me a binary stream.

(code:lib_dir(mmailer) gives me the directory where the mmailer module is located)

More about my engine... My engine takes as firts arguments the template file to parse and every other parameter is saved as $1, or $2, or $3 etc.

Example of a template 'test.template'
Hello $1 $2 !
We have a good news for you, join us at url/$3

So calling:
templater test.template Mister John connect?John
Will compute the following:
Hello Mister John !
We have a good news for you, join us at url/connect?John

Conclusion, you can use whatever template system efficiently with the open_port function, since you can dynamically build the command line.

NB: I've not secure the line generated by list_to_shell, any '; rm -rf *' in the command line will do nasty things with your stuff :)

Sticky