This is a brief introduction to the Plymouth scripting language. The language has many points in common with Javascript and C, so if you know those languages, little should be of surprise.

Basics

There are three types of supported comments:

# script style line comments
// C++ style line comments
/* and C style block comments /* which may be nested */ */

There are some basic objects: numbers, strings, hashes, functions and null.

Simple expression operations such as must be terminated with a semicolon, e.g.

a = b;

Multiple operations can be grouped using curly “{ }” brackets, e.g.

{
 a = b;
 c = a + 8;
}

Numbers can be operated with +, -, *, / and %. Amend assignments (+=, /= etc.) are allowed, as are pre/post inc/decrement, e.g.

a *= ++b;

Strings can be appended using + (even to numbers), e.g.

a = “A” + 7 + “B”;  # gives a string “A7B”

Applying operations on incomparable operands gives a NULL, e.g.

a = “eight” / 2;  # gives a NULL

Comparisons return a number 1, for true, or 0, for false, e.g.

a = (7 >= 6); # sets a to 1
b = ("Cat" == "Dog"); # sets b to 0

Conditional execution operations, “if/else”, “while” and “for” are supported, e.g.

if (a > 0)
 {
  a--;
  b = 0;
 }
else
 a = 0

Conditions evaluate NULL, 0 and “” (empty string) to false, everything else is true, e.g.

while (a--)
 b *= a;

Or operations are lazily evaluated and return the first value that evaluates to true (And returns the first false value), e.g.

value = cached || (cached = do_lookup (index)); # if cached is already set then it is used, otherwise a lookup is executed
if (value > 0 && value < 10) valid == 1;

Hashes can be created by simply accessing their contents using a dot or [] brackets, e.g.

a.size = 1;
b = a[“size”]; # b equals 1

All hash indexing is done using strings even when using a number, e.g.

a[1] = 1;
a[“1”] = 2; # a[1] now equals 2

An auto incrementing hash can be constructed by defining a set between [] brackets, wth the indexing starting at zero, e.g.

a = [1, "c", [3, 2]]; # a[0] equals 1, a[1] equals "C", a[2][0] equals 3, a[2][1] equals 2

To define a function use the “fun” keyword, e.g.

fun functionname (index, par1, par2)
 {
  if (index == 1)
   return par1;
  else
   return par2;
 }

Functions have local variables but if a global one exists, that is used instead. You can force the use of a local even though a global already exists (and vice versa) by using the "local" and "global" hashes, e.g.

val = 1;             #global val = 1
fun functionname ()
 {
  val = 2;           #global val = 2   (global exists, so is used)
  local.val = 3;     #local  val = 3   (explicitly uses the local)
  val = 4;           #local  val = 4   (local exists, so is used)
  mval = 5;          #local mval = 5   (neither global nor local exist, so a local is created)
 }

Plymouth Interaction

There are two basic Plymouth objects: Image and Sprite.

Plymouth Images

To create a new image you need to supply the filename of the image within the theme image directory to Image, e.g.

box_image = Image ("box.png");
logo_image = Image ("special://logo");   # "special://logo" is a special keyword which finds the logo image

You can also create images from text. These are useful to show text messages, e.g.

warning_image = Image.Text ("System running FSCK. This may take some time");

The default is white text color, but you can supply additional parameters of: red, green, blue, alpha, fontname and alignment. Default font is "Sans 12" and default alignment is "left". Alignement is only useful for multi-line text, and its possible values are "left", "center", or "right".

warning_image = Image.Text ("I feel faded", 0.8, 0.8, 0.8, 0.8, "Fixed");

The width and height of an image can be attained using GetWidth and GetHeight, e.g.

logo_area = logo_image.GetWidth() * logo_image.GetHeight();

An image can be rotated or scaled using Rotate and Scale, e.g.

upside_down_logo_image = logo_image.Rotate (3.1415); # the second paramiter is the angle in radians
fat_logo_image = logo_image.Scale (logo_image.GetWidth() * 2 , logo_image.GetHeight ()) # make the image twice the width

Plymouth Sprites

To place an image on the screen, we use sprites.

To create a new sprite call Sprite, then set the image using SetImage, e.g.

my_sprite = Sprite ();
my_sprite.SetImage (fat_logo_image);

You can also set the image while creating the sprite by supplying it to the constructor e.g.

