Extracted watcher and runner into supervision tree.
This commit is contained in:
@@ -16,34 +16,6 @@ defmodule Display do
|
|||||||
{:noreply, %{state | clear_screen: false}}
|
{:noreply, %{state | clear_screen: false}}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_cast({:invalid, koan, modules}, state) do
|
|
||||||
Notifications.invalid_koan(koan, modules)
|
|
||||||
|> IO.puts
|
|
||||||
|
|
||||||
{:noreply, state}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_cast({:show_failure, failure, module, name}, state) do
|
|
||||||
format(failure, module, name)
|
|
||||||
|> IO.puts
|
|
||||||
|
|
||||||
{:noreply, state}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_cast({:show_compile_error, error}, state) do
|
|
||||||
Failure.show_compile_error(error)
|
|
||||||
|> IO.puts
|
|
||||||
|
|
||||||
{:noreply, state}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_cast(:congratulate, state) do
|
|
||||||
Notifications.congratulate
|
|
||||||
|> IO.puts
|
|
||||||
|
|
||||||
{:noreply, state}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_cast(:clear_screen, state = %{clear_screen: true}) do
|
def handle_cast(:clear_screen, state = %{clear_screen: true}) do
|
||||||
IO.puts(ANSI.clear)
|
IO.puts(ANSI.clear)
|
||||||
IO.puts(ANSI.home)
|
IO.puts(ANSI.home)
|
||||||
@@ -55,19 +27,23 @@ defmodule Display do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def invalid_koan(koan, modules) do
|
def invalid_koan(koan, modules) do
|
||||||
GenServer.cast(__MODULE__, {:invalid, koan, modules})
|
Notifications.invalid_koan(koan, modules)
|
||||||
|
|> IO.puts
|
||||||
end
|
end
|
||||||
|
|
||||||
def show_failure(failure, module, name) do
|
def show_failure(failure, module, name) do
|
||||||
GenServer.cast(__MODULE__, {:show_failure, failure, module, name})
|
format(failure, module, name)
|
||||||
|
|> IO.puts
|
||||||
end
|
end
|
||||||
|
|
||||||
def show_compile_error(error) do
|
def show_compile_error(error) do
|
||||||
GenServer.cast(__MODULE__, {:show_compile_error, error})
|
Failure.show_compile_error(error)
|
||||||
|
|> IO.puts
|
||||||
end
|
end
|
||||||
|
|
||||||
def congratulate do
|
def congratulate do
|
||||||
GenServer.cast(__MODULE__, :congratulate)
|
Notifications.congratulate
|
||||||
|
|> IO.puts
|
||||||
end
|
end
|
||||||
|
|
||||||
def clear_screen do
|
def clear_screen do
|
||||||
|
@@ -7,7 +7,9 @@ defmodule ElixirKoans do
|
|||||||
|
|
||||||
children = [
|
children = [
|
||||||
worker(Display, []),
|
worker(Display, []),
|
||||||
worker(Tracker, [])
|
worker(Tracker, []),
|
||||||
|
worker(Runner, []),
|
||||||
|
worker(Watcher, [])
|
||||||
]
|
]
|
||||||
|
|
||||||
opts = [strategy: :one_for_one, name: ElixirKoans.Supervisor]
|
opts = [strategy: :one_for_one, name: ElixirKoans.Supervisor]
|
||||||
|
@@ -7,8 +7,6 @@ defmodule Mix.Tasks.Meditate do
|
|||||||
def run(args) do
|
def run(args) do
|
||||||
Application.ensure_all_started(:elixir_koans)
|
Application.ensure_all_started(:elixir_koans)
|
||||||
Code.compiler_options(ignore_module_conflict: true)
|
Code.compiler_options(ignore_module_conflict: true)
|
||||||
{:ok, watcher} = Watcher.start
|
|
||||||
Process.monitor(watcher)
|
|
||||||
|
|
||||||
Options.start(args)
|
Options.start(args)
|
||||||
|
|
||||||
@@ -22,17 +20,12 @@ defmodule Mix.Tasks.Meditate do
|
|||||||
|> Runner.modules_to_run
|
|> Runner.modules_to_run
|
||||||
|
|
||||||
Tracker.set_total(modules)
|
Tracker.set_total(modules)
|
||||||
|
Tracker.notify_on_complete(self())
|
||||||
|
|
||||||
Runner.run(modules)
|
Runner.run(modules)
|
||||||
|
|
||||||
if Tracker.complete? do
|
Tracker.wait_until_complete()
|
||||||
Display.congratulate
|
Display.congratulate()
|
||||||
exit(:normal)
|
|
||||||
end
|
|
||||||
|
|
||||||
receive do
|
|
||||||
{:DOWN, _references, :process, ^watcher, _reason} -> nil
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp ok?(koan) do
|
defp ok?(koan) do
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
defmodule Runner do
|
defmodule Runner do
|
||||||
|
use GenServer
|
||||||
|
|
||||||
def koan?(koan) do
|
def koan?(koan) do
|
||||||
Keyword.has_key?(koan.__info__(:exports), :all_koans)
|
Keyword.has_key?(koan.__info__(:exports), :all_koans)
|
||||||
@@ -27,14 +28,38 @@ defmodule Runner do
|
|||||||
def modules_to_run, do: Options.initial_koan |> modules_to_run
|
def modules_to_run, do: Options.initial_koan |> modules_to_run
|
||||||
def modules_to_run(start_module), do: Enum.drop_while(modules(), &(&1 != start_module))
|
def modules_to_run(start_module), do: Enum.drop_while(modules(), &(&1 != start_module))
|
||||||
|
|
||||||
def run(modules) do
|
def start_link do
|
||||||
Display.clear_screen()
|
GenServer.start_link(__MODULE__, [], name: __MODULE__)
|
||||||
|
|
||||||
modules
|
|
||||||
|> Enum.take_while( &(run_module(&1) == :passed))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_module(module) do
|
def handle_cast({:run, modules}, _) do
|
||||||
|
flush()
|
||||||
|
send(self(), :run_modules)
|
||||||
|
{:noreply, modules}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_info(:run_modules, []) do
|
||||||
|
{:noreply, []}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_info(:run_modules, [module | rest]) do
|
||||||
|
Display.clear_screen()
|
||||||
|
|
||||||
|
case run_module(module) do
|
||||||
|
:passed ->
|
||||||
|
send(self(), :run_modules)
|
||||||
|
{:noreply, rest}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
{:noreply, []}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run(modules) do
|
||||||
|
GenServer.cast(__MODULE__, {:run, modules})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp run_module(module) do
|
||||||
module
|
module
|
||||||
|> Execute.run_module(&track/3)
|
|> Execute.run_module(&track/3)
|
||||||
|> display
|
|> display
|
||||||
@@ -48,4 +73,12 @@ defmodule Runner do
|
|||||||
:failed
|
:failed
|
||||||
end
|
end
|
||||||
defp display(_), do: :passed
|
defp display(_), do: :passed
|
||||||
|
|
||||||
|
defp flush do
|
||||||
|
receive do
|
||||||
|
_ -> flush()
|
||||||
|
after
|
||||||
|
0 -> :ok
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@@ -1,12 +1,19 @@
|
|||||||
defmodule Tracker do
|
defmodule Tracker do
|
||||||
alias __MODULE__
|
alias __MODULE__
|
||||||
|
|
||||||
defstruct total: 0, koans: MapSet.new(), visited_modules: MapSet.new()
|
defstruct total: 0,
|
||||||
|
koans: MapSet.new(),
|
||||||
|
visited_modules: MapSet.new(),
|
||||||
|
on_complete: :noop
|
||||||
|
|
||||||
def start_link do
|
def start_link do
|
||||||
Agent.start_link(fn -> %Tracker{} end, name: __MODULE__)
|
Agent.start_link(fn -> %Tracker{} end, name: __MODULE__)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def notify_on_complete(pid) do
|
||||||
|
Agent.update(__MODULE__, fn state -> %{state | on_complete: pid} end)
|
||||||
|
end
|
||||||
|
|
||||||
def set_total(modules) do
|
def set_total(modules) do
|
||||||
total = modules
|
total = modules
|
||||||
|> Enum.flat_map(&(&1.all_koans))
|
|> Enum.flat_map(&(&1.all_koans))
|
||||||
@@ -17,6 +24,19 @@ defmodule Tracker do
|
|||||||
|
|
||||||
def completed(module, koan) do
|
def completed(module, koan) do
|
||||||
Agent.update(__MODULE__, &mark_koan_completed(&1, module, koan))
|
Agent.update(__MODULE__, &mark_koan_completed(&1, module, koan))
|
||||||
|
if complete?() do
|
||||||
|
Agent.cast(__MODULE__, fn state ->
|
||||||
|
send(state.on_complete, {self(), :complete})
|
||||||
|
state
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def wait_until_complete() do
|
||||||
|
pid = Process.whereis(Tracker)
|
||||||
|
receive do
|
||||||
|
{^pid, :complete} -> :ok
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp mark_koan_completed(state, module, koan) do
|
defp mark_koan_completed(state, module, koan) do
|
||||||
|
@@ -1,14 +1,13 @@
|
|||||||
defmodule Watcher do
|
defmodule Watcher do
|
||||||
use ExFSWatch, dirs: ["lib/koans"]
|
use ExFSWatch, dirs: ["lib/koans"]
|
||||||
|
|
||||||
|
def start_link do
|
||||||
|
start()
|
||||||
|
end
|
||||||
|
|
||||||
def callback(file, events) do
|
def callback(file, events) do
|
||||||
if Enum.member?(events, :modified) do
|
if Enum.member?(events, :modified) do
|
||||||
file |> normalize |> reload
|
file |> normalize |> reload
|
||||||
|
|
||||||
if Tracker.complete? do
|
|
||||||
Display.congratulate
|
|
||||||
exit(:normal)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user