# inotify_run - tool for auto-running a command on filesystem events
#
# Simply prefix any command you wish to run with `inotify_run`, and it will be
# automatically re-run every time a file is saved in or under the current
# working directory.
#
# For example, to automatically compile and run your test:
# > inotify_run bazel test //my/cool/package:test
#
# If you want to ignore a specific file, you may do so by setting the
# INORUN_EXCLUDE environment variable:
# > INORUN_EXCLUDE=test.png inotify_run bazel run :png_writer -- --out test.png
#
# And, if you frequently operate in a particular CWD where temporary files are
# used, you can create a `.inorun_ignore` file, containing one ignored file
# regex per line. This file will automatically be read in, and added to the list
# of ignored file regexes

function _inotify_run_ignore_file_regex {
  echo -n ".*/~.*"          # Ignore any files starting with a tilde (~)
  echo -n "|${INORUN_EXCLUDE:-.git}"
  echo -n "|./.git/.*$"     # Ignore the entire .git/ directory
  echo -n "|.*4913$"        # Vim 4913 files: https://stackoverflow.com/questions/41842835
  echo -n "|.*index.lock$"  # Git's index.lock file
  echo -n "|.*swp$"         # Vim swap files
  if [ -f .inorun_ignore ]; then
    while read exclude_line; do
      echo -n "|$exclude_line"
    done <.inorun_ignore
  fi
}

function _inotify_run_do {
  echo -e "\033[38;5;64m >>> $@\033[0m"
  "$@"
  exit_code=$?
  if [[ $exit_code != 0 ]]; then
    echo -e "\e[41m\e[1;37m!!! Exited: $exit_code !!!\033[0m"
  else
    echo "Exited: $exit_code"
  fi
  echo
}

function _inotifyrun {
  status_format="$(echo -e "\033[38;5;64m%T %w/%f : %e \033[0m written")"

  # Using do-while loop
  while : ; do
    _inotify_run_do "$@"

    inotifywait --quiet --recursive \
        --event close_write \
        --format "$status_format" \
        --timefmt "%T" \
        --exclude "$(_inotify_run_ignore_file_regex)" . || break
  done
}

function _fswatch {
  _inotify_run_do "$@"
  fswatch "$(_inotify_run_ignore_file_regex)" -0 ./ | while read -d "" event; do
    echo -e "\033[1;33m$event\033[0m written"
    _inotify_run_do "$@"
  done
}

function inotify_run {
  case "$OSTYPE" in
    darwin*) # Mac OSX
      _fswatch "$@"
      ;;
    linux*) # Linux
      _inotifyrun "$@"
      ;;
    msys*) # Lightweight shell and GNU utilities compiled for Windows (part of MinGW)
      _fswatch "$@"
      ;;
    cygwin*) # POSIX compatibility layer and Linux environment emulation for Windows
      _fswatch "$@"
      ;;
    solaris*)
      _fswatch "$@"
      ;;
    bsd*)
      _fswatch "$@"
      ;;
    *)
      echo "Unknown OS \"$OSTYPE\""
      echo "Defaulting to fswatch..."
      _fswatch "$@"
      ;;
  esac
}

