HFS: 模板宏: Difference between revisions

From rejetto wiki
Jump to navigation Jump to search
(Created page with "HFS 支持服务器端语言(指令),也叫做宏。这种语言在模板和事件脚本中的表现几乎相同。 '''请注意:''' 2.3 之前的版本不支持宏...")
 
(Correction of logic)
 
(One intermediate revision by the same user not shown)
Line 14: Line 14:
您可以很简单地区分占位符与宏:占位符由 %百分号% 包围,而宏由 <nowiki>{.带点的大括号.}</nowiki> 包围.
您可以很简单地区分占位符与宏:占位符由 %百分号% 包围,而宏由 <nowiki>{.带点的大括号.}</nowiki> 包围.


=== More on them ===
=== 更多 ===
How the macro will work depends on the parameters. The same macro can have a variety of functions based on its parameters.
宏如何工作取决于输入的参数。一个宏根据输入的参数可进行不同的操作。


The macro ''section'' will copy the content of a [section] of the template. The parameter in the macro specifies which section. So, you have one macro, ''section'', but it will expand to any content as you change the name of the section (as parameter). Let's say <tt><nowiki>{.section|style.}</nowiki></tt> and it will copy the content of section [style].  A shortcut for this is {.$style.}.
在一个模板中,宏 ''section'' 会复制位于该模板中所定义的一个 [] 的内容——而您应该添加一个具体参数,使它知道应该读取哪一个节。


=== Parameters ===
例如:<tt><nowiki>{.section|style.}</nowiki></tt> 将会读取节 [style] 的内容。该宏的快捷方式是 {.$style.}
After the macro name you specify parameters with "|" (pipes) and then the parameter: <tt><nowiki>{.name|parameter.}</nowiki></tt>.
If the macro requires more parameters, you just add more pipes: <tt><nowiki>{.name | parameter | another parameter | a third parameter.}</nowiki></tt>.


