diff --git a/lib/mix_tasks.ex b/lib/mix_tasks.ex index 45ed17a..6d7d90f 100644 --- a/lib/mix_tasks.ex +++ b/lib/mix_tasks.ex @@ -100,6 +100,25 @@ defmodule Mix.Tasks.Aoc do create_file("#{tests_dir(day)}#{test}.#{part}", IO.read(:stdio, :eof)) end + defp run(day, ["test", "watch"]) do + {:ok, pid} = Mix.Tasks.Aoc.Watcher.start_link({[dirs: ["lib/", "test/day#{day}/"]], self()}) + Process.monitor(pid) + loop = fn (loop) -> + IO.puts(IO.ANSI.clear() <> IO.ANSI.cursor(0, 0)) + IO.puts "At #{DateTime.utc_now(:second)}:" + System.shell("mix compile") + :code.purge(module(day)) + :code.purge(Aoc2023.Common) + :code.load_file(module(day)) + run(day, ["test"]) + receive do + :update -> loop.(loop) + {:DOWN, _, :process, ^pid, _} -> nil + end + end + loop.(loop) + end + defp run(day, ["test"]) do mod = module(day) tests = tests(day) @@ -166,4 +185,28 @@ defmodule Mix.Tasks.Aoc do defp run_file(day, file \\ nil) do module(day).main(if file, do: read(file), else: IO.read(:stdio, :eof)) end + + + defmodule Watcher do + use GenServer + + def start_link(args) do + GenServer.start_link(__MODULE__, args) + end + + def init({args, callback}) do + {:ok, watcher_pid} = FileSystem.start_link(args) + FileSystem.subscribe(watcher_pid) + {:ok, %{watcher_pid: watcher_pid, callback: callback}} + end + + def handle_info({:file_event, watcher_pid, {_path, _events}}, %{watcher_pid: watcher_pid, callback: callback} = state) do + send(callback, :update) + {:noreply, state} + end + + def handle_info({:file_event, _watcher_pid, :stop}, state) do + {:noreply, state} + end + end end diff --git a/mix.exs b/mix.exs index dbe42ef..fda6d51 100644 --- a/mix.exs +++ b/mix.exs @@ -19,7 +19,8 @@ defmodule Aoc2023.MixProject do defp deps do [ - {:httpoison, "~> 2.0"} + httpoison: "~> 2.0", + file_system: "~> 1.0" ] end end diff --git a/mix.lock b/mix.lock index 14e8515..41c7099 100644 --- a/mix.lock +++ b/mix.lock @@ -1,5 +1,6 @@ %{ "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, + "file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"}, "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"}, "httpoison": {:hex, :httpoison, "2.2.1", "87b7ed6d95db0389f7df02779644171d7319d319178f6680438167d7b69b1f3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "51364e6d2f429d80e14fe4b5f8e39719cacd03eb3f9a9286e61e216feac2d2df"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},