loot

These are examples of using loot. All of them assume that loot has been already loaded: local loot = require "loot".

Simple templates

template = loot.template "Hello, %username%!" -- creates a new template using provided string
filled_template = template{ -- creates a new template object using provided data
	username = "mrsmith" -- fields correspond to strings between percentage signs in the template string
}
print(filled_template) -- Hello, mrsmith! -- fills in the data and prints the result
template = loot.template "Hello, %name%! This day is 20%% %kind% than yesterday!"
-- double all the percentage signs without special meaning
filled_template = template{
	kind = "cooler"
}
print(filled_template) -- Hello, %name%! This day is 20% cooler than yesterday!
-- there is no data for field "name", so it's not processed at all
template = loot.template "Hello, %name%! This day is 20%% %kind% than yesterday!"
template.name = "John" -- template now contains data for marker "name"
filled_template = template{
	name = "Bob",
	kind = "cooler"
}
print(filled_template) -- Hello, John! This day is 20% cooler than yesterday!
-- provided data doesn't override data set for the template beforehand

Filling templates

template = loot.template "Hello, %name%! This day is 20%% %kind% than yesterday!"
filled_template = template{
	name = "Bob",
	kind = "cooler"
}
-- Note that this hasn't actually generated string result. 
-- It only linked template to the provided data. 
-- Thinking OOP, it created an object of class "template" and initialized it. 
-- There are several ways to get the string result...

text = filled_template() -- call it
print(filled_template) -- print it (writing to file or socket works, too)
text = tostring(filled_template) -- tostring it
text = filled_template .. some_string -- concatenate it

Non-trivial behaviour

template = loot.template "It is %kind% outside"
function template:kind() -- marker is a method
	if self.temperature > 30 then
		return "hot"
	elseif self.temperature > 20 then
		return "warm"
	elseif self.temperature >= 0 then
		return "not as warm as desired"
	else
		return "cold"
	end
end

filled_template = template{
	temperature = 25
}
print(filled_template) -- It is warm outside
template = loot.template [[String "%string%" is %n% characters long. ]]

function template:n()
	return self.string:len()
end

filled_template = template{
	string = "foobar"
}

print(filled_template) -- String "foobar" is 6 characters long. 

Nested templates

template1 = loot.template [[
<html>
<head>
<title>%title%</title>
</head>
<body>
%body%
</body>
</html>
]]

template2 = loot.template [[
<h1>%title%</h1>
<div>
%content%
</div>]]

template1.body = template2

-- usage:

filled_template = template1{
	title = "My page",
	content = "My content"
}

print(filled_template) --[[
<html>
<head>
<title>My page</title>
</head>
<body>
<h1>My page</h1> -- nested template sees outer data
<div>
My content
</div>
</body>
</html>
]]

Preprocessing

local md = require "markdown" -- lua library for parsing markdown

template = loot.template [[
<article>
<header>
Author: %author%<br>
%date%
</header>
<div>
%text%
</div>
</article>
]]

function template:text(text) -- methods receive outer data as argument
	return md(text)
end

-- usage

filled_template = template{
	author = "Mr. Smith",
	date = "12.04.2013",
	text = [[
# Header
Hello!
]]
}

print(filled_template) --[[
<article>
<header>
Author: Mr. Smith<br>
12.04.2013
</header>
<div>
<h1>Header</h1>
<p>Hello!</p>
</div>
</article>
]]
template = loot.template [[The string is "%string%"]]

function template:__prepare() -- this method is called right before filling template
	self.string = self.string:rep(self.n) -- something weird
end

filled_template = template{
	string = "foobar",
	n = 3
}

print(filled_template) -- The string is "foobarfoobarfoobar"

-- Note that it's possible to define other special methods for a template class
-- and then use them in __prepare() or markers-methods (see Non-trivial behaviour)
-- Names of these methods should start with two underscores.