Packages
fnord
0.4.23
0.9.40
0.9.39
0.9.38
0.9.37
0.9.36
0.9.35
0.9.34
0.9.33
0.9.32
0.9.31
0.9.30
0.9.29
0.9.28
0.9.27
0.9.26
0.9.25
0.9.24
0.9.23
0.9.22
0.9.21
0.9.20
0.9.19
0.9.18
0.9.17
0.9.16
0.9.15
0.9.14
0.9.13
0.9.12
0.9.11
0.9.10
0.9.9
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.99
0.8.98
0.8.97
0.8.96
0.8.95
0.8.94
0.8.93
0.8.92
0.8.91
0.8.90
0.8.89
0.8.88
0.8.87
0.8.86
0.8.85
0.8.84
0.8.83
0.8.82
0.8.81
0.8.80
0.8.79
0.8.78
0.8.77
0.8.76
0.8.75
0.8.74
0.8.73
0.8.72
0.8.71
0.8.70
0.8.69
0.8.68
0.8.67
0.8.66
0.8.65
0.8.64
0.8.63
0.8.62
0.8.61
0.8.60
0.8.59
0.8.58
0.8.57
0.8.56
0.8.55
0.8.54
0.8.53
0.8.52
0.8.51
0.8.50
0.8.49
0.8.48
0.8.47
0.8.46
0.8.45
0.8.44
0.8.43
0.8.42
0.8.41
0.8.40
0.8.39
0.8.38
0.8.37
0.8.36
0.8.35
0.8.34
0.8.33
0.8.32
0.8.31
0.8.30
0.8.29
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.1
0.8.0
0.7.24
0.7.23
0.7.22
0.7.21
0.7.20
0.7.19
0.7.18
0.7.17
0.7.16
0.7.15
0.7.14
0.7.13
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.3
0.7.2
0.7.1
0.7.0
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.1
0.6.0
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.44
0.4.43
0.4.42
0.4.41
0.4.40
0.4.39
0.4.38
0.4.37
0.4.36
0.4.35
0.4.34
0.4.33
0.4.32
0.4.30
0.4.29
0.4.28
0.4.27
0.4.26
0.4.25
0.4.24
0.4.23
0.4.22
0.4.21
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
AI code archaeology
Current section
Files
Jump to
Current section
Files
lib/tui.ex
defmodule Tui do
use GenServer
@render_intvl 100
@bullshit_rotation_interval 2500
@bullshit_sf_phrases [
"Reversing the polarity of the context window",
"Recalibrating the embedding matrix flux",
"Initializing quantum token shuffler",
"Stabilizing token interference",
"Aligning latent vector manifold",
"Charging semantic field resonator",
"Inverting prompt entropy",
"Redirecting gradient descent pathways",
"Synchronizing the decoder attention",
"Calibrating neural activation dampener",
"Polarizing self-attention mechanism",
"Recharging photonic energy in the deep learning nodes",
"Fluctuating the vector space harmonics",
"Boosting the backpropagation neutrino field",
"Cross-referencing the hallucination core"
]
# -----------------------------------------------------------------------------
# Client API
# -----------------------------------------------------------------------------
def start_link(opts) do
Owl.LiveScreen.start_link(refresh_every: @render_intvl)
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
def stop(_pid, status \\ :normal) do
case GenServer.whereis(__MODULE__) do
nil -> :ok
pid when is_pid(pid) -> GenServer.stop(pid, status)
end
end
def add_step() do
case GenServer.whereis(__MODULE__) do
nil -> {:ok, nil}
pid when is_pid(pid) -> GenServer.call(__MODULE__, {:add_step})
end
end
def add_step(msg, detail \\ nil) do
case GenServer.whereis(__MODULE__) do
nil -> {:ok, nil}
pid when is_pid(pid) -> GenServer.call(__MODULE__, {:add_step, msg, detail})
end
end
def update_step(id, msg, detail \\ nil) do
case GenServer.whereis(__MODULE__) do
nil -> :ok
pid when is_pid(pid) -> GenServer.cast(__MODULE__, {:update_step, id, msg, detail})
end
end
def finish_step(id, outcome) do
case GenServer.whereis(__MODULE__) do
nil -> :ok
pid when is_pid(pid) -> GenServer.cast(__MODULE__, {:finish_step, id, outcome})
end
end
def finish_step(id, outcome, msg, detail \\ nil) do
case GenServer.whereis(__MODULE__) do
nil -> :ok
pid when is_pid(pid) -> GenServer.cast(__MODULE__, {:finish_step, id, outcome, msg, detail})
end
end
# -----------------------------------------------------------------------------
# Server callbacks
# -----------------------------------------------------------------------------
def init(opts) do
if opts[:quiet] do
{:ok, nil}
else
{:ok, render_proc} = Task.start_link(&render_interval/0)
state = %{
opts: opts,
id_counter: 0,
statuses: %{},
progress_char: "⠋",
progress_color: :magenta,
render_proc: render_proc
}
Owl.LiveScreen.add_block(:ask, state: status_box(state))
{:ok, state}
end
end
def terminate(_reason, nil), do: :ok
def terminate(_reason, state) do
completed =
state.statuses
|> Enum.map(fn
{id, {msg, detail, :processing}} -> {id, {msg, detail, :ok}}
{id, {msg, detail, outcome}} -> {id, {msg, detail, outcome}}
end)
%{state | statuses: Map.new(completed)}
|> render()
Owl.LiveScreen.await_render()
Owl.LiveScreen.flush()
:ok
end
def handle_call({:add_step, _msg, _detail}, _from, nil) do
{:reply, nil, nil}
end
def handle_call({:add_step, msg, detail}, _from, state) do
{id, state} = next_id(state)
state = %{state | statuses: Map.put(state.statuses, id, {msg, detail, :processing})}
{:reply, id, state}
end
def handle_call({:add_step}, _from, nil) do
{:reply, nil, nil}
end
def handle_call({:add_step}, _from, state) do
{id, state} = next_id(state)
state = %{state | statuses: Map.put(state.statuses, id, {nil, nil, :processing})}
start_bs_label_changer(id)
{:reply, id, state}
end
def handle_cast({:update_step, _id, _msg, _detail}, nil) do
{:noreply, nil}
end
def handle_cast({:update_step, id, msg, detail}, state) do
state = %{state | statuses: Map.put(state.statuses, id, {msg, detail, :processing})}
{:noreply, state}
end
def handle_cast({:finish_step, _id, _outcome}, nil) do
{:noreply, nil}
end
def handle_cast({:finish_step, id, outcome}, state) do
{msg, detail, _old_outcome} = Map.get(state.statuses, id)
state = %{state | statuses: Map.put(state.statuses, id, {msg, detail, outcome})}
{:noreply, state}
end
def handle_cast({:finish_step, _id, _outcome, _msg, _detail}, nil) do
{:noreply, nil}
end
def handle_cast({:finish_step, id, outcome, msg, detail}, state) do
state = %{state | statuses: Map.put(state.statuses, id, {msg, detail, outcome})}
{:noreply, state}
end
def handle_cast(:render, nil) do
{:noreply, nil}
end
def handle_cast(:render, state) do
{:noreply, render(state)}
end
# -----------------------------------------------------------------------------
# Internal functions
# -----------------------------------------------------------------------------
defp next_id(state) do
id = state.id_counter
{id, %{state | id_counter: state.id_counter + 1}}
end
defp render_interval() do
GenServer.cast(__MODULE__, :render)
Process.send_after(self(), :tick, @render_intvl)
receive do
:tick -> render_interval()
end
end
defp render(state) do
state = %{
state
| progress_char: next_progress_char(state.progress_char),
progress_color: next_progress_color(state.progress_color)
}
Owl.LiveScreen.update(:ask, status_box(state))
state
end
defp status_box(state) do
cols = Owl.IO.columns()
rows = Owl.IO.rows() - 2
state
|> status()
|> Owl.Box.new(
min_height: 1,
min_width: cols,
max_height: rows,
max_width: cols,
horizontal_align: :left,
vertical_align: :top,
truncate_lines: true,
border_style: :none
)
end
defp status(state) do
state.statuses
|> Map.keys()
|> Enum.sort()
|> Enum.map(fn id ->
{msg, detail, outcome} = Map.get(state.statuses, id)
format_msg(state, msg, detail, outcome)
end)
|> Enum.join("\n")
end
defp format_msg(state, msg, detail, outcome) do
glyph = outcome_glyph(state, outcome)
if is_nil(detail) do
[glyph, " ", Owl.Data.tag(msg, :cyan)]
else
detail =
if String.contains?(detail, "\n") do
detail |> String.split("\n") |> hd()
else
detail
end
[glyph, " ", Owl.Data.tag([msg, ":"], :cyan), " ", Owl.Data.tag(detail, :yellow)]
end
|> Owl.Data.to_chardata()
end
defp outcome_glyph(state, outcome) do
case outcome do
:processing -> Owl.Data.tag(state.progress_char, state.progress_color)
:ok -> Owl.Data.tag("✔", :green)
:error -> Owl.Data.tag("✖", :red)
end
end
defp start_bs_label_changer(status_id) do
Task.start(fn ->
phrases = Enum.shuffle(@bullshit_sf_phrases)
Enum.each(phrases, fn phrase ->
update_step(status_id, phrase)
Process.sleep(@bullshit_rotation_interval)
end)
# Restart the cycle after completing the list
start_bs_label_changer(status_id)
end)
end
# ⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠏
defp next_progress_char("⠋"), do: "⠙"
defp next_progress_char("⠙"), do: "⠹"
defp next_progress_char("⠹"), do: "⠸"
defp next_progress_char("⠸"), do: "⠼"
defp next_progress_char("⠼"), do: "⠴"
defp next_progress_char("⠴"), do: "⠦"
defp next_progress_char("⠦"), do: "⠧"
defp next_progress_char("⠧"), do: "⠏"
defp next_progress_char("⠏"), do: "⠋"
# :magenta :red :yellow :green :blue :cyan
defp next_progress_color(:magenta), do: :red
defp next_progress_color(:red), do: :yellow
defp next_progress_color(:yellow), do: :green
defp next_progress_color(:green), do: :blue
defp next_progress_color(:blue), do: :cyan
defp next_progress_color(:cyan), do: :magenta
end