defmodule Credo.Watcher do alias Credo.CLI.Output.UI @default_watch_path "." def run(argv) do spawn(fn -> path = get_path(argv) UI.puts([ :bright, :magenta, "watch: ", :reset, :faint, "Now watching for changes in '#{path}' ...\n" ]) start_watcher_process(path) watch_loop(argv, nil) end) end defp start_watcher_process(path) do {:ok, pid} = FileSystem.start_link(dirs: [path]) FileSystem.subscribe(pid) end defp watch_loop(argv, exec_from_last_run) do receive do {:file_event, _worker_pid, {file_path, events}} -> elixir_file? = file_path =~ ~r/\.exs?$/ in_ignored_directory? = file_path =~ ~r/\/deps\/$/ relative_path = Path.relative_to_cwd(file_path) exec = if Enum.member?(events, :closed) && elixir_file? && !in_ignored_directory? do UI.puts([:bright, :magenta, "watch: ", :reset, :faint, relative_path, "\n"]) file_that_changed = Path.relative_to_cwd(relative_path) Credo.run(exec_from_last_run || argv, [file_that_changed]) else # data = inspect({System.os_time(:milliseconds), events, relative_path}) # UI.puts([:bright, :magenta, "changes: ", :reset, :faint, data]) exec_from_last_run end watch_loop(argv, exec) end end defp get_path([]), do: @default_watch_path defp get_path(argv) do {_options, argv_rest, _errors} = OptionParser.parse(argv, strict: [watch: :boolean]) path = Enum.find(argv_rest, fn path -> File.exists?(path) or path =~ ~r/[\?\*]/ end) path || @default_watch_path end end