Wren Book
Mix.install([
{:kino, "~> 0.6.1"},
{:temp, "~> 0.4"}
])
About Wren
Think Smalltalk in a Lua-sized package with a dash of Erlang and wrapped up in a familiar, modern syntax. See more at https://wren.io/
Configuration
Choose the binary file to execute Wren Scripts
defmodule Wren do
# Binary Name
# Currently using https://github.com/joshgoebel/wren-console/releases/tag/v0.3.1
# since it has more built in libraries
@unix "wrenc"
@macos "wrenc-mac"
@windows "wrenc.exe"
# Choose platform
@current @macos
def path(executable \\ @current) do
Path.expand("#{__DIR__}/./bin/#{executable}")
end
def unix() do
path(@unix)
end
def windows() do
path(@windows)
end
def macos() do
path(@macos)
end
end
Wren Cell
Defines how Wren Scripts are executed.
defmodule KinoGuide.WrenCell do
use Kino.JS
use Kino.JS.Live
use Kino.SmartCell, name: "Wren script"
@impl true
def init(_attrs, ctx) do
{:ok, ctx, editor: [attribute: "source", language: "javascript"]}
end
@impl true
def handle_connect(ctx) do
{:ok, %{}, ctx}
end
@impl true
def to_attrs(_ctx) do
%{}
end
@impl true
def to_source(attrs) do
quote do
path = Temp.path!()
File.write!(path, unquote(attrs["source"]))
System.shell(
"""
trap "rm -f #{path}" 0 2 3 15
#{Wren.path()} #{path}
""",
into: IO.stream(),
stderr_to_stdout: true
)
|> elem(1)
end
|> Kino.SmartCell.quoted_to_string()
end
asset "main.js" do
"""
export function init(ctx, payload) {
ctx.importCSS("main.css");
root.innerHTML = `
Wren script
`;
}
"""
end
asset "main.css" do
"""
.app {
padding: 8px 16px;
border: solid 1px #cad5e0;
border-radius: 0.5rem 0.5rem 0 0;
border-bottom: none;
}
"""
end
end
Kino.SmartCell.register(KinoGuide.WrenCell)
Scripts
Here you can run your scripts using Wren Script Smart Cells.
Hello Example
path = Temp.path!()
File.write!(
path,
"System.print(\"Hello, world!\")\n\nclass Wren {\n flyTo(city) {\n System.print(\"Flying to %(city)\")\n }\n}\n\nvar adjectives = Fiber.new {\n [\"small\", \"clean\", \"fast\"].each {|word| Fiber.yield(word) }\n}\n\nwhile (!adjectives.isDone) System.print(adjectives.call())"
)
System.shell("trap \"rm -f #{path}\" 0 2 3 15
#{Wren.path()} #{path}
", into: IO.stream(), stderr_to_stdout: true) |> elem(1)
Fractal Example
path = Temp.path!()
File.write!(
path,
"for (yPixel in 0...24) {\n var y = yPixel / 12 - 1\n for (xPixel in 0...80) {\n var x = xPixel / 30 - 2\n var x0 = x\n var y0 = y\n var iter = 0\n while (iter < 11 && x0 * x0 + y0 * y0 <= 4) {\n var x1 = (x0 * x0) - (y0 * y0) + x\n var y1 = 2 * x0 * y0 + y\n x0 = x1\n y0 = y1\n iter = iter + 1\n }\n System.write(\" .-:;+=xX$& \"[iter])\n }\n System.print(\"\")\n}"
)
System.shell("trap \"rm -f #{path}\" 0 2 3 15
#{Wren.path()} #{path}
", into: IO.stream(), stderr_to_stdout: true) |> elem(1)