Yonni na Tag Development

Tags in 42 include a custom scripting language called Yonni na or yna for short. You are free to pronunce this how you want. I personally say "why en ay", but I've heard it pronunced "yonna" and even "nya" before.

yna is a very powerful mechamism, however it can be intimidating to write or read scripts for.
It is usually a good idea to start simple and work up from there, and when you start writing larger scope tags, Make liberal use of {func}. It will save a lot of headache with nested elements.

If you instead want to write code using Notepad++, you can install and edit this shader.


Limitations

There are a few limitations to tags to prevent them from having errors or infinite loops, and an additional one limiting the size of tags for memory considerations.

Tag size limits

Tags have a limit of 32,000 characters (~31.5kB). To upload tags this long, you should create a text file with the .yna extension and upload it with the create call as the caption.

Tags consisting of 5 or fewer yna objects (e.g. 1 or 2 {choose} objects) have a considerably higher limit of 256,000 characters (~250kB).
Patreon supporters also get this higher limit on all their tags.

Stack height

yna evaluation objects work on a stack. While one object is processing its children, the next object is appended to the stack.

When the stack exceeds 32 objects, a nesting depth reached error will be returned.

Debug limit

Even if you are not using debugging, 42 has a hard limit of how much she can execute in a single tag.
This limit is ~32k lines of debug log. Each object adds between 2 and 6 lines to the log, though some may add more.
The debug file also shows the stack height down the left hand side by the number of vertical lines, as well as how long the tag took to execute (note, this will be slightly faster without debug.)

When this limit is reached, the tag is returned in its unfinished state, no errors are thrown.

Call limit

Assuming your tag calls are within the other limits too, there is a hard cap to how many times you can use the {call} function.
Right now, there are 3 distinct limits

  • Trying to call the same tag multiple times will trigger a already used error.
  • When the call command has been used 3 times, any further usage will return a out of calls error.
  • If you do not have permission to call a tag, you will instead get a no access error.

Coding Tools

There are several important tools and structures that are used in yna tags.

"
Descriptions

42 defines two constructs for adding a description to your tag.

Long Description

This one is used in a tag's info page:

{!!description <Description content here>!}
 

Short Description

This one is only used on generic tags, but is absolutely required to have a generic tag approved.
This should be no longer than 8 to 10 words.

{!!descshort <Description content here>!}

Comments

42 provides a way to add comments to yna code or to comment code out completely.
She will not close a comment until all internal brackets are matched up.

{!<Comment content here>!}

Some users have set up their shaders to display commented content anything between {! and !}. While this is not strictly neccissary, it is still a good gesture if you are intending your code to be read by other people.
This style however is used on this site to aid with highlighting.

Escaping

42 has 2 ways of escaping objects and special characters.

To escape individual characters, you can precede the character by a backslash.
\{, \}, \; and \\

To escape entire objects, you can insert a > inside the opening brace.
e.g. {>choose:foo;bar;baz;}


Format Objects

Format objects are one of the 2 kinds of objects in 42. These directly insert a value into the tag without doing anything special.
They are notable by the fact they do not end with a semicolon.

New format objects can be created using set, func and save
Here is a list of default format objects:

  • {tag} The name of the tag
  • {me} The Member object of the tag's creator*
  • {meid} The ID of the tag's creator
  • {caller} The Member object of the caller*
  • {callerid} The ID of the caller
  • {channel} The Channel object of the current channel**
  • {channelid} The ID of the channel
  • {server} The Guild object of the server***
  • {serverid} The ID of the server
  • {time} The DateTime that the tag was called****
  • {uses} The number of times the tag has been called
  • {arglen} The number of args
  • {arg1} {arg2} ... The individual numbered args (1 indexed)
  • {args} All the args as a single string
  • {mentionlen} The number of user mentions
  • {mention1} ... The individual Member objects* (1 indexed)
  • {newrep} How {rep} will work
  • {generic} Whether the tag is generic
  • {base} true until {call} is used, then false

*Member docs

**Channel docs

***Guild docs

****DateTime templates

You can access the different attributes of each object by using Python's attribute access syntax, but in short...

To access the name of a Member, Channel or Server
{me.name} -> squaswin

To pad a string
{arg1:<10} -> Hello     
{arg2:^10} ->   World!  

To print a date
{time:%Y-%m-%d} -> 2017-05-31

