Home

Awesome

fwatch.nvim

fwatch.nvim lets you watch files or directories for changes and then run vim commands or lua functions.

fwatch.watch("a_file", "echo 'it changed!'")
fwatch.watch("b_file", {
  on_event = function()
    print("it changed!")
  end
})

The code is extremely simple and I encourage you to read the source, as you may not require a "plugin" to achieve your goals. fwatch.nvim may just act as some example code for you.

Requirements

Installation

Install via any package managment system:

make_pact 'rktjmp/fwatch.nvim'

Usage

Watch a file and run a vim command

local fwatch = require('fwatch')
fwatch.watch("a_file", "echo 'a_file changed'")

Watch a file and run a lua function

local fwatch = require('fwatch')
fwatch.watch("a_file", {
  on_event = function()
    print('a_file changed')
  end
})

Watch a directory and run a lua function

local fwatch = require('fwatch')
local limit = 10

fwatch.watch("a_dir", {
  on_event = function(filename, events, unwatch)
    limit = limit - 1
    if limit <= 0 then
      -- *immediately* stop.
      -- without return, the callback would continue executing,
      -- but not be run on the next change.
      print("10 changes, very sleepy.")
      return unwatch()
    end

    print("a_dir/" .. filename .. " was changed")
  end,
  on_error = function(error, unwatch)
    -- disable watcher
    unwatch()
    -- note, print still occurs even though we unwatched *future* events
    print("An error occured: " .. error)
  end
})

API

fwatch.watch(path, vim_command_or_function_table)

Watch path, execute vim_command_or_function_table on change or rename. Returns a handle to the watcher.

path :: string

Path to file or directory to be watched. path may be relative to the current working directory or absolute. path is not expanded, so ~/my_file.txt is not expanded to /home/me/my_file.txt. You must use existing vim or lua functions to expand paths.

vim_command_or_function_table :: string | {on_event :: function, on_error :: function}

Either a string, which is executed as a vim ex command, or a table of callbacks.

The string is passed to vim.cmd and is automatically prefixed with :.

-- reload colorscheme whenever path changes
fwatch.watch(path, "colorscheme herbert")

The table must contain an on_event = function key-value pair, it may contain an on_error = function key-value pair.

fwatch.watch(path, {
  on_event = function()
    -- reload colorscheme whenever path changes
    vim.cmd("colorscheme herbert")
  end
})

Callbacks

on_event

Called when the watched path changes. on_event is passed:

on_error

Called when the watcher fails for some reason. on_error is passed:

In lua, function parameters are optional, so you may ignore any you do not need. The following are all valid callbacks:

on_event = function()
  print("an event")
end
on_event = function(filename)
  print("an event for " .. filename)
end
on_event = function(filename, events, unwatch)
  if events.rename then print(filename .. " was renamed")
  if events.change then print(filename .. " was changed")
  if events.rename and events.change then
    unwatch()
  end
end

fwatch.once(path, vim_command_or_function_table)

Watch path, execute vim_command_or_function_table on change or rename only once. Returns a handle to the watcher. See fwatch.watch for more details.

fwatch.unwatch(handle)

Disables given watcher.

local handle = fwatch.watch(path, command)
fwatch.unwatch(handle)

Warnings

Watching a file you edit with vim will likely fire multiple times and detatch your watcher because vim swaps files around on save. See using inotify/wait along with vim on stackoverflow.

You could call unwatch() in every callback and re-call fwatch.watch() with the given filename to watch the new file.

Maybe

:Fwatchers - show list of watchers?

:Fwatch "path" "command" ?

Artwork

GH image is a play on the cover art for the fantastic game Firewatch by the brilliant team of Campo Santo, orignal art at least partly by the talented Olly Moss.