defmodule ChangedReloader do use Application # See http://elixir-lang.org/docs/stable/elixir/Application.html # for more information on OTP Applications def start(_type, _args) do import Supervisor.Spec, warn: false children = [ # Define workers and child supervisors to be supervised worker(ChangedReloader.Worker, []) ] # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: Remix.Supervisor] Supervisor.start_link(children, opts) end defmodule Worker do use GenServer defmodule State, do: defstruct last_mtime: nil def start_link do Process.send_after(__MODULE__, :poll_and_reload, 10000) GenServer.start_link(__MODULE__, %State{}, name: Remix.Worker) end def handle_info(:poll_and_reload, state) do current_mtimes = get_current_mtime {latest_mtime, _} = List.first(current_mtimes) Enum.filter(current_mtimes, fn {mtime, _} -> mtime > state.last_mtime end) |> Enum.each(fn {_, file} -> IEx.Helpers.c(file) end) Process.send_after(__MODULE__, :poll_and_reload, 1000) {:noreply, %State{last_mtime: latest_mtime}} end def get_current_mtime, do: get_current_mtime("lib") def get_current_mtime(dir) do case File.ls(dir) do {:ok, files} -> get_current_mtime(files, [], dir) _ -> nil end end def get_current_mtime([], mtimes, _cwd) do mtimes |> List.flatten |> Enum.sort |> Enum.reverse end def get_current_mtime([h | tail], mtimes, cwd) do path = "#{cwd}/#{h}" mtime = case File.dir?(path) do true -> get_current_mtime(path) false -> {File.stat!(path).mtime, path} end get_current_mtime(tail, [mtime | mtimes], cwd) end end end