Skip to content
Open
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ require("presence").setup({
debounce_timeout = 10, -- Number of seconds to debounce events (or calls to `:lua package.loaded.presence:update(<filename>, true)`)
enable_line_number = false, -- Displays the current line number instead of the current project
blacklist = {}, -- A list of strings or Lua patterns that disable Rich Presence if the current file name, path, or workspace matches
blacklist_repos = {}, -- A blacklist that applies to git remote repo URLs instead of folder/file names
buttons = true, -- Configure Rich Presence button(s), either a boolean to enable/disable, a static table (`{{ label = "<label>", url = "<url>" }, ...}`, or a function(buffer: string, repo_url: string|nil): table)
file_assets = {}, -- Custom file asset definitions keyed by file names and extensions (see default config at `lua/presence/file_assets.lua` for reference)
show_time = true, -- Show the timer
Expand Down Expand Up @@ -69,6 +70,7 @@ let g:presence_log_level
let g:presence_debounce_timeout = 10
let g:presence_enable_line_number = 0
let g:presence_blacklist = []
let g:presence_blacklist_repos = []
let g:presence_buttons = 1
let g:presence_file_assets = {}
let g:presence_show_time = 1
Expand Down
124 changes: 79 additions & 45 deletions lua/presence/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function Presence:setup(...)
-- Support setup invocation via both dot and colon syntax.
-- To maintain backwards compatibility, colon syntax will still
-- be supported, but dot syntax should be recommended.
local args = {...}
local args = { ... }
local options = args[1]
if #args == 0 then
options = self
Expand All @@ -89,7 +89,7 @@ function Presence:setup(...)
-- Get operating system information including path separator
-- http://www.lua.org/manual/5.3/manual.html#pdf-package.config
local uname = vim.loop.os_uname()
local separator = package.config:sub(1,1)
local separator = package.config:sub(1, 1)
local wsl_distro_name = os.getenv("WSL_DISTRO_NAME")
local os_name = self.get_os_name(uname)
self.os = {
Expand All @@ -102,7 +102,7 @@ function Presence:setup(...)
local setup_message_fmt = "Setting up plugin for %s"
if self.os.name then
local setup_message = self.os.is_wsl
and string.format(setup_message_fmt.." in WSL (%s)", self.os.name, vim.inspect(wsl_distro_name))
and string.format(setup_message_fmt .. " in WSL (%s)", self.os.name, vim.inspect(wsl_distro_name))
or string.format(setup_message_fmt, self.os.name)
self.log:debug(setup_message)
else
Expand Down Expand Up @@ -130,6 +130,7 @@ function Presence:setup(...)
self:set_option("workspace_text", "Working on %s")
self:set_option("line_number_text", "Line %s out of %s")
self:set_option("blacklist", {})
self:set_option("blacklist_repos", {})
self:set_option("buttons", true)
self:set_option("show_time", true)
-- File assets options
Expand Down Expand Up @@ -321,10 +322,10 @@ function Presence:connect(on_done)
if err == "EISCONN" then
self.log:info("Already connected to Discord")
elseif err == "ECONNREFUSED" then
self.log:warn("Failed to connect to Discord: "..err.." (is Discord running?)")
self.log:warn("Failed to connect to Discord: " .. err .. " (is Discord running?)")
return
elseif err then
self.log:error("Failed to connect to Discord: "..err)
self.log:error("Failed to connect to Discord: " .. err)
return
end

Expand All @@ -350,7 +351,7 @@ function Presence:authorize(on_done)
self.is_authorized = true
return on_done()
elseif err then
self.log:error("Failed to authorize with Discord: "..err)
self.log:error("Failed to authorize with Discord: " .. err)
self.is_authorized = false
return
end
Expand All @@ -369,18 +370,18 @@ function Presence:get_discord_socket_path()

if self.os.is_wsl then
-- Use socket created by relay for WSL
sock_path = "/var/run/"..sock_name
sock_path = "/var/run/" .. sock_name
elseif self.os.name == "windows" then
-- Use named pipe in NPFS for Windows
sock_path = [[\\.\pipe\]]..sock_name
sock_path = [[\\.\pipe\]] .. sock_name
elseif self.os.name == "macos" then
-- Use $TMPDIR for macOS
local path = os.getenv("TMPDIR")

if path then
sock_path = path:match("/$")
and path..sock_name
or path.."/"..sock_name
and path .. sock_name
or path .. "/" .. sock_name
end
elseif self.os.name == "linux" then
-- Check various temp directory environment variables
Expand All @@ -396,7 +397,7 @@ function Presence:get_discord_socket_path()
local path = os.getenv(var)
if path then
self.log:debug(string.format("Using runtime path: %s", path))
sock_path = path:match("/$") and path..sock_name or path.."/"..sock_name
sock_path = path:match("/$") and path .. sock_name or path .. "/" .. sock_name
break
end
end
Expand All @@ -422,13 +423,13 @@ function Presence:get_project_name(file_path)

-- TODO: Only checks for a git repository, could add more checks here
-- 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
local project_path_cmd = { "git", "rev-parse", "--show-toplevel" }
if file_path then
table.insert(project_path_cmd, 2, "-C")
table.insert(project_path_cmd, 3, file_path)
end

local project_path = vim.fn.system(project_path_cmd)
project_path = vim.trim(project_path)
local project_path = vim.trim(vim.fn.system(project_path_cmd))

if project_path:find("fatal.*") then
self.log:info("Not a git repository, skipping...")
Expand Down Expand Up @@ -613,7 +614,7 @@ function Presence.discord_event(on_ready)
return
end

local args = {...}
local args = { ... }
local callback = function()
on_ready(self, unpack(args))
end
Expand Down Expand Up @@ -662,7 +663,8 @@ function Presence:check_blacklist(buffer, parent_dirpath, project_dirpath)
end

-- Blacklist table
local blacklist_table = self.options["blacklist"]
local blacklist_table = self.options["blacklist"] or {}
local blacklist_repos_table = self.options["blacklist_repos"] or {}

-- Loop over the values to see if the provided project/path is in the blacklist
for _, val in pairs(blacklist_table) do
Expand All @@ -671,26 +673,70 @@ function Presence:check_blacklist(buffer, parent_dirpath, project_dirpath)
-- Match parent either by Lua pattern or by plain string
local is_parent_directory_blacklisted = parent_dirpath and
((parent_dirpath:match(val) == parent_dirpath or
parent_dirname:match(val) == parent_dirname) or
(parent_dirpath:find(val, nil, true) or
parent_dirname:find(val, nil, true)))
parent_dirname:match(val) == parent_dirname) or
(parent_dirpath:find(val, nil, true) or
parent_dirname:find(val, nil, true)))
if is_parent_directory_blacklisted then
return true
end

-- Match project either by Lua pattern or by plain string
local is_project_directory_blacklisted = project_dirpath and
((project_dirpath:match(val) == project_dirpath or
project_dirname:match(val) == project_dirname) or
(project_dirpath:find(val, nil, true) or
project_dirname:find(val, nil, true)))
project_dirname:match(val) == project_dirname) or
(project_dirpath:find(val, nil, true) or
project_dirname:find(val, nil, true)))
if is_project_directory_blacklisted then
return true
end
end


