1
0
mirror of https://github.com/jiriks74/presence.nvim synced 2024-11-23 20:37:50 +01:00

Have snappier multi-window updates via focus events

- Fix multi-window presence
- Update on FocusGained events
- Add BufAdd handler and properly cancel on WinLeave
This commit is contained in:
Andrew Kwon 2021-05-31 17:44:31 -07:00
parent 9c761d486b
commit 12d177985b
3 changed files with 142 additions and 34 deletions

@ -3,9 +3,12 @@ function presence#SetAutoCmds()
augroup presence_events
autocmd!
if exists("g:presence_auto_update") && g:presence_auto_update
autocmd BufEnter * lua package.loaded.presence:update()
autocmd TextChanged * lua package.loaded.presence:update(nil, true)
autocmd VimLeavePre * lua package.loaded.presence:unregister_self()
autocmd FocusGained * lua package.loaded.presence:handle_focus_gained()
autocmd TextChanged * lua package.loaded.presence:handle_text_changed()
autocmd VimLeavePre * lua package.loaded.presence:handle_vim_leave_pre()
autocmd WinEnter * lua package.loaded.presence:handle_win_enter()
autocmd WinLeave * lua package.loaded.presence:handle_win_leave()
autocmd BufAdd * lua package.loaded.presence:handle_buf_add()
endif
augroup END
endfunction

@ -4,4 +4,5 @@ return {
["NERD_tree_"] = "NERDTree",
["[defx] default-"] = "Defx",
["netrw"] = "Netrw",
["TelescopePrompt"] = "Telescope"
}

