makrell, the macro processor
makrell is a simple but powerful macroprocessor for php language. It is aimed to simplify creating complex documents by using macros. A macro is a (typically short) chunk of text that replaces another (typically much longer) chunk. Macros act like functions in programming: once defined, they can be used over and over again.
The applications of makrell are templating, domain specific languages and php preprocessing.
There are perhaps thousands of php templates out there. Is there any reason to try yet another one? Yes, because makrell is different.
Every templating engine comes with its own language and even if it appears simple, you still have to learn it and to teach it to someone else, for example the designer you're working with. Sometimes the language is great, but not extensible, sometimes it's practical, but ugly, sometimes it just doesn't do what you want.
On the contrary, makrell doesn't have any hard-coded language, instead it provides the means for creating your own one on the fly. You are who decides what syntax is right for you.
Ok, enough happy talk for now. Let's just make a simple website with makrell. The first (and only) php file we need looks like this:
file: index.php
include 'makrell.inc.php';
$page = key($_GET);
if(!ctype_alpha($page))
$page = 'index';
$m = new Makrell;
echo $m->parse_file("$page.html");
We get an url like index.php?about and tell makrell to parse and output the file about.html .
The layout of our site is quite conventional: there is a header, navigation menu, content area and a footer.
file: index.html
header
navigation
content
footer
If we run it right away, what do we see?
header navigation content footer
Well... what did we expect? makrell is powerful, but it will not magically create our site for us. We have to tell it what we want.
file: index.html
header
navigation
content
footer
header {{
logo <b>title</b>
}}
navigation {{
<div>
| <a href="?about">About us</a>
| <a href="?news">News</a>
| <a href="?services">Services</a>
</div>
}}
footer {{
<p><small>copyright, terms of use</small></p>
}}
What do we see now?
logo title contentcopyright, terms of use
What happened? makrell has "expanded" the macros, i.e. replaced "header", "navigation" and "footer" with corresponding {{ ... }} blocks. The word "content" is not replaced, because we didn't define any substitution for it.
Did I say makrell doesn't have syntax? I lied. Of course, macro definitions must follow the rules, otherwise makrell won't be able to recognize them. The syntax is simple, though
macro {{ substitution }}
The macro doesn't have be an identifier, we could also have used {header} or <header/> or even <ilovexml:tag xmlns:xmllovesme="blah" foobar:tagname="header" /> ... Just name it like you want, makrell doesn't limit your creativity.
Since we've got three navigation items (about, news, services), we need three html files besides index. Apparently, the header, navigation and footer are common to all pages, it would be a good idea to store them in a separate file:
file: layout
header
navigation
content
footer
header {{
logo <b>title</b>
}}
navigation {{
<div>
| <a href="?about">About us</a>
| <a href="?news">News</a>
| <a href="?services">Services</a>
</div>
}}
footer {{
<p><small>copyright, terms of use</small></p>
}}
Now, in index.html we define only homepage content and attach layout , that takes care of the rest:
file: index.html
{{ include layout }}
content {{
<p>Welcome to our site!</p>
}}
logo titleWelcome to our site!
copyright, terms of use
Once we have this, the rest is easy:
file: about.html
{{ include layout }}
content {{
<p>Content for "about us" page</p>
}}
and the same for the "services" page:
file: services.html
{{ include layout }}
content {{
<p>Our services</p>
}}
Just to make things interesting, suppose that the "news" page has a different header. To achieve that, we don't need to touch our layout , we just define the header once again in news.html :
file: news.html
{{ include layout }}
header {{
<b>Hot News</b>
}}
content {{
<p>Some news</p>
}}
Hot NewsSome news
copyright, terms of use
Since the new definition is textually below that of layout , makrell "prefers" it over the old one. The whole thing is much like how inheritance in object-oriented languages works: we build an abstract prototype and override some parts of it to create specific functionality.
Of course, makrell can do much more than simply replacing one string with another, but more on that later... in the meantime, feel free to download makrell and to view examples
comment on this