root/HTTP/Template.lua

Revision 1453 (checked in by rsz, 4 weeks ago)

cleanup

Line 
1 --------------------------------------------------------------------------------
2 -- Title:               Template.lua
3 -- Description:         Like a square peg in a round hole
4 -- Author:              Raphaël Szwarc http://alt.textdrive.com/lua/
5 -- Creation Date:       January 30, 2007
6 -- Legal:               Copyright (C) 2007 Raphaël Szwarc
7 --                      Under the terms of the MIT License
8 --                      http://www.opensource.org/licenses/mit-license.html
9 --------------------------------------------------------------------------------
10
11 -- import dependencies
12 local io = require( 'io' )
13 local table = require( 'table' )
14
15 local assert = assert
16 local getmetatable = getmetatable
17 local pairs = pairs
18 local require = require
19 local setmetatable = setmetatable
20 local tostring = tostring
21
22 --------------------------------------------------------------------------------
23 -- Template
24 --------------------------------------------------------------------------------
25
26 module( 'Template' )
27 _VERSION = '1.0'
28
29 local self = setmetatable( _M, {} )
30 local meta = getmetatable( self )
31
32 --------------------------------------------------------------------------------
33 -- Utilities
34 --------------------------------------------------------------------------------
35
36 local contents = setmetatable( {}, { __mode = 'k' } )
37 local templates = setmetatable( {}, { __mode = 'k' } )
38 local variables = setmetatable( {}, { __mode = 'k' } )
39 local cache = setmetatable( {}, { __mode = 'v' } )
40
41 local function Path( aName, aLevel )
42     return ( '%s%s' ):format( require( 'Bundle' )(), aName )
43 end
44
45 local function ReadContent( aPath, aLevel )
46     local aContent = cache[ aPath ]
47    
48     if not aContent then
49         local aFile = io.open( aPath, 'rb' )
50        
51         if not aFile then
52             aFile = assert( io.open( Path( aPath, aLevel ), 'rb' ) )
53         end
54        
55         aContent = aFile:read( '*a' )
56         aFile:close()   
57        
58         cache[ aPath ] = aContent     
59     end
60    
61     return aContent
62 end
63
64 local function SetContent( self, aContent )
65     contents[ self ] = tostring( aContent )
66 end
67
68 local function GetContent( self )
69     return contents[ self ]
70 end
71
72 local function GetTemplates( self )
73     local someTemplates = templates[ self ]
74    
75     if not someTemplates then
76         someTemplates = {}
77         templates[ self ] = someTemplates
78     end
79    
80     return someTemplates
81 end
82
83 local function GetVariables( self )
84     local someVariables = variables[ self ]
85    
86     if not someVariables then
87         someVariables = {}
88         variables[ self ] = someVariables
89     end
90    
91     return someVariables
92 end
93
94 --------------------------------------------------------------------------------
95 -- Metamethods
96 --------------------------------------------------------------------------------
97
98 function meta:__call( aContent )
99     local aTemplate = {}
100
101     setmetatable( aTemplate, self )
102    
103     SetContent( aTemplate, aContent )
104
105     return aTemplate
106 end
107
108 function meta:__index( aKey )
109     return self( ReadContent( aKey, 4 ) )
110 end
111
112 function meta:__concat( aValue )
113     return tostring( self ) .. tostring( aValue )
114 end
115
116 function meta:__tostring()
117     return ( '%s/%s' ):format( self._NAME, self._VERSION )
118 end
119
120 function self:__index( aKey )
121     local Template = require( 'Template' )
122     local someTemplates = GetTemplates( self )
123     local aTemplate = someTemplates[ aKey ]
124    
125     if not aTemplate then
126         local aContent = GetContent( self )
127         local anOpenStart, anOpenEnd = aContent:find( '[t:' .. aKey .. ']', 1, true )
128         local aCloseStart, aCloseEnd = aContent:find( '[/t:' .. aKey .. ']', anOpenEnd, true )
129                
130         aTemplate = Template( aContent:sub( anOpenEnd + 1, aCloseStart - 1 ) )
131         someTemplates[ aKey ] = aTemplate
132        
133         aContent = aContent:sub( 1, anOpenStart - 1 ) .. '[v:' .. aKey .. ']' .. aContent:sub( aCloseEnd + 1 )
134         SetContent( self, aContent )
135     end
136    
137     return Template( GetContent( aTemplate ) )
138 end
139
140 function self:__newindex( aKey, aValue )
141     local someVariables = GetVariables( self )
142     local aBuffer = someVariables[ aKey ]
143    
144     if not aBuffer then
145         aBuffer = {}
146         someVariables[ aKey ] = aBuffer
147     end
148        
149     aBuffer[ #aBuffer + 1 ] = tostring( aValue or '' )
150 end
151
152 function self:__concat( aValue )
153     return tostring( self ) .. tostring( aValue )
154 end
155
156 function self:__tostring()
157     local aContent = GetContent( self )
158     local someVariables = GetVariables( self )
159     local aTable = {}
160    
161     for aKey, aBuffer in pairs( someVariables ) do
162         aKey = ( '[v:%s]' ):format( aKey )
163         aTable[ aKey ] = table.concat( aBuffer, '' )
164     end
165    
166     aContent = aContent:gsub( '(%[v%:%w-%])', aTable )
167    
168     return aContent
169 end
170
Note: See TracBrowser for help on using the browser.