mirror of
https://github.com/folke/snacks.nvim
synced 2025-07-07 13:15:08 +00:00
feat: added gitbrowse
This commit is contained in:
parent
f0a9991347
commit
a638d8bafe
6 changed files with 164 additions and 2 deletions
|
@ -6,8 +6,12 @@
|
|||
- [x] words `LspAttach`
|
||||
- [x] quickfile `BufReadPost`
|
||||
- [x] rename
|
||||
- [ ] lazygit
|
||||
- [x] terminal
|
||||
- [x] float
|
||||
- [x] lazygit
|
||||
- [x] git
|
||||
- [x] gitbrowse
|
||||
- [ ] zen
|
||||
- [ ] lsp
|
||||
- [ ] root
|
||||
- [ ] terminal
|
||||
- [ ] toggle
|
||||
|
|
100
lua/snacks/gitbrowse.lua
Normal file
100
lua/snacks/gitbrowse.lua
Normal file
|
@ -0,0 +1,100 @@
|
|||
---@class snacks.gitbrowse
|
||||
---@overload fun(opts?: snacks.gitbrowse.Config)
|
||||
local M = setmetatable({}, {
|
||||
__call = function(t, ...)
|
||||
return t.open(...)
|
||||
end,
|
||||
})
|
||||
|
||||
---@class snacks.gitbrowse.Config
|
||||
local defaults = {
|
||||
open = function(url)
|
||||
if vim.fn.has("nvim-0.10") == 0 then
|
||||
require("lazy.util").open(url, { system = true })
|
||||
return
|
||||
end
|
||||
vim.ui.open(url)
|
||||
end,
|
||||
-- stylua: ignore
|
||||
patterns = {
|
||||
{ "^(https?://.*)%.git$" , "%1" },
|
||||
{ "^git@(.+):(.+)%.git$" , "https://%1/%2" },
|
||||
{ "^git@(.+):(.+)$" , "https://%1/%2" },
|
||||
{ "^git@(.+)/(.+)$" , "https://%1/%2" },
|
||||
{ "^ssh://git@(.*)$" , "https://%1" },
|
||||
{ "^ssh://([^:/]+)(:%d+)/(.*)$" , "https://%1/%3" },
|
||||
{ "^ssh://([^/]+)/(.*)$" , "https://%1/%2" },
|
||||
{ "ssh%.dev%.azure%.com/v3/(.*)/(.*)$", "dev.azure.com/%1/_git/%2" },
|
||||
{ "^https://%w*@(.*)" , "https://%1" },
|
||||
{ "^git@(.*)" , "https://%1" },
|
||||
{ ":%d+" , "" },
|
||||
{ "%.git$" , "" },
|
||||
},
|
||||
}
|
||||
|
||||
---@param remote string
|
||||
---@param opts? snacks.gitbrowse.Config
|
||||
function M.get_url(remote, opts)
|
||||
opts = Snacks.config.get("gitbrowse", defaults, opts)
|
||||
local ret = remote
|
||||
for _, pattern in ipairs(opts.patterns) do
|
||||
ret = ret:gsub(pattern[1], pattern[2])
|
||||
end
|
||||
return ret:find("https://") == 1 and ret or ("https://%s"):format(ret)
|
||||
end
|
||||
|
||||
---@param opts? snacks.gitbrowse.Config
|
||||
function M.open(opts)
|
||||
opts = Snacks.config.get("gitbrowse", defaults, opts)
|
||||
local proc = vim.system({ "git", "remote", "-v" }, { text = true }):wait()
|
||||
if proc.code ~= 0 then
|
||||
return vim.notify("Failed to get git remotes", vim.log.levels.ERROR, { title = "Git Browse" })
|
||||
end
|
||||
local lines = vim.split(proc.stdout, "\n")
|
||||
|
||||
proc = vim.system({ "git", "rev-parse", "--abbrev-ref", "HEAD" }):wait()
|
||||
if proc.code ~= 0 then
|
||||
return vim.notify("Failed to get current branch", vim.log.levels.ERROR, { title = "Git Browse" })
|
||||
end
|
||||
local branch = proc.stdout:gsub("\n", "")
|
||||
|
||||
local remotes = {} ---@type {name:string, url:string}[]
|
||||
|
||||
for _, line in ipairs(lines) do
|
||||
local name, remote = line:match("(%S+)%s+(%S+)%s+%(fetch%)")
|
||||
if name and remote then
|
||||
local url = M.get_url(remote, opts)
|
||||
if url:find("github") and branch and branch ~= "master" and branch ~= "main" then
|
||||
url = ("%s/tree/%s"):format(url, branch)
|
||||
end
|
||||
if url then
|
||||
table.insert(remotes, {
|
||||
name = name,
|
||||
url = url,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function open(remote)
|
||||
if remote then
|
||||
vim.notify(("Opening %s\n%s"):format(remote.name, remote.url), vim.log.levels.INFO, { title = "Git Browse" })
|
||||
opts.open(remote.url)
|
||||
end
|
||||
end
|
||||
|
||||
if #remotes == 0 then
|
||||
return vim.notify("No git remotes found", vim.log.levels.ERROR, { title = "Git Browse" })
|
||||
elseif #remotes == 1 then
|
||||
return open(remotes[1])
|
||||
end
|
||||
|
||||
vim.ui.select(remotes, {
|
||||
prompt = "Select remote to browse",
|
||||
format_item = function(item)
|
||||
return item.name .. (" "):rep(8 - #item.name) .. " 🔗 " .. item.url
|
||||
end,
|
||||
}, open)
|
||||
end
|
||||
|
||||
return M
|
|
@ -9,6 +9,7 @@
|
|||
---@field terminal snacks.terminal
|
||||
---@field lazygit snacks.lazygit
|
||||
---@field git snacks.git
|
||||
---@field gitbrowse snacks.gitbrowse
|
||||
local M = {}
|
||||
|
||||
setmetatable(M, {
|
||||
|
@ -29,6 +30,7 @@ _G.Snacks = M
|
|||
---@field float snacks.float.Config
|
||||
---@field terminal snacks.terminal.Config
|
||||
---@field lazygit snacks.lazygit.Config
|
||||
---@field gitbrowse snacks.gitbrowse.Config
|
||||
local config = {
|
||||
bigfile = { enabled = true },
|
||||
quickfile = { enabled = true },
|
||||
|
|
3
scripts/test
Executable file
3
scripts/test
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/env bash
|
||||
|
||||
nvim -l tests/minit.lua --minitest
|
42
tests/gitbrowse_spec.lua
Normal file
42
tests/gitbrowse_spec.lua
Normal file
|
@ -0,0 +1,42 @@
|
|||
---@module "luassert"
|
||||
|
||||
local gitbrowse = require("snacks.gitbrowse")
|
||||
|
||||
-- stylua: ignore
|
||||
local git_remotes_cases = {
|
||||
["https://github.com/LazyVim/LazyVim.git"] = "https://github.com/LazyVim/LazyVim",
|
||||
["https://github.com/LazyVim/LazyVim"] = "https://github.com/LazyVim/LazyVim",
|
||||
["git@github.com:LazyVim/LazyVim"] = "https://github.com/LazyVim/LazyVim",
|
||||
["git@ssh.dev.azure.com:v3/neovim-org/owner/repo"] = "https://dev.azure.com/neovim-org/owner/_git/repo",
|
||||
["https://folkelemaitre@bitbucket.org/samiulazim/neovim.git"] = "https://bitbucket.org/samiulazim/neovim",
|
||||
["git@bitbucket.org:samiulazim/neovim.git"] = "https://bitbucket.org/samiulazim/neovim",
|
||||
["git@gitlab.com:inkscape/inkscape.git"] = "https://gitlab.com/inkscape/inkscape",
|
||||
["https://gitlab.com/inkscape/inkscape.git"] = "https://gitlab.com/inkscape/inkscape",
|
||||
["git@github.com:torvalds/linux.git"] = "https://github.com/torvalds/linux",
|
||||
["https://github.com/torvalds/linux.git"] = "https://github.com/torvalds/linux",
|
||||
["git@bitbucket.org:team/repo.git"] = "https://bitbucket.org/team/repo",
|
||||
["https://bitbucket.org/team/repo.git"] = "https://bitbucket.org/team/repo",
|
||||
["git@gitlab.com:example-group/example-project.git"] = "https://gitlab.com/example-group/example-project",
|
||||
["https://gitlab.com/example-group/example-project.git"] = "https://gitlab.com/example-group/example-project",
|
||||
["git@ssh.dev.azure.com:v3/org/project/repo"] = "https://dev.azure.com/org/project/_git/repo",
|
||||
["https://username@dev.azure.com/org/project/_git/repo"] = "https://dev.azure.com/org/project/_git/repo",
|
||||
["ssh://git@ghe.example.com:2222/org/repo.git"] = "https://ghe.example.com/org/repo",
|
||||
["https://ghe.example.com/org/repo.git"] = "https://ghe.example.com/org/repo",
|
||||
["git-codecommit.us-east-1.amazonaws.com/v1/repos/MyDemoRepo"] = "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/MyDemoRepo",
|
||||
["https://git-codecommit.us-east-1.amazonaws.com/v1/repos/MyDemoRepo"] = "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/MyDemoRepo",
|
||||
["ssh://git@source.developers.google.com:2022/p/project/r/repo"] = "https://source.developers.google.com/p/project/r/repo",
|
||||
["https://source.developers.google.com/p/project/r/repo"] = "https://source.developers.google.com/p/project/r/repo",
|
||||
["git@git.sr.ht:~user/repo"] = "https://git.sr.ht/~user/repo",
|
||||
["https://git.sr.ht/~user/repo"] = "https://git.sr.ht/~user/repo",
|
||||
["git@git.sr.ht:~user/another-repo"] = "https://git.sr.ht/~user/another-repo",
|
||||
["https://git.sr.ht/~user/another-repo"] = "https://git.sr.ht/~user/another-repo",
|
||||
}
|
||||
|
||||
describe("util.lazygit", function()
|
||||
for remote, expected in pairs(git_remotes_cases) do
|
||||
it("should parse git remote " .. remote, function()
|
||||
local url = gitbrowse.get_url(remote)
|
||||
assert.are.equal(expected, url)
|
||||
end)
|
||||
end
|
||||
end)
|
11
tests/minit.lua
Normal file
11
tests/minit.lua
Normal file
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env -S nvim -l
|
||||
|
||||
vim.env.LAZY_STDPATH = ".tests"
|
||||
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()
|
||||
|
||||
-- Setup lazy.nvim
|
||||
require("lazy.minit").setup({
|
||||
spec = {
|
||||
{ dir = vim.uv.cwd(), opts = {} },
|
||||
},
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue