1
0
mirror of https://github.com/jiriks74/presence.nvim synced 2024-12-05 01:19:01 +01:00

Merge d58bc2821cffc9f378073c9a6f5589cc5aec40e7 into df0a0b52cd0799e99d1b76805d1357ae9c0d017d

This commit is contained in:
Nick 2024-10-07 20:00:31 +02:00 committed by GitHub
commit 9a180d3d3a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -68,6 +68,46 @@ local default_file_assets = require("presence.file_assets")
local plugin_managers = require("presence.plugin_managers") local plugin_managers = require("presence.plugin_managers")
local Discord = require("presence.discord") local Discord = require("presence.discord")
local function create_config(self, buffer)
if buffer ~= nil and buffer:find("^oil://") then
buffer = buffer:gsub("oil://", "")
end
local filetype = vim.bo.filetype
local filename = self.get_filename(buffer, self.os.path_separator)
local parent_dirpath = self.get_dir_path(buffer, self.os.path_separator)
self.log:debug(string.format("Filename: %s, Parent Directory Path: %s", filename, parent_dirpath))
local line_number = vim.api.nvim_win_get_cursor(0)
local line_count = vim.api.nvim_buf_line_count(0)
local project_name, project_path, project_branch = nil, nil, nil
project_name, project_path, project_branch = self:get_project_name(parent_dirpath)
local file_explorer = file_explorers[filetype:match("[^%d]+")] or file_explorers[(filename or ""):match("[^%d]+")]
local plugin_manager = plugin_managers[filetype]
local git_repo = Presence.get_git_repo_url(parent_dirpath)
return {
filename = filename,
line_number = line_number[1],
line_col = line_number[2],
line_count = line_count,
project_name = project_name,
project_path = project_path,
project_branch = project_branch,
buffer = buffer,
filetype = filetype,
parent_dirpath = parent_dirpath,
file_explorer = file_explorer,
plugin_manager = plugin_manager,
git_repo = git_repo,
}
end
function Presence:setup(...) function Presence:setup(...)
-- Support setup invocation via both dot and colon syntax. -- Support setup invocation via both dot and colon syntax.
-- To maintain backwards compatibility, colon syntax will still -- To maintain backwards compatibility, colon syntax will still
@ -436,40 +476,61 @@ end
-- Gets the current project name -- Gets the current project name
function Presence:get_project_name(file_path) function Presence:get_project_name(file_path)
if not file_path then if not file_path then
return nil return nil, nil, nil
end end
-- if filepath has oil:// remove it
if file_path:find("^oil://") then
file_path = file_path:gsub("oil://", "")
end
-- Escape quotes in the file path
file_path = file_path:gsub([["]], [[\"]])
-- TODO: Only checks for a git repository, could add more checks here -- Escape quotes in the file path
-- Might want to run this in a background process depending on performance file_path = file_path:gsub([["]], [[\"]])
local project_path_cmd = "git rev-parse --show-toplevel"
project_path_cmd = file_path and string.format([[cd "%s" && %s]], file_path, project_path_cmd) or project_path_cmd
local project_path = vim.fn.system(project_path_cmd) -- TODO: Only checks for a git repository, could add more checks here
project_path = vim.trim(project_path) -- Might want to run this in a background process depending on performance
local project_path_cmd = "git rev-parse --show-toplevel"
project_path_cmd = file_path and string.format([[cd "%s" && %s]], file_path, project_path_cmd) or project_path_cmd
if project_path:find("fatal.*") then local project_path = vim.fn.system(project_path_cmd)
self.log:info("Not a git repository, skipping...") project_path = vim.trim(project_path)
return nil
end
if vim.v.shell_error ~= 0 or #project_path == 0 then
local message_fmt = "Failed to get project name (error code %d): %s"
self.log:error(string.format(message_fmt, vim.v.shell_error, project_path))
return nil
end
-- Since git always uses forward slashes, replace with backslash in Windows if project_path:find("fatal.*") then
if self.os.name == "windows" then self.log:info("Not a git repository, skipping...")
project_path = project_path:gsub("/", [[\]]) return nil, nil, nil
end end
if vim.v.shell_error ~= 0 or #project_path == 0 then
local message_fmt = "Failed to get project name (error code %d): %s"
self.log:error(string.format(message_fmt, vim.v.shell_error, project_path))
return nil, nil, nil
end
return self.get_filename(project_path, self.os.path_separator), project_path if self.os.name == "windows" then
project_path = project_path:gsub("/", [[\]])
end
local repo_name_cmd = [[basename -s .git "$(git config --get remote.origin.url)"]]
repo_name_cmd = file_path and string.format([[cd "%s" && %s]], file_path, repo_name_cmd) or repo_name_cmd
local repo_name = vim.fn.system(repo_name_cmd)
repo_name = vim.trim(repo_name)
if vim.v.shell_error ~= 0 or #repo_name == 0 then
local message_fmt = "Failed to get repository name (error code %d): %s"
self.log:error(string.format(message_fmt, vim.v.shell_error, repo_name))
return nil, project_path, nil
end
-- Fetch the branch name
local branch_name_cmd = "git rev-parse --abbrev-ref HEAD"
branch_name_cmd = file_path and string.format([[cd "%s" && %s]], file_path, branch_name_cmd) or branch_name_cmd
local branch_name = vim.fn.system(branch_name_cmd)
branch_name = vim.trim(branch_name)
if vim.v.shell_error ~= 0 or #branch_name == 0 then
local message_fmt = "Failed to get branch name (error code %d): %s"
self.log:error(string.format(message_fmt, vim.v.shell_error, branch_name))
return repo_name, project_path, nil
end
return repo_name, project_path, branch_name
end end
-- Get the name of the parent directory for the given path -- Get the name of the parent directory for the given path
@ -488,40 +549,41 @@ function Presence.get_file_extension(path)
end end
-- Format any status text via options and support custom formatter functions -- Format any status text via options and support custom formatter functions
function Presence:format_status_text(status_type, ...) function Presence:format_status_text(status_type, config)
local option_name = string.format("%s_text", status_type) local option_name = string.format("%s_text", status_type)
local text_option = self.options[option_name] local text_option = self.options[option_name]
if type(text_option) == "function" then if type(text_option) == "function" then
return text_option(...) return text_option(config)
else else
return string.format(text_option, ...) return string.format(text_option, config.filename)
end end
end end
-- Get the status text for the current buffer -- Get the status text for the current buffer
function Presence:get_status_text(filename) -- Update the function to pass config
local file_explorer = file_explorers[vim.bo.filetype:match("[^%d]+")] function Presence:get_status_text(config)
or file_explorers[(filename or ""):match("[^%d]+")] -- Use the file_explorer and plugin_manager directly from the config
local plugin_manager = plugin_managers[vim.bo.filetype] local file_explorer = config.file_explorer
local plugin_manager = config.plugin_manager
if file_explorer then if file_explorer then
return self:format_status_text("file_explorer", file_explorer) return self:format_status_text("file_explorer", config)
elseif plugin_manager then elseif plugin_manager then
return self:format_status_text("plugin_manager", plugin_manager) return self:format_status_text("plugin_manager", config)
end end
if not filename or filename == "" then if not config.filename or config.filename == "" then
return nil return nil
end end
if vim.bo.modifiable and not vim.bo.readonly then if vim.bo.modifiable and not vim.bo.readonly then
if vim.bo.filetype == "gitcommit" then if config.filetype == "gitcommit" then
return self:format_status_text("git_commit", filename) return self:format_status_text("git_commit", config)
elseif filename then elseif config.filename then
return self:format_status_text("editing", filename) return self:format_status_text("editing", config)
end end
elseif filename then elseif config.filename then
return self:format_status_text("reading", filename) return self:format_status_text("reading", config)
end end
end end
@ -832,35 +894,32 @@ end
-- Update Rich Presence for the provided vim buffer -- Update Rich Presence for the provided vim buffer
function Presence:update_for_buffer(buffer, should_debounce) function Presence:update_for_buffer(buffer, should_debounce)
-- Avoid unnecessary updates if the previous activity was for the current buffer local config = create_config(self, buffer)
-- (allow same-buffer updates when line numbers are enabled)
if self.options.enable_line_number == 0 and self.last_activity.file == buffer then if config == nil then
self.log:debug(string.format("Activity already set for %s, skipping...", buffer)) self.log:debug("No config found for buffer, skipping...")
return return
end end
-- Parse vim buffer -- Avoid unnecessary updates if the previous activity was for the current buffer
local filename = self.get_filename(buffer, self.os.path_separator) -- (allow same-buffer updates when line numbers are enabled)
local parent_dirpath = self.get_dir_path(buffer, self.os.path_separator) if self.options.enable_line_number == 0 and self.last_activity.file == buffer then
local extension = filename and self.get_file_extension(filename) or nil self.log:debug(string.format("Activity already set for %s, skipping...", config.filename))
self.log:debug(string.format("Parsed filename %s with %s extension", filename, extension or "no")) return
end
-- Return early if there is no valid activity status text to set local status_text = self:get_status_text(config)
local status_text = self:get_status_text(filename)
if not status_text then if not status_text then
return self.log:debug("No status text for the given buffer, skipping...") return self.log:debug("No status text for the given buffer, skipping...")
end end
-- Get project information
self.log:debug(string.format("Getting project name for %s...", parent_dirpath))
local project_name, project_path = self:get_project_name(parent_dirpath)
-- Check for blacklist -- Check for blacklist
local blacklist_not_empty = (#self.options.blacklist > 0 or #self.options.blacklist_repos > 0) local blacklist_not_empty = (#self.options.blacklist > 0 or #self.options.blacklist_repos > 0)
local is_blacklisted = blacklist_not_empty and self:check_blacklist(buffer, parent_dirpath, project_path) local is_blacklisted = blacklist_not_empty
and self:check_blacklist(buffer, config.parent_dirpath, config.project_path)
if is_blacklisted then if is_blacklisted then
self.last_activity.file = buffer self.last_activity.file = buffer
self.log:debug("Either project, directory name, or repository URL is blacklisted. Skipping...") self.log:debug("Either project or directory name is blacklisted, skipping...")
self:cancel() self:cancel()
return return
end end
@ -873,17 +932,16 @@ function Presence:update_for_buffer(buffer, should_debounce)
self.log:debug(string.format("Setting activity for %s...", buffer and #buffer > 0 and buffer or "unnamed buffer")) self.log:debug(string.format("Setting activity for %s...", buffer and #buffer > 0 and buffer or "unnamed buffer"))
-- Determine image text and asset key -- Determine image text and asset key
local name = filename
local asset_key = "code" local asset_key = "code"
local description = filename local description = config.filename
local file_asset = self.options.file_assets[filename] or self.options.file_assets[extension] local file_asset = self.options.file_assets[config.filename] or self.options.file_assets[config.filetype]
if file_asset then if file_asset then
name, asset_key, description = unpack(file_asset) config.name, asset_key, description = unpack(file_asset)
self.log:debug(string.format("Using file asset: %s", vim.inspect(file_asset))) self.log:debug(string.format("Using file asset: %s", vim.inspect(file_asset)))
end end
-- Construct activity asset information -- Construct activity asset information
local file_text = description or name local file_text = description or config.filename
local neovim_image_text = self.options.neovim_image_text local neovim_image_text = self.options.neovim_image_text
local use_file_as_main_image = self.options.main_image == "file" local use_file_as_main_image = self.options.main_image == "file"
local use_neovim_as_main_image = self.options.main_image == "neovim" local use_neovim_as_main_image = self.options.main_image == "neovim"
@ -899,14 +957,12 @@ function Presence:update_for_buffer(buffer, should_debounce)
local activity = { local activity = {
state = status_text, state = status_text,
assets = assets, assets = assets,
timestamps = self.options.show_time == 1 and { timestamps = self.options.show_time == 1 and { start = relative_activity_set_at } or nil,
start = relative_activity_set_at,
} or nil,
} }
-- Add button that links to the git workspace remote origin url -- Add button that links to the git workspace remote origin URL
if self.options.buttons ~= 0 then if self.options.buttons ~= 0 then
local buttons = self:get_buttons(buffer, parent_dirpath) local buttons = self:get_buttons(buffer, config.parent_dirpath)
if buttons then if buttons then
self.log:debug(string.format("Attaching buttons to activity: %s", vim.inspect(buttons))) self.log:debug(string.format("Attaching buttons to activity: %s", vim.inspect(buttons)))
activity.buttons = buttons activity.buttons = buttons
@ -916,13 +972,9 @@ function Presence:update_for_buffer(buffer, should_debounce)
-- Get the current line number and line count if the user has set the enable_line_number option -- Get the current line number and line count if the user has set the enable_line_number option
if self.options.enable_line_number == 1 then if self.options.enable_line_number == 1 then
self.log:debug("Getting line number for current buffer...") self.log:debug("Getting line number for current buffer...")
local line_number_text = self:format_status_text("line_number", config)
local line_number = vim.api.nvim_win_get_cursor(0)[1]
local line_count = vim.api.nvim_buf_line_count(0)
local line_number_text = self:format_status_text("line_number", line_number, line_count)
activity.details = line_number_text activity.details = line_number_text
self.workspace = nil self.workspace = nil
self.last_activity = { self.last_activity = {
id = self.id, id = self.id,
@ -933,29 +985,27 @@ function Presence:update_for_buffer(buffer, should_debounce)
} }
else else
-- Include project details if available and if the user hasn't set the enable_line_number option -- Include project details if available and if the user hasn't set the enable_line_number option
if project_name then if config.project_name then
self.log:debug(string.format("Detected project: %s", project_name)) self.log:debug(string.format("Detected project: %s", config.project_name))
activity.details = self:format_status_text("workspace", project_name, buffer) activity.details = self:format_status_text("workspace", config)
self.workspace = project_path self.workspace = config.project_path
self.last_activity = { self.last_activity = {
id = self.id, id = self.id,
file = buffer, file = buffer,
set_at = activity_set_at, set_at = activity_set_at,
relative_set_at = relative_activity_set_at, relative_set_at = relative_activity_set_at,
workspace = project_path, workspace = config.project_path,
} }
if self.workspaces[project_path] then if self.workspaces[config.project_path] then
self.workspaces[project_path].updated_at = activity_set_at self.workspaces[config.project_path].updated_at = activity_set_at
activity.timestamps = self.options.show_time == 1 activity.timestamps = self.options.show_time == 1
and { and { start = self.workspaces[config.project_path].started_at }
start = self.workspaces[project_path].started_at,
}
or nil or nil
else else
self.workspaces[project_path] = { self.workspaces[config.project_path] = {
started_at = activity_set_at, started_at = activity_set_at,
updated_at = activity_set_at, updated_at = activity_set_at,
} }
@ -999,7 +1049,7 @@ function Presence:update_for_buffer(buffer, should_debounce)
return return
end end
self.log:info(string.format("Set activity in Discord for %s", filename)) self.log:info(string.format("Set activity in Discord for %s", config.filename))
end) end)
end end