Scripting Languages

Viash supports several languages to use in your components. This guide explains how to reference scripts in your Viash config files and how to use Viash specific variables.

Requirements

Note

If you’re using WSL2, make sure to follow the Linux instructions and execute the commands in a WSL2 terminal.

Bash doesn’t have any dependencies and is included in every modern Linux distro, including those provided for WSL2 on Microsoft’s Store app. On macOS, the default shell is Zsh since 2019, but it still comes packaged with an older Bash 3.2.

To get started with C# scripting, you need to download and install the .NET 6.0 SDK.

After installing the SDK, run this command to install the dotnet-script tool:

dotnet tool install -g dotnet-script

To verify that dotnet-script was installed successfully, run this command to get a list of installed tools:

dotnet tool list -g

The output should look something like this:

Package Id         Version      Commands     
---------------------------------------------
dotnet-script      1.3.1        dotnet-script

To run JavaScript on your system, you’ll need to download and install Node.js from their homepage.

To run Python scripts on your system, download and install Python. Most package managers include a python package as well. Make sure to install a version of Python that’s at least version 3.8 or newer.

To be able to run R scripts, you’ll need download and install R for your OS.

Running Scala scripts requires you to download and install Scala.

Referencing scripts in a Viash config file

When referencing a Bash script in the resources of the functionality section your Viash config, use bash_script as its type:

functionality:
  name: my_component
  resources:
  - type: bash_script
    path: script.sh

When referencing a C# script in the resources of the functionality section your Viash config, use csharp_script as its type:

functionality:
  name: my_component
  resources:
  - type: csharp_script
    path: script.csx

When referencing a JavaScript script in the resources of the functionality section your Viash config, use javascript_script as its type:

functionality:
  name: my_component
  resources:
  - type: javascript_script
    path: script.js

When referencing a Python script in the resources of the functionality section your Viash config, use python_script as its type:

functionality:
  name: my_component
  resources:
  - type: python_script
    path: script.py

When referencing a R script in the resources of the functionality section your Viash config, use r_script as its type:

functionality:
  name: my_component
  resources:
  - type: r_script
    path: script.r

When referencing a Scala script in the resources of the functionality section your Viash config, use scala_script as its type:

functionality:
  name: my_component
  resources:
  - type: scala_script
    path: script.scala

Executing scripts

Bash scripts end with the .sh extension. They can be run locally by using the bash command:

bash script.sh

C# scripts end with the .csx extension. They can be run locally by using the dotnet script command:

dotnet script script.csx

JavaScript scripts end with the .js extension. They can be run locally by using the node command:

node script.js

Python scripts end with the .py extension. They can be run locally by using the python command:

python script.py

R scripts end with the .r extension. They can be run locally by using the Rscript command:

Rscript script.r

Scala scripts end with the .scala extension. They can be run locally by using the scala -nc command:

scala -nc script.scala

Script examples

These examples will briefly show to start scripting with Viash in mind. Each example shows the source code and the output after running it.

Using variables

#!/bin/bash

hello="Hello World!"
echo $hello
#!/usr/bin/env dotnet-script

string hello = "Hello World!";
Console.WriteLine(hello);
#!/usr/bin/env node

let hello = 'Hello World!'
console.log(hello)
#!/usr/bin/env python3

hello = "Hello World!"
print(hello)
#!/usr/bin/env Rscript

hello = "Hello World!"
cat(hello)
Rscript script.r
#!/usr/bin/env scala

val hello = "Hello World!";
println(hello)

Output

Hello World!

Using Viash arguments as variables

Viash generates variables based on the arguments defined in the Viash config file and injects them at the top of your script.

Variables start with $par_, followed by the name of the argument.

config.vsh.yaml

functionality:
  name: hello_world
  arguments:
  - type: string
    name: --hello
    default: "Hello World!"
  resources:
  - type: bash_script
    path: ViashVariables.sh

ViashVariables.sh

#!/bin/bash

echo $par_hello

Variables are grouped inside an anonymous par class and can be referenced by name.

config.vsh.yaml

functionality:
  name: hello_world
  arguments:
  - type: string
    name: --hello
    default: "Hello World!"
  resources:
  - type: csharp_script
    path: ViashVariables.csx

ViashVariables.csx

#!/usr/bin/env dotnet-script

Console.WriteLine(par.hello);

Variables are grouped inside a dictionary named par and can be referenced by name.

config.vsh.yaml

functionality:
  name: hello_world
  arguments:
  - type: string
    name: --hello
    default: "Hello World!"
  resources:
  - type: javascript_script
    path: ViashVariables.js

ViashVariables.js

#!/usr/bin/env node

console.log(par['hello'])

Variables are grouped inside a dictionary named par and can be referenced by name.

config.vsh.yaml

functionality:
  name: hello_world
  arguments:
  - type: string
    name: --hello
    default: "Hello World!"
  resources:
  - type: python_script
    path: ViashVariables.py