@ -120,6 +120,7 @@ function Presence:setup(options)
local seed_nums = {}
self.socket:gsub(".", function(c) table.insert(seed_nums, c:byte()) end)
self.id = self.discord.generate_uuid(tonumber(table.concat(seed_nums)) / os.clock())
self.log:debug(string.format("Using id %s", self.id))
-- Ensure auto-update config is reflected in its global var setting
vim.api.nvim_set_var("presence_auto_update", options.auto_update)
@ -138,16 +139,23 @@ function Presence:setup(options)
return self
end
-- To ensure consistent option values, coalesce true and false values to 1 and 0
function Presence.coalesce_option(value)
if type(value) == "boolean" then
return value and 1 or 0
end
return value
end
-- Set option using either vim global or setup table
function Presence:set_option(option, default, validate)
default = self.coalesce_option(default)
validate = validate == nil and true or validate
local g_variable = string.format("presence_%s", option)
-- Coalesce boolean options to integer 0 or 1
if type(self.options[option]) == "boolean" then
self.options[option] = self.options[option] and 1 or 0
end
self.options[option] = self.coalesce_option(self.options[option])
if validate then
-- Warn on any duplicate user-defined options
@ -297,17 +305,17 @@ function Presence:get_discord_socket()
end
-- Gets the file path of the current vim buffer
function Presence.get_current_buffer(on_buffer)
vim.schedule(function()
local current_buffer = vim.api.nvim_get_current_buf()
local buffer = vim.api.nvim_buf_get_name(current_buffer)
on_buffer(buffer)
end)
function Presence.get_current_buffer()
local current_buffer = vim.api.nvim_get_current_buf()
return vim.api.nvim_buf_get_name(current_buffer)
end
-- Gets the current project name
function Presence:get_project_name(file_path)
if not file_path then
return nil
end
-- Escape quotes in the file path
file_path = file_path:gsub([["]], [[\"]])
@ -356,24 +364,26 @@ end
-- Get the status text for the current buffer
function Presence:get_status_text(filename)
local file_explorer = file_explorers[vim.bo.filetype:match "[^%d]+"]
or file_explorers[(filename or ""):match "[^%d]+"]
local plugin_manager = plugin_managers[vim.bo.filetype]
if file_explorer then
return string.format(self.options.file_explorer_text, file_explorer)
elseif plugin_manager then
return string.format(self.options.plugin_manager_text, plugin_manager)
end
if not filename or filename == "" then return nil end
if vim.bo.modifiable and not vim.bo.readonly then
if vim.bo.filetype == "gitcommit" then
return string.format(self.options.git_commit_text, filename)
else
elseif filename then
return string.format(self.options.editing_text, filename)
end
else
local file_explorer = file_explorers[vim.bo.filetype:match "[^%d]+"]
or file_explorers[filename:match "[^%d]+"]
local plugin_manager = plugin_managers[vim.bo.filetype]
if file_explorer then
return string.format(self.options.file_explorer_text, file_explorer)
elseif plugin_manager then
return string.format(self.options.plugin_manager_text, plugin_manager)
else
return string.format(self.options.reading_text, filename)
end
elseif filename then
return string.format(self.options.reading_text, filename)
end
end
@ -461,6 +471,12 @@ end
-- Update Rich Presence for the provided vim buffer
function Presence:update_for_buffer(buffer, should_debounce)
-- Avoid unnecessary updates if the previous activity was for the current buffer
-- (allow same-buffer updates when line numbers are enabled)
if self.options.enable_line_number == 0 and self.last_activity.file == buffer then
self.log:debug(string.format("Activity already set for %s, skipping...", buffer))
return
end
local activity_set_at = os.time()
-- If we shouldn't debounce and we trigger an activity, keep this value the same.
@ -472,7 +488,7 @@ function Presence:update_for_buffer(buffer, should_debounce)
-- Parse vim buffer
local filename = self.get_filename(buffer, self.os.path_separator)
local parent_dirpath = self.get_dir_path(buffer, self.os.path_separator)
local extension = self.get_file_extension(filename)
local extension = filename and self.get_file_extension(filename) or nil
self.log:debug(string.format("Parsed filename %s with %s extension", filename, extension or "no"))
@ -498,6 +514,9 @@ function Presence:update_for_buffer(buffer, should_debounce)
}
local status_text = self:get_status_text(filename)
if not status_text then
return self.log:debug("No status text for the given buffer, skipping...")
end
local activity = {
state = status_text,
@ -521,6 +540,7 @@ function Presence:update_for_buffer(buffer, should_debounce)
self.workspace = nil
self.last_activity = {
id = self.id,
file = buffer,
set_at = activity_set_at,
relative_set_at = relative_activity_set_at,
@ -544,6 +564,7 @@ function Presence:update_for_buffer(buffer, should_debounce)
self.workspace = project_path
self.last_activity = {
id = self.id,
file = buffer,
set_at = activity_set_at,
relative_set_at = relative_activity_set_at,
@ -567,6 +588,7 @@ function Presence:update_for_buffer(buffer, should_debounce)
self.workspace = nil
self.last_activity = {
id = self.id,
file = buffer,
set_at = activity_set_at,
relative_set_at = relative_activity_set_at,
@ -588,8 +610,10 @@ function Presence:update_for_buffer(buffer, should_debounce)
end
-- Sync activity to all peers
self.log:debug("Sync activity to all peers...")
self:sync_self_activity()
self.log:debug("Setting Discord activity...")
self.discord:set_activity(activity, function(err)
if err then
self.log:error("Failed to set activity in Discord: "..err)
@ -623,16 +647,16 @@ Presence.update = Presence.discord_event(function(self, buffer, should_debounce)
if buffer then
self:update_for_buffer(buffer, should_debounce)
else
self.get_current_buffer(function(current_buffer)
if not current_buffer or current_buffer == "" then
return self.log:debug("Current buffer not named, skipping...")
end
self:update_for_buffer(current_buffer, should_debounce)
vim.schedule(function()
self:update_for_buffer(self.get_current_buffer(), should_debounce)
end)
end
end)
--------------------------------------------------
-- Presence peer-to-peer API
--------------------------------------------------
-- Register some remote peer
function Presence:register_peer(id, socket)
self.log:debug(string.format("Registering peer %s...", id))
@ -813,4 +837,84 @@ function Presence:stop()
end)
end
--------------------------------------------------
-- Presence event handlers
--------------------------------------------------
-- FocusGained events force-update the presence for the current buffer unless it's a quickfix window
function Presence:handle_focus_gained()
self.log:debug("Handling FocusGained event...")
if vim.bo.filetype == "qf" then
self.log:debug("Skipping presence update for quickfix window...")
return
end
self:update()
end
-- TextChanged events debounce current buffer presence updates
function Presence:handle_text_changed()
self.log:debug("Handling TextChanged event...")
self:update(nil, true)
end
-- VimLeavePre events unregister the leaving instance to all peers and sets activity for the first peer
function Presence:handle_vim_leave_pre()
self.log:debug("Handling VimLeavePre event...")
self:unregister_self()
end
-- WinEnter events force-update the current buffer presence unless it's a quickfix window
function Presence:handle_win_enter()
self.log:debug("Handling WinEnter event...")
vim.schedule(function()
if vim.bo.filetype == "qf" then
self.log:debug("Skipping presence update for quickfix window...")
return
end
self:update()
end)
end
-- WinLeave events cancel the current buffer presence
function Presence:handle_win_leave()
self.log:debug("Handling WinLeave event...")
local current_window = vim.api.nvim_get_current_win()
vim.schedule(function()
-- Avoid canceling presence when switching to a quickfix window
if vim.bo.filetype == "qf" then
self.log:debug("Not canceling presence due to switching to quickfix window...")
return
end
-- Avoid canceling presence when switching between windows
if current_window ~= vim.api.nvim_get_current_win() then
self.log:debug("Not canceling presence due to switching to a window within the same instance...")
return
end
self.log:debug("Canceling presence due to leaving window...")
self:cancel()
end)
end
-- WinLeave events cancel the current buffer presence
function Presence:handle_buf_add()
self.log:debug("Handling BufAdd event...")
vim.schedule(function()
if vim.bo.filetype == "qf" then
self.log:debug("Skipping presence update for quickfix window...")
return
end
self:update()
end)
end
return Presence