Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Wren Book

wren.livemd

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)