=== Readability ===
=== 参数 ===
You can also put macros inside macros, or nest them. However, this can often be a mess to read. To increase readability, you can:
在宏名称的后面,您可以添加管道字符“|”以添加参数,如:<tt><nowiki>{.宏名称|参数.}</nowiki></tt>.
* split the syntax over several lines, and [http://en.wikipedia.org/wiki/Indentation#Indentation_in_programming indent].
如果需要更多参数,只需添加更多管道字符:<tt><nowiki>{.宏名称 | 参数1 | 参数2 | 参数3.}</nowiki></tt>.
* add a final <tt>/macroname</tt> to know that you are closing just that macro, like <tt><nowiki>{.load|{.section|stuff /section.} /load.}</nowiki></tt>. The final <tt>/load</tt> is ignored by hfs, it's just for your convenience.


=== Quoting ===
=== 可读性 ===
Sometimes you don't want HFS to consider plain text as part of the macro syntax. There's a way to tell HFS to not process the text, and it is called ''quoting''.
宏是可以嵌套的。不过,这可能使得宏难以阅读。为了增加宏的可读性,您可以:
* 将每个宏排列到独立的行并[http://en.wikipedia.org/wiki/Indentation#Indentation_in_programming 缩进].
* 在一层宏的结尾添加: <tt>/宏名称</tt> 以提示自己关闭了一个宏。例如:<tt><nowiki>{.load|{.section|stuff /section.} /load.}</nowiki></tt>。最后的 <tt>/section</tt> 和 <tt>/load</tt> 会被 HFS 忽略——这只是为了您的便利。


To quote text you type <tt>{:</tt> then the text you want. To close the quoting just type <tt>:}</tt> .
=== 引用 ===
某些情况下,您可能不希望 HFS 将某段文本当作宏处理。有一种不让 HFS 处理这种文本的方式,叫做“引用”。


This capability is very useful with macros ''set'' and ''if''. You'll see later.
要引用一段文本,只需用带冒号的大括号包围: <tt>{:这是一段普通文本,并且{.这个宏不会被执行.}:}</tt>。


Sometimes you may need to use the pipe in plain text.  To tell HFS not to interpret it as a parameter, you can quote it.
同时引用还可以让宏 ''set'' 和 ''if'' 不提前执行其参数宏指令——您会在后面有所了解。
Example: <tt>{.add to log|print{:|:}pipes.}</tt> to have the pipe character in your log.  Additionally, you can use the command {.no pipe||.}


== Available commands ==
如果您需要在宏参数中使用管道字符而不分割参数,引用就是一种方法。
Refer to [[HFS: scripting commands|the full list]] for available commands.
例如: <tt>{.add to log|输出一个管道字符:{:|:}.}</tt>。如此您可在日志中使用管道字符。您也可以使用宏 ''no pipe'':<tt>{.no pipe||.}</tt>


== Execution order ==
== 可用的指令 ==
The current execution order of macros is: from inner to outer, from left to right.  Macros are like XHTML in that they cannot overlap.
HFS 预置了许多实用指令。请参阅[[HFS: 宏脚本命令大全|完整列表]]。


An example: <tt>{.A {.B.} {.C.}.} {.D.}</tt>. In this scenario, the order is B, C, A, D. HFS cannot process A until B and C are processed because it doesn't yet know what the macro {.A.} contains. 
== 执行次序 ==
如果宏是嵌套的,那么它们的执行次序为:从里到外,从左到右。宏的嵌套格式就像 XHTML,以保证其不重叠。


=== Problem and Solution ===
比如:<tt>{.A {.B.} {.C.}.} {.D.}</tt>。在此例中,宏的执行顺序为: B, C, A, D。HFS 在处理 B 与 C 前不能处理 A——因为 HFS 仍不知道 B C 的最终结果,而 B、C 的最终结果才是 A 要处理的。
All macros, except [[#Quoting|quoted ones]], are expanded, not matter what. For example, if you have the command {.if | A | B | C .}, then B and C will both be expanded, no matter what A is.


Since it is important to be able to select the execution of B or C based on the value of A, there's a workaround.
=== 问题与解决方案 ===
By quoting B and C, you stop them from being executed. After the ''if'' command chooses between B (''then'') and C (''else'') based on A, it removes the surrounding quoting markers, if any, executing the proper command.  However, if B and C contain only text and not macros, they do not need to be quoted.
除了[[#Quoting|被引用的宏]]之外,其他宏都会被扩展。不过,''if'' <tt>{.if | A | B | C .}</tt> 根据 A 来判断执行(扩展为) B 还是 C,但是如果 B 与 C 本身是宏,那么 B 与 C 总是会被执行。
Here's an example:
<tt><nowiki>{.if| %user% | {.append|file.txt|someone is in!.} .}</nowiki></tt>
As we stated before, this is not going to choose whether or not to execute the append command. ''Append'' will always be executed, because every macro is executed. The only way to stop this is to surround with quoting markers:
<tt><nowiki>{.if| %user% | {:{.append|file.txt|someone is in!.}:} .}</nowiki></tt>
By having quoted the ''append'', it will only be dequoted and then executed if ''%user%'' is not void. This is because the ''if'' automatically removes the appropriate quoting markers.


Normally you would have to remove the markers yourself, by using macro ''dequote''. But some macros (like ''if'') have this special behavior, for your convenience. The special macros with such behavior are: ''if'', ''set'', ''for'', ''for each'', ''switch'' and ''breadcrumbs''.  These allow you to use variables to change output.
因此我们需要''引用'' B 与 C。引用后,B 与 C 不会被提前执行,而是会在 ''if'' 判断符合条件后解除引用,然后被正确执行。
当然,如果 B 与 C 都是常文本,那么它们不必被引用。


=== From the beginning ===
比如:
Sometimes you need to be sure something gets done before every page is built and sent to the browser. In such case, you can put all your macros in the section '''[special:begin]'''.
<tt><nowiki>{.if| %user% | {.append|日志文件.txt|有用户登录了哦!.} .}</nowiki></tt>
如前文所描述,无论占位符 %user% 扩展为何,{.append.} 宏总是会被执行——这不是我们想要的。
 
然而,当我们将宏引用后:
<tt><nowiki>{.if| %user% | {:{.append|日志文件.txt|有用户登录了哦!.}:} .}</nowiki></tt>
仅当 %user% 扩展不为空时(值为真),{.append.} 宏才会被解除引用并执行。
 
在其他情况下,您需要使用宏 {.dequote.} 来解除引用。不过如 ''if'' 之类的特殊宏则不必。此类宏有:''if'', ''set'', ''for'', ''for each'', ''switch'' 和 ''breadcrumbs''。这允许您使用变量改变输出。
 
=== 预处理 ===
如果您需要在每份文件页面加载之前处理一些宏,那么您可以将宏放置在节 '''[special:begin]''' 下。如:
 
<pre><nowiki>
[special:begin] 
{.if| %user% | {:{.append|日志文件.txt|用户 %user% 登录了哦!.}:} .}
</nowiki></pre>

Latest revision as of 07:52, 27 October 2020

HFS 支持服务器端语言(指令),也叫做宏。这种语言在模板和事件脚本中的表现几乎相同。

请注意: 2.3 之前的版本不支持宏。

宏很强大,可以用于给 HFS 及其文件页面添加新的功能。

宏是如何工作的

与占位符的不同

您需要对模板如何工作有大概的了解。宏与占位符相似。输入的宏将在用户浏览页面时被替换为有实际意义的内容(我们称之“扩展”)。

占位符只代表一个名称,而宏有自己的功能及相应的参数。占位符只会被替换为文本(比如 %user% 替换为当前用户),而宏被用来在 HFS 服务器端进行指令操作(如 {.load.} 用以加载文件内容)。

您可以很简单地区分占位符与宏:占位符由 %百分号% 包围,而宏由 {.带点的大括号.} 包围.

更多

宏如何工作取决于输入的参数。一个宏根据输入的参数可进行不同的操作。

在一个模板中,宏 section 会复制位于该模板中所定义的一个 [节] 的内容——而您应该添加一个具体参数,使它知道应该读取哪一个节。

例如:{.section|style.} 将会读取节 [style] 的内容。该宏的快捷方式是 {.$style.}。

参数

在宏名称的后面,您可以添加管道字符“|”以添加参数,如:{.宏名称|参数.}. 如果需要更多参数,只需添加更多管道字符:{.宏名称 | 参数1 | 参数2 | 参数3.}.

可读性

宏是可以嵌套的。不过,这可能使得宏难以阅读。为了增加宏的可读性,您可以:

  • 将每个宏排列到独立的行并缩进.
  • 在一层宏的结尾添加: /宏名称 以提示自己关闭了一个宏。例如:{.load|{.section|stuff /section.} /load.}。最后的 /section/load 会被 HFS 忽略——这只是为了您的便利。

引用

某些情况下,您可能不希望 HFS 将某段文本当作宏处理。有一种不让 HFS 处理这种文本的方式,叫做“引用”。

要引用一段文本,只需用带冒号的大括号包围: {:这是一段普通文本,并且{.这个宏不会被执行.}:}

同时引用还可以让宏 setif 不提前执行其参数宏指令——您会在后面有所了解。

如果您需要在宏参数中使用管道字符而不分割参数,引用就是一种方法。 例如: {.add to log|输出一个管道字符:{:|:}.}。如此您可在日志中使用管道字符。您也可以使用宏 no pipe{.no pipe||.}

可用的指令

HFS 预置了许多实用指令。请参阅完整列表

执行次序

如果宏是嵌套的,那么它们的执行次序为:从里到外,从左到右。宏的嵌套格式就像 XHTML,以保证其不重叠。

比如:{.A {.B.} {.C.}.} {.D.}。在此例中,宏的执行顺序为: B, C, A, D。HFS 在处理 B 与 C 前不能处理 A——因为 HFS 仍不知道 B 与 C 的最终结果,而 B、C 的最终结果才是 A 要处理的。

问题与解决方案

除了被引用的宏之外,其他宏都会被扩展。不过,if{.if | A | B | C .} 根据 A 来判断执行(扩展为) B 还是 C,但是如果 B 与 C 本身是宏,那么 B 与 C 总是会被执行。

因此我们需要引用 B 与 C。引用后,B 与 C 不会被提前执行,而是会在 if 判断符合条件后解除引用,然后被正确执行。 当然,如果 B 与 C 都是常文本,那么它们不必被引用。

比如:

{.if| %user% | {.append|日志文件.txt|有用户登录了哦!.} .}

如前文所描述,无论占位符 %user% 扩展为何,{.append.} 宏总是会被执行——这不是我们想要的。

然而,当我们将宏引用后:

{.if| %user% | {:{.append|日志文件.txt|有用户登录了哦!.}:} .}

仅当 %user% 扩展不为空时(值为真),{.append.} 宏才会被解除引用并执行。

在其他情况下,您需要使用宏 {.dequote.} 来解除引用。不过如 if 之类的特殊宏则不必。此类宏有:if, set, for, for each, switchbreadcrumbs。这允许您使用变量改变输出。

预处理

如果您需要在每份文件页面加载之前处理一些宏,那么您可以将宏放置在节 [special:begin] 下。如:

[special:begin]  
{.if| %user% | {:{.append|日志文件.txt|用户 %user% 登录了哦!.}:} .}