-- check against git repo blacklist
local git_repo = Presence:get_git_repo_url(parent_dirpath)
if git_repo then
self.log:debug(string.format("Checking git repo blacklist for %s", git_repo))
else
self.log:debug("No git repo, skipping blacklist check")
return false
end


for _, val in pairs(blacklist_repos_table) do
if buffer:match(val) == buffer then return true end

local is_git_repo_blacklisted = git_repo and
((git_repo:match(val) == git_repo) == git_repo or
(git_repo:find(val, nil, true)))

if is_git_repo_blacklisted then
return true
end
end

return false
end

function Presence:get_git_repo_url(parent_dirpath)
local repo_url

if parent_dirpath then
-- Escape quotes in the file path
local path = parent_dirpath:gsub([["]], [[\"]])
local git_url_cmd = { "git", "config", "--get", "remote.origin.url" }
if path then
table.insert(git_url_cmd, 2, "-C")
table.insert(git_url_cmd, 3, path)
end

-- Trim and coerce empty string value to null
repo_url = vim.trim(vim.fn.system(git_url_cmd))
repo_url = repo_url ~= "" and repo_url or nil

return repo_url
end
end

-- Get either user-configured buttons or the create default "View Repository" button definition
function Presence:get_buttons(buffer, parent_dirpath)
-- User configured a static buttons table
Expand All @@ -703,19 +749,7 @@ function Presence:get_buttons(buffer, parent_dirpath)
end

-- Retrieve the git repository URL
local repo_url
if parent_dirpath then
-- Escape quotes in the file path
local path = parent_dirpath:gsub([["]], [[\"]])
local git_url_cmd = "git config --get remote.origin.url"
local cmd = path
and string.format([[cd "%s" && %s]], path, git_url_cmd)
or git_url_cmd

-- Trim and coerce empty string value to null
repo_url = vim.trim(vim.fn.system(cmd))
repo_url = repo_url ~= "" and repo_url or nil
end
local repo_url = Presence:get_git_repo_url(parent_dirpath)

-- User configured a function to dynamically create buttons table
if type(self.options.buttons) == "function" then
Expand All @@ -725,7 +759,6 @@ function Presence:get_buttons(buffer, parent_dirpath)

-- Default behavior to show a "View Repository" button if the repo URL is valid
if repo_url then

-- Check if repo url uses short ssh syntax
local domain, project = repo_url:match("^git@(.+):(.+)$")
if domain and project then
Expand Down Expand Up @@ -792,10 +825,11 @@ function Presence:update_for_buffer(buffer, should_debounce)
local project_name, project_path = self:get_project_name(parent_dirpath)

-- Check for blacklist
local is_blacklisted = #self.options.blacklist > 0 and self:check_blacklist(buffer, parent_dirpath, project_path)
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)
if is_blacklisted then
self.last_activity.file = buffer
self.log:debug("Either project or directory name is blacklisted, skipping...")
self.log:debug("Either project, directory name, or repository URL is blacklisted. Skipping...")
self:cancel()
return
end
Expand Down Expand Up @@ -1042,11 +1076,11 @@ function Presence:register_and_sync_peer(id, socket)
end
end

self:call_remote_method(socket, "sync_self", {{
self:call_remote_method(socket, "sync_self", { {
last_activity = self.last_activity,
peers = peers,
workspaces = self.workspaces,
}})
} })
end

-- Register self to any remote Neovim instances
Expand Down Expand Up @@ -1124,11 +1158,11 @@ function Presence:sync_self_activity()
end
end

self:call_remote_method(peer.socket, "sync_peer_activity", {{
self:call_remote_method(peer.socket, "sync_peer_activity", { {
last_activity = self.last_activity,
peers = peers,
workspaces = self.workspaces,
}})
} })
end
end

Expand Down