Packages
kino
0.2.0
0.19.0
0.18.0
0.17.0
0.16.1
0.16.0
0.15.3
0.15.2
0.15.1
0.15.0
0.14.2
0.14.1
0.14.0
0.13.2
0.13.1
0.13.0
0.12.3
0.12.2
0.12.1
0.12.0
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.1
0.8.0
0.7.0
0.6.2
0.6.1
0.6.0
retired
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
Interactive widgets for Livebook
Current section
Files
Jump to
Current section
Files
lib/kino.ex
defmodule Kino do
@moduledoc """
Client-driven interactive widgets for Livebook.
Kino is the library used by Livebook to render rich and interactive
output directly from your Elixir code.
Kino renders any data structure that implements the `Kino.Render`
protocol, falling back to the `inspect/2` representation whenever
an implementation is not available. The data structures supported
by Kino out of the box are:
### VegaLite
`VegaLite` specifications are rendered as visualizations:
Vl.new(...)
|> Vl.data_from_series(...)
|> ...
### Kino.VegaLite
`Kino.VegaLite` is an extension of `VegaLite` that allows data to
be streamed:
widget =
Vl.new(...)
|> Vl.data_from_series(...)
|> ...
|> Kino.VegaLite.new()
|> Kino.render()
Kino.VegaLite.push(widget, %{x: 1, y: 2})
### Kino.ETS
`Kino.ETS` implements a data table output for ETS tables in the
system:
tid = :ets.new(:users, [:set, :public])
Kino.ETS.new(tid)
### Kino.DataTable
`Kino.DataTable` implements a data table output for user-provided
tabular data:
data = [
%{id: 1, name: "Elixir", website: "https://elixir-lang.org"},
%{id: 2, name: "Erlang", website: "https://www.erlang.org"}
]
Kino.DataTable.new(data)
### Kino.Image
`Kino.Image` wraps binary image content and can be used to render
raw images of any given format:
content = File.read!("/path/to/image.jpeg")
Kino.Image.new(content, "image/jpeg")
### All others
All other data structures are rendered as text using Elixir's
`inspect/2`.
"""
@doc """
Sends the given term as cell output.
This allows any Livebook cell to have multiple evaluation
results. You can think of this function as a generalized
`IO.puts/2` that works for any type.
"""
@spec render(term()) :: term()
def render(term) do
gl = Process.group_leader()
ref = Process.monitor(gl)
output = Kino.Render.to_livebook(term)
send(gl, {:io_request, self(), ref, {:livebook_put_output, output}})
receive do
{:io_reply, ^ref, :ok} -> :ok
{:io_reply, ^ref, _} -> :error
{:DOWN, ^ref, :process, _object, _reason} -> :error
end
Process.demonitor(ref)
term
end
end