HFS: Template macros: Difference between revisions

From rejetto wiki
Jump to navigation Jump to search
(→‎Problem and Solution: username being "true" can be hard to understand at this stage)
 
(171 intermediate revisions by 11 users not shown)
Line 1: Line 1:
'''Please note:''' Macros are not available in current version 2.2, but they will in 2.3, and you can experiment with it using beta versions.
Server-side scripting is possible through commands, also known as macros. These commands are mostly the same for templates and for hfs.events.
 
'''Please note:''' Macros are currently not available in 2.2f, but they will be in 2.3. You can experiment with them using [http://www.rejetto.com/forum/index.php/board,33.0.html beta versions].
 
Macros are very powerful and can be used to add new functionality to HFS.


== How macros work ==
== How macros work ==


=== Differences with symbols ===
=== Differences with symbols ===
Macros are similar to symbols. They are something you type in the template and is substituted (we say ''expands to'') with meaning content when the user watch the page.
You are supposed to already know [[HFS: Template#How_templates_work|how templates work]]. Macros are similar to symbols. They are something you type in the template that gets substituted (we say ''expands to'') with meaningful content when the user watch the page.


While symbols are just a name, macros have a name and optionally parameters.
While symbols are just a name, macros have a name and optionally parameters.  Additionally, while symbols only expand to text (such as %user% or %url%), macros can be used to perform server-side commands (such as {.save.} and {.load.} ).  


You can tell symbols by macros because symbols are surrounded by %percent% signs, macros are surrounded by <nowiki>{{double braces}}</nowiki>.
You can tell symbols from macros easily: symbols are surrounded by %percent% signs, while macros are surrounded by <nowiki>{.dotted braces.}</nowiki>.


=== More on them ===
=== More on them ===
How the macro will work depends on the parameters. The same macro has a different effect when the parameter change.
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. But which section is specified by the parameters. 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].
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.}.


=== Parameters ===
=== Parameters ===
After the name of the macro you can put a character "|" (its name is pipe) and then a parameter: <tt><nowiki>{{name|parameter}}</nowiki></tt>.
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, like 2 or 3, you just add more pipes: <tt><nowiki>{{name | parameter | another parameter | don't look at me}}</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 ===
=== Readability ===
Having macro in macro, nested, can be a mess to read. To increase readability you can
You can also put macros inside macros, or nest them.  However, this can often be a mess to read. To increase readability, you can:
* split the syntax over several lines, and [http://en.wikipedia.org/wiki/Indentation#Indentation_in_programming indent].
* split the syntax over several lines, and [http://en.wikipedia.org/wiki/Indentation#Indentation_in_programming indent].
* add a final <tt>/macroname</tt> to know that you are closing just that macro, like <tt><nowiki>{{load | something /load}}</nowiki></tt>. The final <tt>/load</tt> is ignored by hfs, it's just for your convenience.
* 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 ===
=== Quoting ===
Sometimes you don't want HFS to consider a text as part of the macros syntax. There's a way to tell HFS to leave untouched the text, and it is called ''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''.
 
To quote text you type <tt>{:</tt> then the text you want. To close the quoting just type <tt>:}</tt> .
 
This capability is very useful with macros ''set'' and ''if''. You'll see later.
 
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.
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.
 
== 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.


To quote a text you type <tt><nowiki>{{quote</nowiki></tt> followed by a space, and all the text you want. To close the quoting you type <tt><nowiki>quote}}</nowiki></tt> . You can consider ''quote'' a special macro with no parameters.
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.


== Full list ==
=== Problem and Solution ===
With letters we are denoting parameters, and their meaning is explained immediately after.
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.
=== Logic ===
; if | A | B | C
: if A is true, then it expands to B, else it expands to C. When it expands to B, C is just discarded, and the vice versa. C is optional.
: How you tell A is true? A is true if it is not empty and not just a zero. So if A is "hi there!", then it is true.
; if not | A | B | C : same as ''if'', but the logic is inverted. When A is true it expands to C and vice versa.
; not | A : true if A is not true
; and | A | B : true if both A and B are true
; or | A | B : true if any of A or B are true
; xor | A | B : true if A is true while B is false, or the opposite
; switch | A | B | C | D | E | F ...
: this is rather complex for non-programmers. You can learn how a switch statement is supposed to work [http://en.wikipedia.org/wiki/Switch_statement#Examples from Wikipedia]. When you know how a ''switch'' works, then you will understand this schema that will make you understand how the parameters of this macro work
<pre><nowiki>
switch(A) {
  case C: return D;
  case E: return F;
  ...
}
</nowiki></pre>
: The B is a separator string for C. Let's be clearer: if you want to specify several cases in C, all of them returning D, then you can specify them separating with B.
: As you can see C and D are paired, as E and F, eventually G and H, and so on. If at the end of this list of pairs, a single unpaired parameter is found, then it is used as the else/default case, when all other pairs have failed.
: Let me translated the first example of Wikipedia using the macro
<pre><nowiki>
{{switch|%n%|,|
  0|you typed zero|
  3,5,7|%n% is a prime number|
  4,6,8|%n% is an even number|
  2|%n% is a prime and even number|
  1,9|%n% is a perfect square|
  Only single-digit numbers are allowed
}}
</nowiki></pre>


=== Data getting ===
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.
; section | A
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.
: A is the name of the [section] you want to include. Note: till build #160 it was case sensitive.
Here's an example:
; get | A
<tt><nowiki>{.if| %user% | {.append|file.txt|someone is in!.} .}</nowiki></tt>
: where A is the name of a value you are interested in, like to know if an option is enabled or not.
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:
: This is a list of supported values for A:
<tt><nowiki>{.if| %user% | {:{.append|file.txt|someone is in!.}:} .}</nowiki></tt>
:; can upload : true if in the current folder the user is allowed to upload files
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.
:; can recur : true if the option ''Recursive listing'' is enabled
:; can archive : true if the current folder is archivable
; urlvar | A : url variable. Let's say in the url you see <tt>?sort=s</tt> and you want to know that '''s''', just use the macro urlvar|sort.
; header | A : get any value from the HTTP request header. A is the name of the header field. This is something mostly for techies. Don't fret if you don't even know what the header is.
; load | A : you'll love this one. You can specify A as a file name, or as a URL. It will load and expand to it. The file or URL you specify must be accessible from the server machine. A can be <tt>C:\windows\win.ini</tt> or also <tt><nowiki>http://another_hfs_in_lan/the_file_i_want.txt</nowiki></tt>.


=== Data manipulation ===
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.
; substring | A | B | C : cut C from A to B, with B not included. Example: <tt><nowiki>{{substring|(|belong|you (are) belong to us}}</nowiki></tt> will be <tt>(are)</tt>.
: If A is not specified, C is taken from the start. If B is not specified, C is taken to the end.
; cut | A | B | C : cut C from position A, for B characters. The difference with macro ''substring'' is that here you specify where to cut by numeric positions. Example: with A=2 and B=3 and C=''abcdef'' you will get ''bcd'' because it is from character 2 and for a length of 3.
: If you don't specify A, it defaults to 1. If you don't specify B, it defaults to the length of C.
: If A is negative, then you are counting backward from the end of C. If B is negative, then you are considering the length of C minus the amount of B.
; repeat | A | B : repeat B for A times. Example: for A=5 and B=+ the result is +++++
; upper | A : returns A with all letters uppercased. Example: for A=Hello the result is HELLO
; lower | A : returns A with all letters lowercased. Example: for A=Hello the result is hello
; trim | A : returns A with any leading and trailing space removed
; replace | A | B | C : returns C with every A replaced with B


=== Others ===
=== From the beginning ===
; comment | A : this is just discarded. It's for your convenience, to put a comment in the template. HTML comments are readable by visitors if they use ''show html source'' in their browser. Using this macro you will have comments that will never leave your server.
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]'''.
; length | A : if A is 5 characters length, it expands to 5.
; match | A | B : it is true if the content B is matched by [[HFS: File masks|the mask]] A.
; match address | A | B : just like the macro ''match'', but the mask supports ip ranges like 10.0.0.1-10.0.0.25
; random | A | B | C | ... : it expands to any of the parameters, randomly
; is substring | A | B : it is true if A is contained in B

Latest revision as of 12:18, 20 September 2011

Server-side scripting is possible through commands, also known as macros. These commands are mostly the same for templates and for hfs.events.

Please note: Macros are currently not available in 2.2f, but they will be in 2.3. You can experiment with them using beta versions.

Macros are very powerful and can be used to add new functionality to HFS.

How macros work

Differences with symbols

You are supposed to already know how templates work. Macros are similar to symbols. They are something you type in the template that gets substituted (we say expands to) with meaningful content when the user watch the page.

While symbols are just a name, macros have a name and optionally parameters. Additionally, while symbols only expand to text (such as %user% or %url%), macros can be used to perform server-side commands (such as {.save.} and {.load.} ).

You can tell symbols from macros easily: symbols are surrounded by %percent% signs, while macros are surrounded by {.dotted braces.}.

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 {.section|style.} and it will copy the content of section [style]. A shortcut for this is {.$style.}.

Parameters

After the macro name you specify parameters with "|" (pipes) and then the parameter: {.name|parameter.}. If the macro requires more parameters, you just add more pipes: {.name | parameter | another parameter | a third parameter.}.

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:

  • split the syntax over several lines, and indent.
  • add a final /macroname to know that you are closing just that macro, like {.load|{.section|stuff /section.} /load.}. The final /load 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.

To quote text you type {: then the text you want. To close the quoting just type :} .

This capability is very useful with macros set and if. You'll see later.

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. Example: {.add to log|print{:|:}pipes.} to have the pipe character in your log. Additionally, you can use the command {.no pipe||.}

Available commands

Refer to the full list for available commands.

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.

An example: {.A {.B.} {.C.}.} {.D.}. 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.

Problem and Solution

All macros, except 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. Here's an example:

{.if| %user% | {.append|file.txt|someone is in!.} .}

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:

{.if| %user% | {:{.append|file.txt|someone is in!.}:} .}

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.

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].