Custom Tags

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.

Callable Tags

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:

$ moya run fib.xml --breakpoint

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 fib:

<!-- 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 type of 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. The dst attribute is added to tag's signature automatically.

Setting the Application

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:

<sushi:get-specials dst="specials"/>

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:

<sushi:get-specials dst="specials" from="sushifinder"/>

Data Tags

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:

$ moya run datatag.xml

When you run this code, it will display a list containing two dictionaries which Moya has created from the (custom) <product> tags.

The main <macro> calls <get-data> which returns a list of the tag data extracted from the attributes of the two <product> tags.

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 "Kappa Maki":

<get-data-item tag="product" let:name="'Kappa Maki'" dst="kappa_maki" />
<echo obj="kappa_maki" />
NOTE Data tags do not contain executable code–Moya will ignore any data tags in a macro.

Conditional Data Tags

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.

Tag Namespaces

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:

http://ns.moyaproject.com/<organization>/<library name>/

Replace <organization> with the name of your orginization (or your own name) and <library name> with the long name of your library.