8000 Add basic filewatcher by CKolkey · Pull Request #788 · NeogitOrg/neogit · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add basic filewatcher #788

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,16 @@ neogit.setup {
disable_commit_confirmation = false,
-- Uses `vim.notify` instead of the built-in notification system.
disable_builtin_notifications = false,
-- Changes what mode the Commit Editor starts in. `true` will leave nvim in normal mode, `false` will change nvim to insert mode, and `"auto"` will change nvim to insert mode IF the commit message is empty, otherwise leaving it in normal mode.
-- Changes what mode the Commit Editor starts in. `true` will leave nvim in normal mode, `false` will change nvim to
-- insert mode, and `"auto"` will change nvim to insert mode IF the commit message is empty, otherwise leaving it in
-- normal mode.
disable_insert_on_commit = true,
-- When enabled, will watch the `.git/` directory for changes and refresh the status buffer in response to filesystem
-- events.
filewatcher = {
interval = 1000,
enabled = true,
},
-- Allows a different telescope sorter. Defaults to 'fuzzy_with_index_bias'. The example below will use the native fzf
-- sorter instead. By default, this function returns `nil`.
telescope_sorter = function()
Expand Down
10 changes: 10 additions & 0 deletions lua/neogit/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ end
---@field rebase NeogitConfigSection|nil
---@field sequencer NeogitConfigSection|nil

---@class NeogitFilewatcherConfig
---@field interval number
---@field enabled boolean
---@field filewatcher NeogitFilewatcherConfig|nil

---@alias NeogitConfigMappingsFinder "Select" | "Close" | "Next" | "Previous" | "MultiselectToggleNext" | "MultiselectTogglePrevious" | "NOP" | false
---@alias NeogitConfigMappingsStatus "Close" | "InitRepo" | "Depth1" | "Depth2" | "Depth3" | "Depth4" | "Toggle" | "Discard" | "Stage" | "StageUnstaged" | "StageAll" | "Unstage" | "UnstageStaged" | "DiffAtFile" | "CommandHistory" | "Console" | "RefreshBuffer" | "GoToFile" | "VSplitOpen" | "SplitOpen" | "TabOpen" | "HelpPopup" | "DiffPopup" | "PullPopup" | "RebasePopup" | "MergePopup" | "PushPopup" | "CommitPopup" | "LogPopup" | "RevertPopup" | "StashPopup" | "CherryPickPopup" | "BranchPopup" | "FetchPopup" | "ResetPopup" | "RemotePopup" | "GoToPreviousHunkHeader" | "GoToNextHunkHeader" | false | fun()

Expand All @@ -61,6 +66,7 @@ end
---@field status? { [string]: NeogitConfigMappingsStatus } A dictionary that uses status commands to set a single keybind

---@class NeogitConfig Neogit configuration settings
---@field filewatcher? NeogitFilewatcherConfig Values for filewatcher
---@field disable_hint? boolean Remove the top hint in the Status buffer
---@field disable_context_highlighting? boolean Disable context highlights based on cursor position
---@field disable_signs? boolean Special signs to draw for sections etc. in Neogit
Expand Down Expand Up @@ -100,6 +106,10 @@ function M.get_default_values()
disable_signs = false,
disable_commit_confirmation = false,
disable_builtin_notifications = false,
filewatcher = {
interval = 1000,
enabled = true,
},
telescope_sorter = function()
return nil
end,
Expand Down
4 changes: 2 additions & 2 deletions lua/neogit/lib/git/repository.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ local function empty_state()
local Path = require("plenary.path")

return {
git_path = function(path)
return Path.new(root):joinpath(".git", path)
git_path = function(...)
return Path.new(root):joinpath(".git", ...)
end,
cwd = vim.fn.getcwd(),
git_root = root,
Expand Down
19 changes: 19 additions & 0 deletions lua/neogit/lib/util.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local a = require("plenary.async")
local uv = vim.loop

---@generic T: any
---@generic U: any
Expand Down Expand Up @@ -360,6 +361,23 @@ local function pad_right(s, len)
return s .. string.rep(" ", math.max(len - #s, 0))
end

--- Debounces a function on the trailing edge.
---
--- @generic F: function
--- @param ms number Timeout in ms
--- @param fn F Function to debounce
--- @return F Debounced function.
local function debounce_trailing(ms, fn)
local timer = assert(uv.new_timer())
return function(...)
local argv = { ... }
timer:start(ms, 0, function()
timer:stop()
fn(unpack(argv))
end)
end
end

return {
time = time,
time_async = time_async,
Expand Down Expand Up @@ -394,4 +412,5 @@ return {
reverse = reverse,
flat_map = flat_map,
str_wrap = str_wrap,
debounce_trailing = debounce_trailing,
}
7 changes: 7 additions & 0 deletions lua/neogit/status.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ local LineBuffer = require("neogit.lib.line_buffer")
local fs = require("neogit.lib.fs")
local input = require("neogit.lib.input")
local util = require("neogit.lib.util")
local watcher = require("neogit.watcher")

local map = require("neogit.lib.util").map
local api = vim.api
Expand Down Expand Up @@ -602,6 +603,8 @@ local function close(skip_close)
if not skip_close then
M.status_buffer:close()
end

M.watcher:stop()
notif.delete_all()
M.status_buffer = nil
vim.o.autochdir = M.prev_autochdir
Expand Down Expand Up @@ -1091,6 +1094,7 @@ local cmd_func_map = function()
end),

["RefreshBuffer"] = function()
notif.create("Refreshing Status", vim.log.levels.INFO)
dispatch_refresh(true)
end,

Expand Down Expand Up @@ -1259,6 +1263,9 @@ function M.create(kind, cwd)
logger.debug("[STATUS BUFFER]: Dispatching initial render")
refresh(true, "Buffer.create")
end,
after = function()
M.watcher = watcher.new(git.repo.git_path():absolute())
end,
}
end

Expand Down
82 changes: 82 additions & 0 deletions lua/neogit/watcher.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
local uv = vim.loop

local config = require("neogit.config")
local logger = require("neogit.logger")
local util = require("neogit.lib.util")

local a = require("plenary.async")

local watch_gitdir_handler = a.void(function()
logger.debug("[WATCHER] Dispatching Refresh")
require("neogit.status").dispatch_refresh()
end)

local watch_gitdir_handler_db =
util.debounce_trailing(config.values.filewatcher.interval, watch_gitdir_handler)

local fs_event_handler = function(err, filename, events)
if err then
logger.error(string.format("[WATCHER] Git dir update error: %s", err))
return
end

local info = string.format(
"[WATCHER] Git dir update: '%s' %s",
filename,
vim.inspect(events, { indent = "", newline = " " })
)

-- stylua: ignore
if
filename == nil or
filename:match("%.lock$") or
filename:match("COMMIT_EDITMSG") or
filename:match("~$")
then
logger.debug(string.format("%s (ignoring)", info))
return
end

logger.debug(info)
watch_gitdir_handler_db()
end

-- Adapted from https://github.com/lewis6991/gitsigns.nvim/blob/main/lua/gitsigns/watcher.lua#L103
--- @param gitdir string
--- @return uv_fs_event_t
local function start(gitdir)
local w = assert(uv.new_fs_event())
w:start(gitdir, {}, fs_event_handler)

return w
end

---@class Watcher
---@field gitdir string
---@field fs_event_handler uv_fs_event_t|nil
local Watcher = {}
Watcher.__index = Watcher

function Watcher:stop()
if self.fs_event_handler then
logger.debug("[WATCHER] Stopped watching git dir: " .. self.gitdir)
self.fs_event_handler:stop()
end
end

function Watcher:create(gitdir)
self.gitdir = gitdir

if config.values.filewatcher.enabled then
logger.debug("[WATCHER] Watching git dir: " .. gitdir)
self.fs_event_handler = start(gitdir)
end

return self
end

function Watcher.new(...)
return Watcher:create(...)
end

return Watcher
0