Arrow Playground is now available
by Juan Valencia Calvellido
- •
- April 11, 2019
- •
- kotlin• functional• arrow• kategory• funktionale
- |
- 9 minutes to read.

As you know Arrow is an open source library that’s packed with data types and type classes that empower pure functional programming in Kotlin. But, did you know you can embed Arrow snippets into any page? And even execute them? 😏
Arrow Playground is a JavaScript library that creates Kotlin-aware, including Arrow, editors capable of running code from HTML block elements. This is a fork of the original Kotlin Playground work done by the JetBrains team.
Installation and usage
Automatic initialization
You can load Arrow Playground from the UNPKG content delivery network, insert a <script>
element into your page, and specify what elements should be converted in a data-selector
attribute.
<script src="https://unpkg.com/arrow-playground@1" data-selector=".kotlin-code"></script>
The result of this action can be seen on this very page. As this site is already using Arrow Playground, the following block of Kotlin code:
import arrow.*
import arrow.core.*
fun main(args: Array<String>) {
val someValue: Option<String> = Some("I am wrapped in something")
println(someValue)
// Some(I am wrapped in something)
}
Turns into:
import arrow.*
import arrow.core.*
fun main(args: Array<String>) {
val someValue: Option<String> = Some("I am wrapped in something")
println(someValue)
// Some(I am wrapped in something)
}
Through the use of the custom data-selector
attribute you can set the elements that will be applied with the Playground. You can use any valid DOM selector:
- An element tag, for example
code
- A class selector, like
.kotlin-code
- An identifier, such as
#my-unique-id-selector
- An attribute, as
[data-attribute="value"]
Manual initialization
If you want to initiate Arrow Playground manually, you can separate the process of fetching the library and the code conversion itself. To accomplish this, simply omit the data-selector
attribute and use a second <script>
element like this:
<script src="https://unpkg.com/arrow-playground@1"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
ArrowPlayground('.kotlin-code-selector');
});
</script>
You can also overwrite the server where the code is being sent to be compiled and analyzed (this could be valuable, for example, if you host a server instance that includes your own Kotlin libraries outside of Arrow). This can be accomplished by setting the data-server
attribute, like this:
<script src="https://unpkg.com/arrow-playground@1"
data-selector="code"
data-server="https://my-arrow-playground-server">
</script>
To host your own server, please review forking and/or cloning the Try Arrow server repository.
Serve your own Arrow Playground instance
Instead of using a CDN, you can also generate the library through the proper npm
script (npm run build
), then host it, and use it with the same process we’ve illustrated previously.
<script src="https://my-own-server/arrow-playground.js" data-selector="code"></script>
Arrow Playground is published in the NPM registry, so if you use a node.js based build environment, you can install arrow-playground
as you usually do with dependencies - through npm
.
npm install arrow-playground -S
And then just use it in your code:
// ES5
var playground = require('arrow-playground');
document.addEventListener('DOMContentLoaded', function() {
playground('code'); // attach to all <code> elements
});
// ES6
import playground from 'arrow-playground';
document.addEventListener('DOMContentLoaded', () => {
playground('code'); // attach to all <code> elements
});
Jekyll environment
It’s possible that you want to embed Arrow code snippets in a Jekyll based website. As Jekyll uses Kramdown as its default Markdown parser, here are a few tips to integrate Arrow Playground with this stack.
<script src="https://unpkg.com/arrow-playground@1" data-selector=".language-kotlin"></script>
{: data-executable="true" data-theme="darcula"}
```kotlin
import arrow.*
import arrow.core.*
fun main(args: Array<String>) {
val someValue: Option<String> = Some("I am wrapped in something")
println(someValue)
// Some(I am wrapped in something)
}
```
Processing triple backticks fenced code blocks will surround the snippet into <pre>
and <code>
elements, adding a class with the specified language. In this case, it’s language-kotlin
so you can take advantage of using it as your selector. To add attributes to the blocks, you can use the Kramdown IAL syntax. Let’s dive deeper into the attributes to customize your Arrow Playground snippets!
Customizing editors
Use some of the following attributes on the editors to adjust their behavior:
-
data-executable
: Not just highlighting, you can make the code snippets runnable and editable by using thedata-executable
attribute. -
theme="arrow|idea|darcula|default"
: Some highlighting themes to use, we’ll have a rundown of them later in the post. -
autocomplete="true|false"
: Get completion on every key press. Iffalse
=> Press ctrl-space to activate autocompletion. Defaults tofalse
. -
indent="4"
: How many spaces a block should be indented. Defaults to4
. -
lines="true|false"
: Whether to show line numbers to the left of the editor. Defaults tofalse
. -
from="5" to="10
: Create a part of code. Examplefrom
line 5to
line 10. -
match-brackets="true|false""
: Determines whether brackets are matched whenever the cursor is moved next to a bracket. Defaults totrue
.
Additionally, you can make a section of code read-only by placing it between //sampleStart
and //sampleEnd
markers. The code outside of those markers will be hidden by default, with possibility of showing it by clicking a button. If you want to completely hide a section, just set the attribute folded-button
to false
value.
<code data-executable="true">
import arrow.*
import arrow.core.*
fun main(args: Array<String>) {
//sampleStart
val someValue: Option<String> = Some("I am wrapped in something")
println(someValue)
//sampleEnd
// Some(I am wrapped in something)
}
</code>
import arrow.*
import arrow.core.*
fun main(args: Array<String>) {
//sampleStart
val someValue: Option<String> = Some("I am wrapped in something")
println(someValue)
//sampleEnd
// Some(I am wrapped in something)
}
<code data-executable="true" folded-button="false">
import arrow.*
import arrow.core.*
fun main(args: Array<String>) {
//sampleStart
val someValue: Option<String> = Some("I am wrapped in something")
println(someValue)
//sampleEnd
// Some(I am wrapped in something)
</code>
import arrow.*
import arrow.core.*
fun main(args: Array<String>) {
//sampleStart
val someValue: Option<String> = Some("I am wrapped in something")
println(someValue)
//sampleEnd
// Some(I am wrapped in something)
}
Themes
If you don’t specify it, the highlighting theme will follow Arrow library color scheme, but you can change it using the theme
attribute.
For example, this would be CodeMirror’s default theme:
<code theme="default"></code>
import arrow.*
import arrow.core.*
fun main(args: Array<String>) {
val someValue: Option<String> = Some("I am wrapped in something")
println(someValue)
// Some(I am wrapped in something)
}
Or you can go with the dark theme, darcula
:
<code theme="darcula"></code>
import arrow.*
import arrow.core.*
fun main(args: Array<String>) {
val someValue: Option<String> = Some("I am wrapped in something")
println(someValue)
// Some(I am wrapped in something)
}
Events
You can leverage some of the Arrow Playground emitted events. You would use it like this:
function onChange(code) {
console.log("Editor code was changed:\n" + code);
}
const options = {
onChange: onChange(code),
};
playground('.selector', options)
Events description:
-
onChange(code)
— fires every time the content of the editor is changed. Debounce time: 0.5s. code — current playground code. -
onCloseConsole
— is called after the console’s closed. -
onOpenConsole
— is called after the console’s opened. -
getInstance(instance)
- gets the playground state API, where you can find some useful data:
instance.state // playground attributes, dependencies and etc.
instance.nodes // playground NodeElement.
instance.codemirror // editor specification.
instance.execute() // function for executing code snippet programmatically.
instance.getCode() // function for getting the code from the snippet.
Supported keyboard shortcuts
- Ctrl+Space — code completion
- Ctrl+F9 / Cmd+R — execute snippet
- Ctrl+/ — comment code
- Ctrl+Alt+L / Cmd+Alt+L — format code
- Shift+Tab — decrease indent
For the complete list of options and examples, please check out: