defmodule Demo do require Logger def walking_owl do owl = """ ,_, {o,o} /) ) ---"-"-- """ |> String.trim_trailing() owl_height = 4 owl_width = 8 width = 60 height = 20 colors = [:red, :yellow, :cyan, :blue, :green] Owl.LiveScreen.add_block(:demo, render: fn nil -> "" state -> owl |> Owl.Tag.new(state.owl_color) |> Owl.Box.new( min_width: width - state.padding_left, min_height: height - state.padding_top, padding_top: state.padding_top, padding_left: state.padding_left ) |> Owl.Tag.new(:magenta) end ) Stream.iterate( %{ padding_top: 10, padding_left: 30, vertical_shift: 1, horizontal_shift: -1, owl_color: Enum.random(colors) }, fn state -> horizontal_shift = cond do state.padding_left == 0 or width - state.padding_left - owl_width == 0 -> state.horizontal_shift * -1 state.padding_left > 0 -> state.horizontal_shift end vertical_shift = cond do state.padding_top == 0 or height - state.padding_top - owl_height == 0 -> state.vertical_shift * -1 state.padding_top > 0 -> state.vertical_shift end owl_color = if vertical_shift != state.vertical_shift or horizontal_shift != state.horizontal_shift do Enum.random(colors) else state.owl_color end padding_left = state.padding_left + horizontal_shift padding_top = state.padding_top + vertical_shift Owl.LiveScreen.update(:demo, %{ padding_left: padding_left, padding_top: padding_top, owl_color: owl_color }) Process.sleep(50) %{ padding_left: padding_left, padding_top: padding_top, vertical_shift: vertical_shift, horizontal_shift: horizontal_shift, owl_color: owl_color } end ) |> Stream.run() end def bar do Owl.ProgressBar.start(id: :users, label: "Creating users", total: 100) Enum.each(1..100, fn _ -> Process.sleep(10) Owl.ProgressBar.inc(id: :users) end) # Wait a bit to give ProgressBar server a time to send last state update to LiveScreen Process.sleep(1) Owl.LiveScreen.flush() end def bars do 1..10 |> Enum.map(fn index -> Task.async(fn -> range = 1..Enum.random(100..500) label = "Demo Progress ##{index}" Owl.ProgressBar.start( id: {:demo, index}, label: label, total: range.last, timer: true, filled_symbol: "#", partial_symbols: [] ) Enum.each(range, fn _ -> Process.sleep(Enum.random(10..120)) Owl.ProgressBar.inc(id: {:demo, index}) end) end) end) |> Task.await_many(:infinity) Owl.LiveScreen.flush() end def demo do Owl.LiveScreen.add_block(:test, state: "hello", render: &Owl.Box.new/1) 1..100 |> Enum.each(fn index -> Owl.LiveScreen.update( :test, index |> to_string() |> Owl.Tag.new(:red) |> Owl.Box.new(title: Owl.Tag.new("Owl", :green)) |> Owl.Tag.new(:cyan) |> List.duplicate(5) |> Enum.reduce(&Owl.Data.zip/2) |> Owl.Box.new( min_width: 80, horizontal_align: :right, min_height: 30, vertical_align: :middle ) |> Owl.Tag.new(:blue) ) Process.sleep(100) end) Owl.LiveScreen.flush() IO.puts(Owl.LiveScreen, "hello") end @moduledoc false def run3 do Owl.ProgressBar.render(%{ label: "Demo", total: 200, current: 8, start_symbol: "|", end_symbol: "|", filled_symbol: "█", partial_symbols: ["▏", "▎", "▍", "▌", "▋", "▊", "▉"], empty_symbol: " ", screen_width: 80, start_time: -576_460_748_012_758_993, current_time: -576_460_748_012_729_828 }) end def run2 do 1..30 |> Enum.map(fn index -> Task.async(fn -> range = 1..Enum.random(100..500) # range = 1..30 label = "Demo Progress ##{index}" Owl.ProgressBar.start( id: {:demo, index}, label: label, total: range.last, filled_symbol: Owl.Tag.new("≡", :cyan), timer: true, bar_width_ratio: 0.3, partial_symbols: [Owl.Tag.new("-", :green), Owl.Tag.new("=", :blue)] # start_symbol: " ", # end_symbol: "▏", # filled_symbol: "█", # partial_symbols: ["▏", "▎", "▍", "▌", "▋", "▊", "▉"] ) Enum.each(range, fn i -> Owl.IO.puts( Owl.LiveScreen, Owl.Data.add_prefix( List.duplicate("test #{i}", 10), [label, ": "] |> Owl.Tag.new(:yellow) ) ) # Process.sleep(Enum.random([10, 15, 20, 30])) Process.sleep(Enum.random(10..120)) Owl.ProgressBar.inc(id: {:demo, index}) end) end) end) |> Task.await_many(:infinity) Owl.LiveScreen.stop() end def run do range = 100..0 total = max(range.first, range.last) bar_width = 70 sleep = 2000 Owl.LiveScreen.add_block(:header, state: "header", render: fn state -> Owl.Box.new(state) |> Owl.Tag.new(:blue) end ) Owl.LiveScreen.add_block(:pipeline, state: "pipeline", render: &List.duplicate(&1, 100) ) Owl.LiveScreen.add_block(:progress, state: range.first, render: fn i -> bar = List.duplicate("█", bar_width - ceil(i / (total / bar_width))) bar |> Owl.Box.new(min_width: bar_width) |> Owl.Tag.new(:yellow) end ) Owl.LiveScreen.add_block(:footer, state: "footer", render: fn state -> state = case state do start_time when is_integer(start_time) -> duration = Float.ceil((System.monotonic_time(:millisecond) - start_time) / 1_000, 2) "#{duration} sec" state -> state end Owl.Box.new(state) |> Owl.Tag.new(:red) end ) Process.sleep(sleep) start_time = System.monotonic_time(:millisecond) {:ok, timer} = :timer.send_interval(5000, Owl.LiveScreen, {:update, :footer, start_time}) range |> Enum.each(fn i -> Owl.IO.puts(Owl.LiveScreen, List.duplicate("test", 100)) Process.sleep(sleep) additional_lines = List.duplicate("\nhello", rem(i, 5)) Owl.LiveScreen.update(:header, ["header #{i}", additional_lines]) Owl.LiveScreen.update(:progress, i) end) :timer.cancel(timer) Owl.LiveScreen.stop() end def run4 do Logger.configure_backend(:console, device: Owl.LiveScreen) Owl.LiveScreen.add_block(:dependency, state: :init, render: fn :init -> "init..." dependency -> ["dependency: ", Owl.Tag.new(dependency, :yellow)] end ) Owl.LiveScreen.add_block(:compiling, render: fn :init -> "init..." filename -> ["compiling: ", Owl.Tag.new(to_string(filename), :cyan)] end ) ["ecto", "phoenix", "ex_doc", "broadway"] |> Enum.each(fn dependency -> Owl.LiveScreen.update(:dependency, dependency) 1..5 |> Enum.map(&"filename#{&1}.ex") |> Enum.each(fn filename -> Owl.LiveScreen.update(:compiling, filename) Process.sleep(1000) Logger.debug("#{filename} compiled for dependency #{dependency}") end) end) end def run5 do Logger.configure_backend(:console, device: Owl.LiveScreen) ["ecto", "phoenix", "ex_doc", "broadway"] |> Enum.map(fn dependency -> Task.async(fn -> block_id = {:dependency, dependency} Owl.LiveScreen.add_block(block_id, state: :init, render: fn :init -> "init..." :compiled -> [ "dependency: ", Owl.Tag.new(dependency, :yellow), "\n", "compiling: ", Owl.Tag.new("done", :green), "\n" ] {:filename, filename} -> [ "dependency: ", Owl.Tag.new(dependency, :yellow), "\n", "compiling: ", Owl.Tag.new(to_string(filename), :cyan), "\n" ] end ) 1..10 |> Enum.map(&"filename#{&1}.ex") |> Enum.each(fn filename -> Owl.LiveScreen.update(block_id, {:filename, filename}) Process.sleep(Enum.random([100, 300, 500, 1000, 1500])) Logger.debug("#{filename} compiled for dependency #{dependency}") end) Owl.LiveScreen.update(block_id, :compiled) end) end) |> Task.await_many(:infinity) end def run6 do Owl.LiveScreen.add_block(:footer, state: "starting...") Process.sleep(1000) Owl.LiveScreen.update(:footer, "...almost done...") Process.sleep(1000) Owl.LiveScreen.update(:footer, "done!!!") Owl.LiveScreen.stop() end def run7 do owl = """ ,_, {o,o} /) ) ---"-"-- """ |> String.trim_trailing() :_ |> List.duplicate(10) |> Enum.map(fn _ -> owl |> Owl.Tag.new(:blue) |> Owl.Box.new() |> Owl.Tag.new(:red) end) |> Enum.reduce(&Owl.Data.zip/2) |> Owl.IO.puts() end end %{ label: "Demo", total: 259, current: 259, bar_width_ratio: 0.7, start_symbol: "[", end_symbol: "]", filled_symbol: "#", partial_symbols: [], empty_symbol: ".", screen_width: 40 }