文本模板 |
|
宏处理器的缺点之一是它们没有数据结构。在 Lua 的旧版本(lua-4.0.1/test/examples/www/db.lua)中提供的一个示例展示了一种很好的技术,用于使用配置文件中的数据结构填充模板文件。
如果您只想用来自表的数值替换字符串中的变量,请参阅 字符串插值。
以下模块,Expand.lua
[5],使用 Bentley 的宏扩展算法,以及 GNU make 语法在模板字符串中引用变量。它还从 Mark J. Dominus 的 Text::Template.pm
和 Sriram Srinivasan 的模板驱动代码生成器 Jeeves
(在 O'Reilly 的 高级 Perl 编程 第 17 章中)中获取了一些增强功能。
目标是拥有一个名为 expand
的函数,该函数扫描模板字符串以查找变量引用,并递归地将它们替换为在列出的表或函数中找到的数值。
模板语法非常简单。对表成员和变量的引用表示为 ${varname
} 或 $(varname)
,或者如果它是一个字符的变量名,则表示为 $x
。
返回字符串的简单 Lua 表达式也可以用 ${ expr
} 或 $( expr )
包裹。
Lua 语句可以用以下之一包裹
$(do ... end)
$(if ... end)
$(for ... end)
$(while ... end)
$(repeat ... until ...)
Lua 代码可以设置一个名为 OUT
的变量,该变量将替换模板字符串中的代码。
Lua 表达式和语句由 loadstring
使用函数环境设置为第一个表来计算。
以下示例展示了如何使用 expand
。请注意,Expand.lua
仅适用于 Lua 5.0。
expand = require'Expand' template = [[ you can access variables: $v or environment variables: ${HOME} you can call functions: ${table.concat(list, ', ')} this list has ${list.n} elements ${string.rep('=', list.n)} ${table.concat(list)} ${string.rep('=', list.n)} or evaluate code inline ${for i=1,list.n do OUT = table.concat{ OUT, ' list[', i, '] = ', list[i], '\n'} end} you can access global variables: This example is from ${mjd} at $(mjdweb) The Lord High Chamberlain has gotten ${L.n} things for me this year. ${do diff = L.n - 5 more = 'more' if diff == 0 then diff = 'no' elseif diff < 0 then diff = -diff more = 'fewer' end end} That is $(diff) $(more) than he gave me last year. values can have other variables: $(ref) ]] mjd = "Mark J. Dominus" mjdweb = 'http://perl.plover.com/' L = { 'A', 'B', 'C', 'D', n=4} local x = { v = 'this is v', list = L, ref = "$(mjd) made Text::Template.pm" } -- fill in the template with values in table x io.write(expand(template, x, _G, os.getenv))
x
、然后搜索全局环境、最后通过调用 os.getenv 函数来找到。
以下是上面示例生成的输出
you can access variables: this is v or environment variables: /home/pshook you can call functions: A, B, C, D this list has 4 elements ==== ABCD ==== or evaluate code inline list[1] = A list[2] = B list[3] = C list[4] = D you can access global variables: This example is from Mark J. Dominus at http://perl.plover.com/ The Lord High Chamberlain has gotten 4 things for me this year. That is 1 fewer than he gave me last year. values can have other variables: Mark J. Dominus made Text::Template.pm
$(when varname ...)
语法。如果 varname 不是 false
,那么包含的字符串将进行宏扩展。如果 varname 是一个表,那么它将是包含的字符串进行宏扩展时搜索的第一个表。
代码生成的一个有用功能是 $(foreach tabname ...)
语法。如果 tabname 是一个包含表列表的表,那么对于 tabname
中的每个表,将对包含的字符串执行宏扩展,并将结果连接在一起。
expand = require'Expand' fun_temp = [[ ============================================================================== $(foreach funcs ${type} x = ${name}( ${table.concat(args, ', ')} ) { $(code) $(when stuff x = $x; y = $y; ) reutrn $(exit); } ) ============================================================================== ]] fun_list = { exit = 1; stuff = false; funcs = { { type = 'int'; name = 'bill'; args = { 'a', 'b', 'c' }; code = 'something'; stuff = { x=99, y=34 }; }; { type = 'char *'; name = 'bert'; args = { 'one', 'two', 'three' }; code = 'something else'; exit = 2 }; }; } io.write(expand(fun_temp, fun_list, _G))
============================================================================== int x = bill( a, b, c ) { something x = 99; y = 34; reutrn 1; } char * x = bert( one, two, three ) { something else reutrn 2; } ==============================================================================
此页面的第一个版本是 OldTextTemplate。