watcher.ex (1700B)
1 defmodule Credo.Watcher do 2 alias Credo.CLI.Output.UI 3 4 @default_watch_path "." 5 6 def run(argv) do 7 spawn(fn -> 8 path = get_path(argv) 9 10 UI.puts([ 11 :bright, 12 :magenta, 13 "watch: ", 14 :reset, 15 :faint, 16 "Now watching for changes in '#{path}' ...\n" 17 ]) 18 19 start_watcher_process(path) 20 21 watch_loop(argv, nil) 22 end) 23 end 24 25 defp start_watcher_process(path) do 26 {:ok, pid} = FileSystem.start_link(dirs: [path]) 27 28 FileSystem.subscribe(pid) 29 end 30 31 defp watch_loop(argv, exec_from_last_run) do 32 receive do 33 {:file_event, _worker_pid, {file_path, events}} -> 34 elixir_file? = file_path =~ ~r/\.exs?$/ 35 in_ignored_directory? = file_path =~ ~r/\/deps\/$/ 36 relative_path = Path.relative_to_cwd(file_path) 37 38 exec = 39 if Enum.member?(events, :closed) && elixir_file? && !in_ignored_directory? do 40 UI.puts([:bright, :magenta, "watch: ", :reset, :faint, relative_path, "\n"]) 41 42 file_that_changed = Path.relative_to_cwd(relative_path) 43 44 Credo.run(exec_from_last_run || argv, [file_that_changed]) 45 else 46 # data = inspect({System.os_time(:milliseconds), events, relative_path}) 47 # UI.puts([:bright, :magenta, "changes: ", :reset, :faint, data]) 48 exec_from_last_run 49 end 50 51 watch_loop(argv, exec) 52 end 53 end 54 55 defp get_path([]), do: @default_watch_path 56 57 defp get_path(argv) do 58 {_options, argv_rest, _errors} = OptionParser.parse(argv, strict: [watch: :boolean]) 59 60 path = Enum.find(argv_rest, fn path -> File.exists?(path) or path =~ ~r/[\?\*]/ end) 61 62 path || @default_watch_path 63 end 64 end