Exceptions
  • missing semicolon General formatting exception. This is usually caused by forgetting the semicolon from an evaluation object, however, it may also be caused by a broken template.
  • does not have x General attribute exception. Usually caused by trying to access a member variable that does not exist.
  • bad slice General type exception. Usually caused by using invalid slices
  • out of range General index exception. Usually caused by accessing an array index that doesn't exist (e.g. {caller.roles[501]})

Evaluation Objects

Evaluation objects are the other kind of objects in yna, and they are much more powerful than format objects.
These objects generally do a lot of various things, such as flow control, variable storage, and recursion.

Evaluation objects are differentiated by the training semicolon inside the closing brace.

Keys

Keys are special shortcuts for saving the output of some functions.
While this is a holdover from yna4, it is still useful to save something without a set function.
For example, {chooseanimal:cat;dog;horse;} will save whatever it chooses to {chooseanimal}

Exceptions
  • mismatched brackets Failed to find a closing bracket for an object.

Case Functions

Case functions change the case of a block of evaluated content, either to UPPER, lower or Title case.

Syntax
{upper:<content>;}
{lower:<content>;}
{title:<content>;}
Arguments
  • content The content to edit.
Exceptions
  • no content No content was given.

Length Function

Gets the length of the given evaluated content.

Syntax
{len:<content>;}
Arguments
  • content The content to measure.
Exceptions
  • no content No content was given.

Slice Function

Slices a piece of evaluated content.

Syntax
{slice:<c>;<content>;}
Returns a specific 0-indexed character
{slice:[<b=None>],[<e=None>][,<s=1>];<content>;}
Returns a 0-indexed, top-exclusive substring.
Arguments
  • content The content to slice.
  • c A specific character index.
  • b The beginning of a slice.
  • e The end value of a slice.
  • s The step of a slice.
Exceptions
  • no args No arguments were given.
  • bad content Either not enough or too many args were given.
  • too many nums More than 3 values were given for the slice.
  • bad index String index was out of range.
  • non int index Values could not be casted to int.
  • zero step A step value of 0 was given.

Time Function

Gets the current time and either stores or posts it.
Template options

Syntax
{time[<k>][:<offset=0>[;<template=%H:%M>]];}
Posts the time with a given template.
{time<k>:<offset>;;}
Stores the DateTime object without posting it.
Arguments
  • k A key to store the DateTime object under.
  • offset The integer hours offest to add to the time.
  • template The template to match the time into. If omitted and a key is given, then no output will be posted.
Exceptions
  • invalid offset The offset given could not be casted to int.
  • invalid format The template given was invalid.

Parse Function

Converts characters into a string into a format that can be used in URLs.

Syntax
{parse:<quote>;}
Arguments
  • quote The content to parse.
Exceptions
  • no content No content was given.

Choose Function

Chooses a random element from a given list.

Syntax
{choose[<k>]:<option>;<option>[;<...>];}
Arguments
  • option One of the choices.
  • ... Options list can extend indefinately.
Exceptions
  • no options No options were given.

Weighted Choose Function

Chooses an element with regards to given weightings.

Syntax
{wchoose[<k>]:<option1>;<weight1>;<option2>;<weight2>[;<...>;<...>];}
Arguments
  • option The available choices.
  • weight The corresponding weightings for each option.
  • ... Options list can extend indefinately.
Exceptions
  • no options No options were given
  • mismatched weightings Not every option could be matched with a weighting.
  • invalid weight A weighting could not be casted to int or float.

Random User Function

Chooses a random member from the server. Can choose any member, not just online/active/in the channel members.

Syntax
{user[:<attrs=None>];}
Posts the content directly in place.
{user<k>;}
Swallows the output and only stores the Member object.
Arguments
  • attrs Attribute path for the member. Equal to {_.attrs}
  • k Key value to store the member with.
Exceptions
  • type clash User brackets cannot have a key and an attribute path.
  • too many args More than 1 argument was given.
  • has no attrs The attribute path is not valid.

Nameof Function

Fetches a members name from their ID.
This can be paired with {member} to get an object.

Syntax
{nameof:<ID>[;<attrs=None>];}
Arguments
  • ID ID to search for.
  • attrs Attribute path for the member. Equal to {_.attrs}
Exceptions
  • no id No ID was given.
  • too many args More than 1 arg was given.
  • not found The ID did not match a user on the server.
  • has no attrs The attribute path is not valid.