my_sprite = Sprite (fat_logo_image);

The default placement of a new sprite is at the top left corner of the screen (at 0,0). To change the position call SetX and SetY, e.g.

my_sprite.SetX (100);
my_sprite.SetY (200);

If there are multiple sprites it us useful to decide which sprite should be shown above other. This is controlled using the Z component, the sprite with higher the Z is drawn on top.

background_sprite.SetZ (-10);
foreground_sprite.SetZ (10);

To set X, Y and Z in one call you can use SetPosition

logo_sprite.Setposition(100, 100, 0); # place at X=100, Y=100, Z=0

SetOpacity can make sprites transparent (the default opacity is solid 1) or even invisible when set to 0 , e.g.

faded_sprite.SetOpacity (0.5);
invisible_sprite.SetOpacity (0);

It is also possible to get the X/Y/Z/Opcaity/Image properties of a sprite.

sprite.SetOpacity(sprite.GetOpacity()/2);
sprite.SetPosition(sprite.GetX()+1, sprite.Gety()+1, sprite.GetZ());
sprite.SetImage(sprite.GetImage().Rotate(0.1));

Knowing the size of the window can be useful to position sprites. This can be reached using Window.GetWidth and Window.GetHeight, e.g.

centred_sprite.SetX (Window.GetWidth ()  / 2 - centred_sprite.GetImage().GetWidth()  / 2);
centred_sprite.SetY (Window.GetHeight () / 2 - centred_sprite.GetImage().GetHeight() / 2);

If the sprites do not fully cover the whole window, some of the sprite background will be exposed. To set the background colours use Window.SetBackground{Top,Bottom}Color. These take Red, Green and Blue values between 0 and 1, e.g.

Window.SetBackgroundTopColor (0, 0, 1);           # Nice blue on top of the screen fading to
Window.SetBackgroundBottomColor (0.8, 0.2, 0.1);  # an equally nice brown on the bottom

Plymouth Callbacks

Calling Plymouth.SetRefreshFunction with a function will set that function to be called up to 50 times every second, e.g.

fun refresh_callback ()
{
 time++;
}
Plymouth.SetRefreshFunction (refresh_callback);

Other callbacks which can be hooked onto are:

  • Plymouth.SetBootProgressFunction: the callback function is called with two numbers, time spent booting so far and the progress (between 0 and 1)
  • Plymouth.SetRootMountedFunction: the callback function is called when a new root is mounted
  • Plymouth.SetKeyboardInputFunction: the callback function is called with a string containing a new character entered on the keyboard
  • Plymouth.SetUpdateStatusFunction: the callback function is called with the new boot status string
  • Plymouth.SetDisplayPasswordFunction: the callback function is called when the display should display a password dialogue. First arg is prompt string, the second is the number of bullets.
  • Plymouth.SetDisplayQuestionFunction: the callback function is called when the display should display a question dialogue. First arg is prompt string, the second is the entry contents.
  • Plymouth.SetDisplayNormalFunction: the callback function is called when the display should return to normal
  • Plymouth.SetMessageFunction: the callback function is called when new message should be displayed. First arg is message to display. e.g.
fun progress_callback (time, progress)
{
 progress_status = "We have waited " + time + "seconds and we are "+ (progress * 100) + "% though";
 ...
}
Plymouth.SetBootProgressFunction (progress_callback);

To determine the mode of operation plymouth was started in use Plymouth.GetMode which returns a string of one of: "boot", "shutdown", "suspend", "resume" or unknown.

if (Plymouth.GetMode () == "suspend")
{
 ShowSuspendBackground();
}

Mathematics Functions

There are some basic mathematics functions to

  • Math.Abs: Absolute (positive) of a number
  • Math.Min: The smaller of two numbers
  • Math.Max: The greater of two numbers
  • Math.Clamp: Takes 3 numbers, value, min and max. Function forces the value to be between min and max, otherwise either min or max are returned.
  • Math.Pi: The value of Pi (3.14159...)
  • Math.Cos: Cosine function
  • Math.Sin: Sine function
  • Math.Tan: Tangent function
  • Math.ATan2: Arc tangent function taking 2 values (see "man atan2")
  • Math.Sqrt: Square root
  • Math.Int: Returns the rounded down integer.
  • Math.Random: Returns a pseudo random number between 0 and 1.