# Rune finder ```elixir Mix.install([ {:kino, "~> 0.12.3"} ]) ``` ## About this ```elixir import Kino.Shorts ``` ````elixir markdown("""
About this app Find Unicode characters by name. For example, for `face cat` ``` U+1F431 🐱 CAT FACE U+1F638 😸 GRINNING CAT FACE WITH SMILING EYES U+1F639 😹 CAT FACE WITH TEARS OF JOY U+1F63A 😺 SMILING CAT FACE WITH OPEN MOUTH U+1F63B 😻 SMILING CAT FACE WITH HEART-SHAPED EYES U+1F63C 😼 CAT FACE WITH WRY SMILE U+1F63D 😽 KISSING CAT FACE WITH CLOSED EYES U+1F63E 😾 POUTING CAT FACE U+1F63F 😿 CRYING CAT FACE U+1F640 🙀 WEARY CAT FACE ```
""") ```` ## Code ```elixir content = Kino.FS.file_path("UnicodeData.txt") |> File.read!() ``` ```elixir defmodule RuneFinder do defp to_rune(code, name) do rune = <> "U+#{code}\t#{rune}\t#{name}" end defp select(line_stream, query_words) do Enum.map(line_stream, fn line -> [code, name | _] = String.split(line, ";") if MapSet.subset?(query_words, tokenize(name)), do: to_rune(code, name) end) |> Enum.reject(&(&1 == nil)) end defp find(query_words) do Kino.FS.file_path("UnicodeData.txt") |> File.stream!() |> select(query_words) end defp tokenize(text) do text |> String.replace("-", " ") |> String.split() |> MapSet.new() end def main(args) do args |> String.upcase() |> tokenize |> find end end ``` ```elixir form = Kino.Control.form( [ name: Kino.Input.text("Unicode characters name", default: "face cat") ], submit: "Find" ) ``` ```elixir output_frame = frame() Kino.listen(form, fn event -> origin = event.origin Kino.Frame.clear(output_frame, to: origin) case event.data.name do "" -> Kino.Frame.render(output_frame, "Please provide words to find.", to: origin) _ -> runes = RuneFinder.main(event.data.name) Enum.each(runes, fn rune -> Kino.Frame.append(output_frame, text(rune), to: origin) end) Kino.Frame.append(output_frame, text("\n#{Enum.count(runes)} found"), to: origin) end end) output_frame ```