Skip to content

Latest commit

 

History

History
132 lines (113 loc) · 8.33 KB

documentation.md

File metadata and controls

132 lines (113 loc) · 8.33 KB

scripting language documentation

The Mkvsynth scripting language is pretty simple and easy to learn. Those who are used to Avisynth scripting may have to unlearn a few habits, but overall the two languages are fairly similar (e.g. neither has a real name!).

The main differences are:

Property Avisynth Mkvsynth
Terminator Newline (use \ for line continuation) Semicolon
Case sensitive No Yes
Types int, float, bool, string, clip, val num, bool, string, clip
Functions Function foo(int i, bool "b") {... function foo(num n, :bool b) {...
Function calls foo(arg1, arg2 + 3, optArg=val) foo arg1 (arg2 + 3) optArg:val
Chaining clip.Foo().Bar().Baz() clip -> Foo -> Bar -> Baz
Default radius = Default(radius, 2) default radius: 2
Plugins Can clobber existing function names No namespace conflicts
if/else Not supported Supported
Ternary cond ? foo : bar cond ? foo ¦ bar

Full specification

types

type literal description
num 3, 1.5, .1 A number. Internally represented as a double.
bool True, False A boolean. Case-sensitive.
string "Hello", "World" A string. Most escape sequences supported.
clip N/A A video. Actually a pointer to a video file.

keywords

keyword description example
if, else Conditional statement if (x == 1) print "yes"; else print "no";
function Function definition function foo(num x) { ...
default Specify default value default radius = 2;
import Import a plugin import libfoo;
return Function return value return result * 3;
otherwise Ternary syntactic sugar y = x == 1 ? "yes" ¦ otherwise ? "no";

built-in functions

function description example
print Generalized print function print 12 False "hi"
assert Assertion statement assert (frames > 2) "not enough frames"
show Convert to string show 12.3 == "12.3"
read Convert string to num read "12.3" == 12.3

operators

operator description
+,-,*,/,^,% Standard binary arithmetic operators. ^ is exponentiation, not XOR.
==,!=,¦¦,&& Standard binary boolean operators.
>,<,<=,>= Standard binary relational operators.
+=, -=, *=... Arithmetic assignment operators.
!, - Standard unary negation operators.
-> Function chaining operator. Appends LHS to front of RHS argument list.
=> Chaining assignment operator. a => is equivalent to a = a ->
? ¦ Standard ternary operator, using ¦ in place of :
: Optional argument operator. Marks function arguments as optional.
. References a plugin function.

misc. syntax

syntax description
# Comment signifier. There is no multi-line comment signifier.
; Statement terminator.

statements

assignment statements:

x = "Hello";  # x is "Hello"
x = 12;       # x is 12
y = (x %= 7); # x is 5, y is 5

Assignment statements are pretty straightforward. Note that variable names are not preceded by a type, and a variable can easily be reassigned to a different type. Since assignment "statements" are really just expressions, they also return the value of the variable they are assigning to, as shown in the last line of the example.

function declarations (and default statements):

function foo(bool b, :string s) {
    default s: "bar";
    if (b)
        return s;
    else
        return 0;
}

This tiny example showcases everything you need to know about function definitions. Functions do not have an explicit return type; this example returns either a num or a string. Optional arguments are marked by a : preceding their type. Inside the function body, a default statement is used to set the value of an optional argument if it is not supplied in the function call. Next, an if/else statement is used to determine the return value of the function.

import statements:

import libfoo;

Plugins can be imported with import. Plugins are shared object (.so) files containing functions written in C. Constructs like import libfoo as bar and import baz from libfoo will probably be added in the future. Unlike most languages, import statements can be placed anywhere, allowing for things like conditional imports.

expressions

function calls:

We can call foo (defined above) like so:

foo True            # returns "bar"
foo (True && False) # returns 0
foo True s:"baz"    # returns "baz"

Function arguments are separated by spaces, as in Haskell. Note that this means that you may need to enclose arguments in parentheses, or you might get some strange error messages. Optional arguments are specified using their name, and can be declared in any order. Note how : is used in all expressions relating to optional arguments: function definitions, function calls, and default statements.

Plugin functions are called by prepending them with the plugin name:

libfoo.foo True

This means that plugin function names can't conflict with core or user functions.

ternary expressions:

x = y < 100 ? 50 | 1000;

speed = x < 100   ? "slow"
      | x < 300   ? "medium"
      | otherwise ? "fast";

In Avisynth, ternary expressions are used heavily to compensate for the language's lack of if/else statements. This is not an issue in Mkvsynth, but the ternary expression is still nice to have. In addition, the otherwise construct is provided to make long ternary chains more readable. otherwise acts as a catch-all, as in Haskell (or default in C).

function chains:

clp => Lanczos4Resize dx dy
    -> TurnLeft
    -> SangNom aa:aath
    -> TurnRight
    -> SangNom aa:aath
    -> LanczosResize ox oy;

The -> operator is used to pass a variable through a series of functions, allowing the script author to avoid lengthy, unreadable nested function calls. Internally, the value on the left side is appended to the front of the argument list on the right side. This is why all video filters should have the input clip as their first argument. The => operator can be used to assign the resulting value to the original variable.