Random Number Function

Gets a random number between a given range.

Syntax
{num[<k>][:[<min=0>];<max=100>[;<step=1>]];}
Arguments
  • k Key value to store the number with.
  • min The inclusive minimum.
  • max The inclusive maximum.
  • step The step value.
Exceptions
  • no args Args were expected, but none were given. Caused by {num:;}
  • invalid args Could not cast args to int.
  • invalid range Given range was negative or empty, or step was 0.

Variable Storing

Variables can be stored using the set command and then recalled like any other Format Object.
All objects saved this way are strings.

Example: calling {set:foo;Hello World;} means that you can now use {foo}

Syntax
{set:<key>;<value>;}
Sets a variable's content
{set:<key>;}
Deletes an existing variable
Arguments
  • key The key value (variable name.)
  • value The evaluated contents to store.
Exceptions
  • no args No args were given.
  • invalid args Either too many or not enough args were given.
  • invalid key The key value is not a valid identifier name.

Function Declaration

Functions are declared using the func command. This is similar to the set command but does not evaluate the contents.
This means that when you recall it, it executes the code again instead of just regurgitating the results.

You can use recursion this way, but if you start an infinite loop, I will find you and kill you she will eventually reach a point and stop executing.

While not strictly required, some syntax highlighters will mark functions starting with f_. This makes it easier to see what is a function. e.g. {f_recurse}.

Syntax
{func:<key>;<code>;}
Arguments
  • key The key value (function name.)
  • code The script to store.
Exceptions
  • no args No args were given.
  • invalid args Either too many or not enough args were given.
  • invalid key The key value is not a valid identifier name.

You have the option of passing "Template Arguments" into your function calls.
These are a comma seperated list that are placed in the template of the function call.

{f_myfunc:foo,bar,baz;}

The above code will run f_myfunc with these additional format objects.
Note: Once the function call has completed, these format objects will be deleted.

  • {targs} The full template string ("foo,bar,baz")
  • {ta1} The first arg ("foo")
  • {ta2} The second arg ("bar")
  • {ta3} The third arg ("baz")
  • {talen} The number of template args (3)

Member Fetch Function

Fetches a Member object from the server and stores it to a variable.
Fetches a member by either name, nickname or Discord Tag.

Syntax
{member:<key>;<name>;}
Arguments
  • key The key value (variable name.)
  • name The username, nickname or Discord Tag of the target.
Exceptions
  • no args No args were given.
  • no query No name was given.
  • invalid key The key value is not a valid identifier name.
  • not found There was no user with the given name on the server.

When Function

Conditionals, similar to if statements.
Unlike the old version of yna, only the path chosen will be executed instead of the when block deciding just what output to post.

Syntax
{when:<a>;<op>;<b>;<true>[;<false=None>];}
Arguments
  • a b The 2 arguments.
  • op The operation.
  • true Code to execute if true.
  • false Code to execute if false.
Operations
  • eq Checks that a and b are the same.
  • ne Checks that a and b are different.
  • lt Checks that a is strictly less than b.
  • le Checks that a is less than or equal to b.
  • gt Checks that a is strictly greater than b.
  • ge Checks that a is greater than or equal to b.
  • in Checks that a is a substring of b.
  • in Checks that a matches an element in the comma seperated list in b.
  • is Checks that a is of the type defined in b
    • word Checks if a is a single word.
    • letter Checks if a is a single letter.
    • number Checks if a is castable to int.
    • decimal Checks if a is castable to float.
    • error Checks if a is a yna exception.
    • /regex/ Checks if a matches the regex.
Exceptions
  • invalid args Either too few or too many args were given.
  • invalid op The operation could not be recognised.
  • args must be numbers Comparison operators were attempted between non-number inputs
  • args do not support in A generic type error occured while performing in checks.
  • invalid type name The type name in is could not be recognised.
  • invalid regex The regex could not be compiled

Loop Function

Flow control, similar to "for" loops.
Whilst inside the loop, your current loopcount will be stored in the {iter} variable. Note: This will be deleted when a loop is exited.
When loops are nested, only the current loop value is stored in {iter}. Once the loop finishes, the loop value of the outside loop will be copied back again.
If you want to access the loop variable inside nested loops, you will need to {set} it to a new variable.

