# Introduction to Kino

## Setup

In this notebook we will explore the possibilities that
[`kino`](https://github.com/elixir-nx/kino) brings
into your notebooks. Kino can be thought of as Livebook's
friend that instructs it how to render certain widgets
and interact with them. Let's install it:

```elixir
Mix.install([
  {:kino, "~> 0.5.0"}
])
```

<!-- livebook:{"branch_parent_index":0} -->

## Kino.Input

The [`Kino.Input`](https://hexdocs.pm/kino/Kino.Input.html)
module contains the most common kinos you will use. They are
used to define inputs in one cell, which you can read in a
future cell:

```elixir
name = Kino.Input.text("Your name")
```

and now we can greet the user back:

```elixir
IO.puts("Hello, #{Kino.Input.read(name)}!")
```

There are multiple types of inputs, such as text areas,
color dialogs, selects, and more. Feel free to explore them.

<!-- livebook:{"branch_parent_index":0} -->

## Kino.Markdown

Given our notebooks already know how to render Markdown,
you won't be surprised to find we can also render Markdown
directly from our Elixir cells. This is done by wrapping
the Markdown contents in [`Kino.Markdown.new/1`](https://hexdocs.pm/kino/Kino.Markdown.html):

````elixir
Kino.Markdown.new("""
# Example

A regular Markdown file.

## Code

```elixir
"Elixir" |> String.graphemes() |> Enum.frequencies()
```

## Table

| ID | Name   | Website                 |
| -- | ------ | ----------------------- |
| 1  | Elixir | https://elixir-lang.org |
| 2  | Erlang | https://www.erlang.org  |
""")
````

The way it works is that Livebook automatically detects
the output is a kino and renders it in Markdown. That's
the first of many kinos we will learn today. Let's move
forward.

<!-- livebook:{"branch_parent_index":0} -->

## Kino.DataTable

You can render arbitrary tabular data using [`Kino.DataTable.new/1`](https://hexdocs.pm/kino/Kino.DataTable.html), let's have a look:

```elixir
data = [
  %{id: 1, name: "Elixir", website: "https://elixir-lang.org"},
  %{id: 2, name: "Erlang", website: "https://www.erlang.org"}
]

Kino.DataTable.new(data)
```

The data must be an enumerable, with records being maps or
keyword lists.

Now, let's get some more realistic data. Whenever you run
Elixir code, you have several lightweight processes running
side-by-side. We can actually gather information about these
processes and render it as a table:

```elixir
processes = Process.list() |> Enum.map(&Process.info/1)
```

We can pick the data keys that are relevant for us:

```elixir
Kino.DataTable.new(
  processes,
  keys: [:registered_name, :initial_call, :reductions, :stack_size]
)
```

Now you can use the table above to sort by the number of
reductions and identify the most busy processes!

<!-- livebook:{"branch_parent_index":0} -->

## Kino.ETS

Kino supports multiple other data structures to be rendered
as tables. For example, you can use [`Kino.ETS`](https://hexdocs.pm/kino/Kino.ETS.html)
to render ETS tables and easily browse their contents.
Let's first create our own table:

```elixir
tid = :ets.new(:users, [:set, :public])
Kino.ETS.new(tid)
```

In fact, Livebook automatically recognises an ETS table and
renders it as such:

```elixir
tid
```

Currently the table is empty, so it's time to insert some rows.

```elixir
for id <- 1..24 do
  :ets.insert(tid, {id, "User #{id}", :rand.uniform(100), "Description #{id}"})
end
```

Having the rows inserted, click on the "Refetch" icon in the table output
above to see them.

Similar functionality is available for database queries via [Ecto](https://github.com/elixir-ecto/ecto) and the [`Kino.Ecto`](https://hexdocs.pm/kino/Kino.Ecto.html) module.

<!-- livebook:{"branch_parent_index":0} -->

## Kino.render/1

As we saw, Livebook automatically recognises widgets returned
from each cell and renders them accordingly. However, sometimes
it's useful to explicitly render a widget in the middle of the cell,
similarly to `IO.puts/1`, and that's exactly what `Kino.render/1`
does! It works with any type and tells Livebook to render the value
in its special manner.

```elixir
# Arbitrary data structures
Kino.render([%{name: "Ada Lovelace"}, %{name: "Alan Turing"}])
Kino.render("Plain text")

# Some kinos
Kino.render(Kino.Markdown.new("**Hello world**"))

"Cell result 🚀"
```

<!-- livebook:{"branch_parent_index":0} -->

## Kino.Frame and animations

`Kino.Frame` allows us to render an empty frame and update it
as we progress. Let's render an empty frame:

```elixir
frame = Kino.Frame.new()
```

Now, let's render a random number between 1 and 100 directly
in the frame:

```elixir
Kino.Frame.render(frame, "Got: #{Enum.random(1..100)}")
```

Notice how every time you reevaluate the cell above it updates
the frame. You can also use `Kino.Frame.append/2` to append to
the frame:

```elixir
Kino.Frame.append(frame, "Got: #{Enum.random(1..100)}")
```

Appending multiple times will always add new contents. The content
can be reset by calling `Kino.Frame.render/2` or `Kino.Frame.clear/1`.

By using loops, you can use `Kino.Frame` to dynamically add contents
or animate your livebooks. In fact, there is a convenience function
called `Kino.animate/3` to be used exactly for this purpose:

```elixir
Kino.animate(100, 0, fn i ->
  md = Kino.Markdown.new("**Iteration: `#{i}`**")
  {:cont, md, i + 1}
end)
```

The above example renders new Markdown output every 100ms.
You can use the same approach to render regular output
or images too!

With this, we finished our introduction to Kino. Now we are
ready to bring two concepts we have already learned together:
`Kino` and `VegaLite`. [Let's use them to introspect the Elixir
runtime your livebooks run on](/explore/notebooks/vm-introspection).
