Moya allows you to create custom tags, which may be used in the same way as the tags built in to Moya. Custom tags will help you catch errors and make your code more self-documenting.
The first type of custom tag we will look at is the callable tag which – in many cases – can replace a macro. First lets create a macro that we will replace with the custom tag. The following code calculates the first 20 Fibonacci numbers:
<!-- fib.xml --><moya xmlns:let="http://moyaproject.com/let"><macro docname="fib"><let fib="[0, 1]"/><repeat times="count - 2"><append value="fib[-1] + fib[-2]" src="fib" /></repeat><return value="fib" /></macro><macro docname="main"><call macro="fib" dst="fib_list" let:count="20"/><echo obj="fib_list" /></macro></moya>
This code should be somewhat familiar. If you save this code as
fib.xml, you can run it in the debugger with the following command:
If you step through this code you will see the main macro call fib, which returns a list and displays it in the terminal.
The following code will have the same output, but replaces the <macro> with a custom tag called
<!-- fib2.xml --><moya xmlns:let="http://moyaproject.com/let"><tag name="fib"><doc>Calculate the Fibonacci sequence</doc><signature><attribute name="count" type="integer" /></signature><let fib="[0, 1]"/><repeat times="count - 2"><append value="fib[-1] + fib[-2]" src="fib" /></repeat><return value="fib" /></tag><macro docname="main"><fib count="20" dst="fib_list" /><echo obj="fib_list" /></macro></moya>
The <tag> tag creates the custom tag, it contains a <signature> tag which tells Moya we are going to define the tag's attributes (known as the the tag's signature). In the example, the signature consists of a single <attribute> tag which defines an attribute called
name with a
integer. The type of an attribute tells Moya how the attribute should be processed. Moya will raise a helpful error, if the attribute isn't in the correct format (if you enter text for a integer attribute, for example).
The rest of the code inside the <tag> is the same as the macro. Tags may also return a value which will be stored in the location specified by
dst attribute is added to tag's signature automatically.
When you call a tag in a project, Moya needs to know which application contains the tag. If there is only one application installed for the library that defines the tag then Moya can detect the application automatically. Otherwise, you will need to specify the
from attribute in the calling tag.
For example, let's say we have a library called
sushifinder.shop installed as application
sushifinder. It defines a tag called
get-specials which gets a list of products on special. We might call it like this:
This is fine as long as
sushifinder.shop was installed just once. If we have installed it twice, we would need to specify the application when we call the tag. Here's an example:
Moya can create data tags which are a way of specifying structured data that may be difficult to express in the form of settings. A data tag may appear anywhere in your project (including in other libraries), and may be queried with <get-data>. Let's look at en example:
<!-- datatag.xml --><moya><data-tag name="product"><doc>A sushi product</doc><signature><attribute name="name" required="yes"/><attribute name="description" required="no" default=""/></signature></data-tag><product name="Maguro Nigiri" description="A lean cut of tuna" /><product name="Kappa Maki" description="Cucumber" /><macro docname="main"><get-data tag="product" dst="products" /><echo obj="products" /></macro></moya>
You can run the above code with the following:
When you run this code, it will display a list containing two dictionaries which Moya has created from the (custom)
You can also retrieve data from a single data tag with <get-data-item>, which matches a single data tag based on the LET parameters you supply to it. Here's how you would use <get-data-item> to get the data from the
product tag with a name of
Although data tags aren't executable, they do have an
if attribute. This condition is checked when you get the data. If a data tag contains in
if attribute which evaluates to False, the tag is omitted from the data. Here's an example:
<product name="Maguro Nigiri" description="A lean cut of tuna" if=".settings.tuna-in-stock.bool"/><product name="Kappa Maki" description="Cucumber" />
A call to <get-data> now may return one item or two, depending on the value of
tuna-in-stock in the settings.
When creating custom tags in a project, they are defined in the XML namespace specified in the library's lib.ini. Alternatively you can specify the namespace for the tag with the
ns attribute of <tag>. Moya doesn't place any restrictions on the namespace you use, but it is advisable to use a namespace from a domain you own. If you don't have a domain name, then you can use the following:
<organization> with the name of your orginization (or your own name) and
<library name> with the long name of your library.