Syntax
{loop:[<b=1>,]<e>[,<s=1>;<content>;}
Arguments
  • b The inclusive loop beginning.
  • e The inclusive loop ending.
  • s The loop step.
  • content The content to loop through.
Exceptions
  • no args No arguments were given.
  • invalid args Either too few or too many args were given.
  • invalid range invalid values for the range of the loop.

Rep Function

Works like a find and replace function in a text editor.
This command has 2 different syntaxes. The old and depreciated one and a new one.
Switching between the two is done by setting the {newrep} variable.

Syntax
{rep:<var>;<in>;<with>;}
Old syntax. This is the one used by default.
{rep:<var>;<with>;<in>;}
New syntax. To enable this, call {set:newrep;true;}.
Arguments
  • var The search variable. This can be a regex string by wrapping it in /s
  • with The evaluated replace value.
  • in The string to search and replace.
Exceptions
  • no args No arguments were given.
  • invalid args Too few or too many args were given.

Split Function

Splits a string based on a given separator, generating a set of variables with the split values.
Each element of the output will be saved in a variable with a given prefix, and counting up from 1.
This function returns the total number of elements (which is by definition the highest valid output index.)

Syntax
{split:<var>;<content>[;<sep=,>];}
Arguments
  • var The output variable prefix. Must be a valid variable name.
  • content The content to split.
  • sep The string to split on.
Exceptions
  • no args No arguments were given.
  • invalid args Too few or too many args were given.
  • invalid key Output parameter is not a valid valid name.

yna Arithmetic

All arithmetic is done through a single function.
Each method takes a specific number of arguments and has a specific resolution.
The resolution is either int or float, the args are either exactly 1, exactly 2 or 2 and more.

You can use aliases, e.e. add and +, not and ~

Syntax
{math:<op>;<arg1>[[;<arg2>];<...>];}
Arguments
  • op The operator to use.
  • arg1 The first arg.
  • arg2 The second arg. Omitted in = 1 operators.
  • ... Any aditional args. Only used in ≥ 2 operators.
Operators
OperationAliasesArgumentsResolutionDescription
add + ≥ 2floatAddition
sub - = 2 floatSubtraction
mul * ≥ 2floatMultiplication
div /, /f= 2 floatDivision
idiv // = 2 int Integer Division
mod % = 2 int Modulo Function
pow ** = 2 floatExponent
and &≥ 2int Bitwise AND
or | ≥ 2int Bitwise OR
xor ^ = 2 int Bitwise XOR
not ~ = 1 int Bitwise NOT
max ≥ 2floatMaximum Number
min ≥ 2floatMinimum Number
floor = 1 floatFloor Function
ceil = 1 floatCeiling Function
round = 1 floatRound Function
Exceptions
  • no args No arguments were given.
  • unknon op The operator was not recognised.
  • invalid args The number of args doesn't match the operator.
  • non-int args, non-float args The args could not be cast properly.
  • inf, -inf The result is too large or small.
  • divide by 0 Attempted to divide by 0.

Oneline Function

This strips all the newlines and leading whitespace from code, allowing it to be formatted in a readable way without leaving a lot of newlines.
A backslash at the end of a line will make the newline remain, but not preserve the next line's leading whitespace.
A "\n" anywhere inside the block will insert a newline.

Using a empty comment {!} will force the start of the line, allowing for leading whitespace.

Syntax
{oneline:<content>;}
Arguments
  • content The content to condense.
Exceptions
  • no content No content was given.

Void Function

This evaluates its internal code and then swallows the output.
The output will be printed to the debug log, accessable through +tag debug

Syntax
{void:<content>;}
Arguments
  • content The content to evaluate.
Exceptions
  • This code returns no error messages.

Saving States Between Calls

Tags have access to a set of state variables. These are similar to variables created using {set}, but with 1 very big difference:
State variables aren't deleted when a tag call ends!

This allows you to create tags that can remember things, like when they were called, or who called them, or things like that.

There is a small list of restrictions with state variables however:

  • State variables are strictly per tag. Cloning, Syncing or otherwise copying tags will not preserve its state.
  • Each tag can only support at most 16 state variables.
  • State variable names must be at most 32 charcters and cannot conflict with any formatting objects.
  • State variable content can be at most 256 characters.

There is only 1 command that you can use to save variables to the state.

State Saving

This function takes an evaluated value and saves it to the tags state dictionary.

While not strictly required, some syntax highlighters will mark functions starting with s_. This makes it easier to see what is a state variable. e.g. {s_lastcall}.

Syntax
{save:<name>;<content>;}
Creates a new state variable
{save:<name>;}
Deletes an existing state variable
Arguments
  • name The state variable name.
  • content The content to store.
Exceptions
  • no args No args were given.
  • invalid args Either too many or not enough args were given.
  • invalid key The key value is not a valid identifier name.
  • too many variables There are already 16 state variables.
  • invalid name A reserved key was used or the name was too long.
  • content too long The content was too long.

Initialising States

You can set up some initial state variables when you create a tag. These defaults are actually stored and used when a tag is cloned or reset.

Syntax
{init} <initialisation code> {endinit}

42 will read this as its own short script and then immediately comment the entire section out to prevent it being shown in a regular call.
init and endinit are not yna objects. They are more akin to preprocessor instructions.
In the same vein, 42 does not care if you have commented the init block already. She will still find it and execute it when the tag is created.


Calling Multiple Tags at Once

Tags have the ability to import other tags within some reason.

  • You cannot call the same tag more than once.
  • You cannot call other user's tags unless they are marked as a library.
  • You can only call 3 tags.

If you wish to create a library tag for anyone to use, you must mark it as such.
Add this line to your code to mark a tag as library:
{!!library}

Calling Tags

This function is how you import tags. The content of the tag will replace this call in its relative position to your script.

Syntax
{call:&lt;tagname&gt;;}
Arguments
  • tagname The tag to call.
Exceptions
  • no tag You did not supply a tag name.
  • not found The tag was not found.
  • no access You do not own the tag and it is not public.
  • already used The tag has already been imported.
  • out of calls You have already used call 3 times.

Posting Rich Embeds

If you are a Supporter or the server owner, you can create tags that post rich embeds as well as text.
Note that when you stop supporting, your embed tags will no longer embed. Also, this is checked off the tag's owner, not off of {meid}.

Editing the Embed

Editing is done using the {embed} object. You cannot unset an element once you have set it though.

Syntax
{embed:&lt;attribute&gt;;&lt;args...&gt;;}
Arguments
  • attribute The part of the embed to edit.
  • args... The list of args for that attribute.
Attributes
Author
{embed:author;&lt;name&gt;;}
{embed:author;name;&lt;name&gt;;}
{embed:author;url;&lt;url&gt;;}
{embed:author;icon_url;&lt;url&gt;;}
{embed:author;&lt;name&gt;;&lt;url&gt;;&lt;icon_url&gt;;}
Title
{embed:title;&lt;title&gt;;}
{embed:url;&lt;title-url&gt;;}
Description
{embed:description;&lt;content&gt;;}
Footer
{embed:footer;&lt;text&gt;;}
{embed:footer;text;&lt;text&gt;;}
{embed:footer;icon_url;&lt;url&gt;;}
{embed:footer;&lt;text&gt;;&lt;icon_url&gt;;}
Images
{embed:thumbnail;&lt;url&gt;;}
{embed:image;&lt;url&gt;;}
Colour
{embed:colour;&lt;0xRRGGBB&gt;;}
{embed:colour;&lt;red&gt;;&lt;green&gt;;&lt;blue&gt;;}
Note: red, green and blue are either ints from 0 to 255 or floats from 0 to 1.
Fields
{embed:field;&lt;label&gt;;&lt;content&gt;;}
Timestamp
{embed:timestamp;&lt;args&gt;;}
Note: args is 1 to 6 numbers seperated by non-numbers in order Y, M, D, H, M, S.
If fewer than 6 args are given, unset values are set to 0. {embed:timestamp;;&lt;time;&gt;;
When the timestamp starts with a ;, the date will be set to UTC Today and only the time is defined.
Exceptions
  • no args You did not specify an attribute,
  • invalid field The embed field was not valid
  • attrib invalid args The field was passed invalid args. See debug for details.
  • no author name Author requires a name to be specified
  • invalid timestamp Could not parse timestamp, either invalid values (33 days) or too many values (9 args).
  • invalid colour Could not map colour values into a colour.

Example Programs

Here is a list of relatively simple tags created by either myself or the community.
If you want your tag here, let me know over on Kiwi Hangout.
Credit will be given where it is due.


Return to top.