简介
Smart Text是一个文本生成工具.
使用它可以帮助你用极少的时间快速生成大量文本(比如代码,报表,配置文件等等,本帮助文件就是使用SmartText生成的).
它内置了一个名为LuaTextTemplate的文本模板引擎(类似Velocity), 并提供了一个漂亮,简单易用的GUI让你更好地使用它.
主要特点:
- 使用简单的Lua语法构建模板(非常灵活!)
- 支持3种类型的参数文件
- .csv
- .xml
- .lua
- 支持命令行参数
- 多语言支持(包括英语,简体中文,日语)
- 友好的GUI
开始
Smart Text需要运行在Windows XP/Vista/7及以上的操作系统.
并需要安装.Net Framework 4.0及以上.
双击SmartText.exe即可运行.

界面还算漂亮吧?好,那么让我们用一个简单的例子来看看Smart Text能干些什么.
- 制作模板文件
用你喜欢的文本编辑器输入下面的文本,并保存为template.txt(文件位置任意).
Hello ${person.name}!
This year ${person.name} is ${person.age} years old.
Next year ${person.name} is ${person.age+1} years old.
- 制作参数文件
同样,用文本编辑器输入下面的文本,并保存为parameter.xml(文件位置任意).
<person>
<name>WAKU</name>
<age>29</age>
</person>
- 使用Smart Text
在"模板文件"中选择保存的template.txt文件,
在"参数文件"中选择parameter.xml文件,
"输出文件"为空即可,
点击"生成"按钮,如果一切正常的话,你将会看到下面的输出文本:
怎么样,聪明的你应该能猜到Smart Text大概的本领了吧?
模板
SmartText的模板是生成文本的框架.
模板中使用一些特殊的标记来区分哪些是普通文本,哪些是要特殊处理的内容.
SmartText主要使用Lua语法做为模板的控制语法,
所以如果你熟悉Lua的话,你会非常容易的就能掌握SmartText的模板文件
如果不太熟悉Lua的话也不要紧,只需要学习几种非常简单的结构就能做出符合自己要求的模板文件来.
变量
通过开始中的例子,你应该已经知道了SmartText的模板使用变量的语法:
只要是一个合法的Lua表达式,SmartText就会计算该表达式的结果,并用结果替换变量出现的位置.
利用Lua的特性,可以很容易为一个变量设置一个默认值,比如:
当person.name为nil(Lua中表示空值)时,则使用or后面的值(一个字符串somebody).
另外Lua中使用字符串,既可以使用双引号("),也可以使用单引号(').
之前的例子都展示了一个很重要的用法,即使用点(.)来表示参数的层级结构.
在参数中我们还会详细讲解
流程控制语句
模板中可以使用判断语句(if)或者是循环语句(for)来控制文本生成的方式.
因为SmartText内部使用Lua(最终模板会被解析成Lua代码),所以流程控制语句都是使用标准的Lua语法.
唯一特别的是,需要使用#{...}的方式:
if
看下面的例子:
${person.name} is a child.
#{else}
${person.name} is an adult.
#{end}
该例子中,使用if语句根据年龄在child和adult中做出判断.
使用之前的xml参数的话,该示例的输出结果为:
Lua中if语句完整的语法是这样:
当然在判断条件中也可以使用Lua中的运算符,下面是运算符的一个表格:
运算符 | 含义 |
== | 相等 |
~= | 不等 |
< | 小于 |
> | 大于 |
<= | 小于等于 |
>= | 大于等于 |
and | 与 |
or | 或 |
not | 非 |
for
使用for语句,可循环输出模板中的一部分,在输出重复内容,列表等文本时极为有用.
Lua中的for有两种,我们先看第一种:数值型for
i = ${i}
#{end}
这个模板是如此简单甚至都不需要使用参数文件就能输出结果:
i = 2
i = 3
i = 4
i = 5
数值型for的语法是这样:
然而在实际工作中,我们经常使用的是另一种for:范型for
演示范型for之前我们需要先扩展我们的参数文件:
<person>
<name>WAKU</name>
<age>29</age>
</person>
<person>
<name>Joey</name>
<age>2</age>
</person>
</list>
然后在模板中像下面这样使用范型for:
NAME: ${p.name} AGE: ${p.age}
#{end}
输出结果为:
NAME: Joey AGE: 2
SmartText将XML参数的解析成Lua代码,(将在参数中详细讲解)其中的person是一个Table(可做为数组),通过list.person来引用它.
SmartText提供了一个非常方便的函数enum,用来枚举Table中的元素,
所以enum(list.peronson)就是枚举数组中所有person,每次的枚举结果用p表示.
- 技术细节:
enum是SmartText提供的一个函数,并不是Lua的标准函数,
enum不仅可以枚举Lua的数组形式的Table,还可以枚举.Net数组,集合(List, Dictionary等)和所有实现了IEnumerable接口的对象,
当枚举Lua的Table时,与Lua函数ipairs类似,不同的地方是,ipairs函数返回两个值(索引和值),而enum只返回值.
关于enum函数的具体实现,可查看SmartText的源代码
最后,提供范型for的语法:
以上就是关于流程控制的讲解,主要是if和for,但是SmartText与Lua结合的非常灵活,
实际上你可以在#{...}中插入任意有效的Lua语句,它们都将成为Lua代码并被执行.
你可以在#{...}中定义全局变量,并在模板的其它位置使用它.
你甚至可以定义函数,以此实现类似velocity中的宏.
参数
SmartText可以使用三种类型的参数文件(CSV XML LUA),虽然它们作用类似(都是向模板提供数据),
但是每种类型都有各自的优缺点,应当在不同场合使用合适的参数文件类型.
SmartText把CSV和XML参数文件都解析为Lua代码,但是不需要掌握解析的细节,只需要知道如何在模板中正确的使用数据即可.
CSV参数文件是最简单的参数文件,数据关系简单明了.可以使用EXCEL编辑CSV文件.
行列格式也和数据库中的表对应,所以如果想以数据库中的一个表做为参数的话,CSV参数文件是最合适不过的了.
但是CSV参数文件不能表示有层级关系的数据结构,这时就需要考虑使用XML和LUA形式的参数文件了.
示例:
模板文件:
${parameter[2].name} is ${parameter[2].age} years old.
参数文件 "parameter.csv":
WAKU,29
Joey,2
输出结果:
Joey is 2 years old.
因为CSV文件没有类似XML文件的根元素,所以SmartText将CSV参数文件的文件名做为每个变量的前缀.
示例中,因为CSV参数文件的文件名是parameter,所以前缀的名称也是parameter
使用下标方式访问CSV文件第一行的方式就变成了parameter[1](Lua的数组下标从1开始),
而访问该行name列中的内容就变成了parameter[1].name,很简单.
- 技术细节:
实际上parameter已经变成了Lua中的Table.
SmartText将CSV参数文件解析成嵌套的Table,
CSV文件除了第一行header以外每行都解析成Table中的一个子Table.
示例中的CSV解析完的Lua代码如下:
parameter =
{
{
['name'] = 'WAKU',
['age'] = 29,
},
{
['name'] = 'Joey',
['age'] = 2,
},
}
上面的示例虽然能很好的工作,但是模板却略显笨拙,
使用范型for,你完全可以使用以下的模板形式得到完全一样的输出结果:
${p.name} is ${p.age} years old.
#{end}
值得一提的是,SmartText使用LumenWorks解析CSV文件,LumenWorks是我认为.Net中最棒的CSV解析器.
XML参数文件
XML文件是非常流行的文件格式,有着良好的兼容性,树状的关系最适合表现具有层级关系的数据结构.
.Net中对XML也有非常完善的支持,你可以将一个.Net对象序列化为XML文件,可以将DataSet对象直接写入XML文件等等.
XML参数文件的缺点可能是文件内容有些冗长,没有合适的工具的话编辑也有些麻烦.
同CSV参数文件一样,SmartText把XML参数文件也解析为Lua代码.
示例:
模板文件:
${p.name} is ${p.age} years old.
${p.name} likes ${join(p.favourite_food.food)}.
#{end}
参数文件 "parameter.xml":
<person name="WAKU" age="29">
<favourite_food>
<food>rice</food>
<food>chicken</food>
</favourite_food>
</person>
<person name="Joey" age="2">
<favourite_food>
<food>milk</food>
<food>juice</food>
<food>candy</food>
</favourite_food>
</person>
</list>
输出结果:
WAKU likes rice,chicken.
Joey is 2 years old.
Joey likes milk,juice,candy.
这个示例演示了如何正确的在模板中引用XML参数中的内容.
只需记住几个简单的规则:
1.变量从根节点开始(示例中根节点为list)
2.使用点(.)引用Attribute(示例中的name和age)
3.同样使用点(.)引用子节点
4.如果一个节点出现多次,则它就是一个数组,可以使用enum函数枚举(示例中的person和food)
示例的模板中出现了一个新函数join,和enum一样它也是由SmartText提供的.
作用是将一个数组中的字符串元素拼接起来,调用时第一个参数与enum一样(.Net的数组,集合或者Lua的Table);第二个参数可选,即拼接时的分隔符,默认是一个逗号(,).
- 技术细节:
示例中的XML解析完的Lua代码如下:
list =
{
['person'] =
{
{
['name'] = 'WAKU',
['age'] = 29,
['favourite_food'] =
{
['food'] =
{
'rice',
'chicken',
},
},
},
{
['name'] = 'Joey',
['age'] = 2,
['favourite_food'] =
{
['food'] =
{
'milk',
'juice',
'candy',
},
},
},
},
}
Lua参数文件在三种参数文件中效率最高(因为CSV和XML都需要先解析为Lua代码),而且也是最灵活的一个.
它的缺点是没有CSV和XML那么流行,并且使用它需要掌握一定的Lua知识.
使用Lua参数文件完全可以实现之前CSV和XML的示例(直接使用技术细节中的Lua代码做为参数文件即可)
而Lua参数文件有些东西却是CSV和XML做不到的.
示例:
模板文件:
b = ${b}
c = ${c}
a + b + c = ${a + b + c}
参数文件 "parameter.lua":
b = 2
c = 3