ViashVariables.py

#!/usr/bin/env python3

print(par["hello"])

Variables are grouped inside a list named par and can be referenced by name.

config.vsh.yaml

functionality:
  name: hello_world
  arguments:
  - type: string
    name: --hello
    default: "Hello World!"
  resources:
  - type: r_script
    path: ViashVariables.r

ViashVariables.r

#!/usr/bin/env Rscript

cat(par$hello)

Variables are grouped inside an instance of a class named par and can be referenced by name.

config.vsh.yaml

functionality:
  name: hello_world
  arguments:
  - type: string
    name: --hello
    default: "Hello World!"
  resources:
  - type: scala_script
    path: ViashVariables.scala

ViashVariables.scala

#!/usr/bin/env scala

println(par.hello.get)

Using Viash placeholder variables

By adding Viash variables between a VIASH START and a VIASH END comment, you can write your script with Viash in mind while keeping it working for standalone execution.

#!/bin/bash

## VIASH START
par_hello="Hello World!"
## VIASH END

echo $par_hello
#!/usr/bin/env dotnet-script

// VIASH START
var par = new {
  hello = "Hello World!"
};
// VIASH END

Console.WriteLine(par.hello);
#!/usr/bin/env node

// VIASH START
let par = {
    'hello': 'Hello World!'
  }
// VIASH END

console.log(par['hello'])
#!/usr/bin/env python3

## VIASH START
par = {
  "hello": "Hello World!"
}
## VIASH END

print(par["hello"])
#!/usr/bin/env Rscript

## VIASH START
par <- list(
  hello = "Hello World!"
)
## VIASH END

cat(par$hello)
#!/usr/bin/env scala

// VIASH START
case class ViashPar(
  greeter: Option[String]
)

val par = ViashPar(
  greeter = Some("Hello World!")
)
// VIASH END

println(par.hello.get)

Output

Hello World!

Anything between VIASH START and VIASH END will be replaced by the injected variables Viash generates once the script is executed as part of a component. This allows you to easily troubleshoot your script while being compatible with Viash.

Language specific tips

Sourcing other scripts

With bash, you can include other bash scripts to share content and functionality by using the source command.
By writing two scripts and adding them to the same directory, one can reference the other:

script.sh

#!/bin/bash

source include_me.sh
echo "Hello from the main script!"

include_me.sh

#!/bin/bash

echo "Hi from the included script!"

Running script.sh results in the following output:

Hi from the included script!
Hello from the main script!

Viash supports the sourcing of scripts by adding them as a resource:

config.vsh.yaml

functionality:
  name: source_example
  resources:
  - type: bash_script
    path: script.sh
  - type: bash_script
    path: include_me.sh

Doing this will ensure any needed scripts will be included with the build target.

Using NuGet packages

With dotnet-script, you can reference NuGet packages directly from within the script. In the example below, we add a reference to Newtonsoft.Json to convert a dictionary to JSON and output it to the console.

script.csx

#!/usr/bin/env dotnet-script
#r "nuget: Newtonsoft.Json, 13.0.1"

using Newtonsoft.Json;

Dictionary<string, int> downloads = new Dictionary<string, int>
{
    { "v1.0", 501 },
    { "v1.1", 802 },
    { "v2.0", 2857 }
};

string json = JsonConvert.SerializeObject(downloads, Formatting.Indented);
Console.WriteLine(json);

Running script.csx results in the following output:

{
  "v1.0": 501,
  "v1.1": 802,
  "v2.0": 2857
}

We don’t have any JavaScript tips yet!

We don’t have any Python tips yet!

We don’t have any R tips yet!

We don’t have any Scala tips yet!

Meta variables

Viash offers hidden variables to use in your scripts that can be used to get meta information about your component.

Functionality name

Name of the component found in the functionality section of the Viash config:

functionality:
  name: my_component
echo $meta_functionality_name
Console.WriteLine(meta.functionality_name);
console.log(meta['functionality_name']);
print(meta["functionality_name"])
cat(meta$functionality_name)
println(meta.functionality_name)

Output

my_component

Resources directory

Path where the resources as defined in the Viash config file are stored.

echo $meta_resources_dir
Console.WriteLine(meta.resources_dir);
console.log(meta['resources_dir']);
print(meta["resources_dir"])
cat(meta$resources_dir)
println(meta.resources_dir)

When using viash run to create a temporary build target and execute it, this will point to the temporary path where the executable was generated:

/tmp/viash_my_component9560481446119256265

After building a component using viash build and running the generated executable, it points to the directory where the executable and the other resources reside in:

/home/user/components/my_component_target_dir

Temp directory

Path to the directory supplied by the host system where you can write temporary files to.

echo $meta_temp_dir
Console.WriteLine(meta.temp_dir);
console.log(meta['temp_dir']);
print(meta["temp_dir"])
cat(meta$temp_dir)
println(meta.temp_dir)

Output

/tmp