From c7f2f95bc5440435fd314629d7a291eee44a4ec3 Mon Sep 17 00:00:00 2001 From: Sonny Bakker Date: Mon, 9 Dec 2024 20:26:16 +0100 Subject: [PATCH] Add files --- lua/source-link/init.lua | 84 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 lua/source-link/init.lua diff --git a/lua/source-link/init.lua b/lua/source-link/init.lua new file mode 100644 index 0000000..97500ab --- /dev/null +++ b/lua/source-link/init.lua @@ -0,0 +1,84 @@ +local function file_exists(file_path) + local file = io.open(file_path, "rb") + if file then file:close() end + return file ~= nil +end + +local remote_prefix_patterns = {'ssh://', 'http[s]?://', '%w+@'} + +local function transform_url(remote) + for _, pattern in pairs(remote_prefix_patterns) do + local regex_pattern = string.format('^%s(.*)', pattern) + if remote:match(regex_pattern) then + local _url = remote:match(regex_pattern, 1) + _url = _url:gsub('(:)(%a+)', '/%2') + _url = _url:gsub('.git$', '') + + if not _url:match('^http[s]?://') then + return string.format('%s%s', 'https://', _url) + end + + return _url + end + end +end + +-- TODO: add more providers +-- TODO: add feature to specify provider +local provider_mapping = { + ['github'] = '%s/blob/%s/%s#L%i', + ['bitbucket'] = '%s/src/%s/%s#lines-%i', + ['forgejo'] = '%s/src/commit/%s/%s#L%i', +} + +local function get_provider_template(remote) + local transformed_url = transform_url(remote) + + if not transformed_url then return end + + for domain, template_string in pairs(provider_mapping) do + if transformed_url:match(domain) then + return transformed_url, template_string + end + end +end + +local function source_open() + local git_conf_path = '.git/config' + + -- TODO: determine based on recursively traversing upwards in path + if not file_exists(git_conf_path) then return end + + local _remote_output = io.popen('git remote get-url origin', 'r') + + -- TODO: test with other refs + local _commit_output = io.popen('git show --pretty=%H HEAD', 'r') + + if _remote_output == nil or _commit_output == nil then return end + + local line_number = unpack(vim.api.nvim_win_get_cursor(0)) + local filepath = vim.api.nvim_buf_get_name(0) + local relative_filepath = vim.fn.fnamemodify(filepath, ':.') + + local remote = _remote_output:read() + local branch = _commit_output:read() + + local transformed_url, template_string = get_provider_template(remote) + + for _, variable in pairs({ filepath, transformed_url, template_string }) do + if variable == nil then + return + end + end + + local template_args = { transformed_url, branch, relative_filepath, line_number } + local url = template_string:format(unpack(template_args)) + + os.execute(('xdg-open %s'):format(url)) +end + +local function setup(opts) + vim.api.nvim_create_user_command('SourceOpen', source_open, {}) +end + +return { setup = setup }