mirror of
https://github.com/folke/snacks.nvim
synced 2025-08-04 18:58:12 +00:00
feat(picker): added git_stash
picker. Closes #762
This commit is contained in:
parent
1a5a0871c8
commit
bb3db117a4
5 changed files with 87 additions and 4 deletions
|
@ -155,6 +155,16 @@ function M.git_stage(picker)
|
|||
end
|
||||
end
|
||||
|
||||
function M.git_stash_apply(_, item)
|
||||
if not item then
|
||||
return
|
||||
end
|
||||
local cmd = { "git", "stash", "apply", item.stash }
|
||||
Snacks.picker.util.cmd(cmd, function()
|
||||
Snacks.notify("Stash applied: `" .. item.stash .. "`", { title = "Snacks Picker" })
|
||||
end, { cwd = item.cwd })
|
||||
end
|
||||
|
||||
function M.git_checkout(picker, item)
|
||||
picker:close()
|
||||
if item then
|
||||
|
|
|
@ -190,6 +190,13 @@ M.git_log_line = {
|
|||
confirm = "git_checkout",
|
||||
}
|
||||
|
||||
M.git_stash = {
|
||||
finder = "git_stash",
|
||||
format = "git_stash",
|
||||
preview = "git_stash",
|
||||
confirm = "git_stash_apply",
|
||||
}
|
||||
|
||||
M.git_status = {
|
||||
finder = "git_status",
|
||||
format = "git_status",
|
||||
|
|
|
@ -101,7 +101,8 @@ function M.git_log(item, picker)
|
|||
local a = Snacks.picker.util.align
|
||||
local ret = {} ---@type snacks.picker.Highlight[]
|
||||
ret[#ret + 1] = { picker.opts.icons.git.commit, "SnacksPickerGitCommit" }
|
||||
ret[#ret + 1] = { item.commit, "SnacksPickerGitCommit" }
|
||||
local c = item.commit or item.branch or "HEAD"
|
||||
ret[#ret + 1] = { a(c, 7, { truncate = true }), "SnacksPickerGitCommit" }
|
||||
|
||||
ret[#ret + 1] = { " " }
|
||||
if item.date then
|
||||
|
@ -158,6 +159,20 @@ function M.git_branch(item, picker)
|
|||
return ret
|
||||
end
|
||||
|
||||
function M.git_stash(item, picker)
|
||||
local a = Snacks.picker.util.align
|
||||
local ret = {} ---@type snacks.picker.Highlight[]
|
||||
ret[#ret + 1] = { a(item.stash, 10), "SnacksPickerIdx" }
|
||||
ret[#ret + 1] = { " " }
|
||||
ret[#ret + 1] = { a(item.branch, 10, { truncate = true }), "SnacksPickerGitBranch" }
|
||||
ret[#ret + 1] = { " " }
|
||||
local offset = Snacks.picker.highlight.offset(ret)
|
||||
local log = M.git_log(item, picker)
|
||||
Snacks.picker.highlight.fix_offset(log, offset)
|
||||
vim.list_extend(ret, log)
|
||||
return ret
|
||||
end
|
||||
|
||||
function M.indent(item, picker)
|
||||
local ret = {} ---@type snacks.picker.Highlight[]
|
||||
local indents = picker.opts.icons.indent
|
||||
|
|
|
@ -307,6 +307,24 @@ function M.git_diff(ctx)
|
|||
M.cmd(cmd, ctx, { ft = not native and "diff" or nil })
|
||||
end
|
||||
|
||||
---@param ctx snacks.picker.preview.ctx
|
||||
function M.git_stash(ctx)
|
||||
local native = ctx.picker.opts.previewers.git.native
|
||||
local cmd = {
|
||||
"git",
|
||||
"-c",
|
||||
"delta." .. vim.o.background .. "=true",
|
||||
"stash",
|
||||
"show",
|
||||
"--patch",
|
||||
ctx.item.stash,
|
||||
}
|
||||
if not native then
|
||||
table.insert(cmd, 2, "--no-pager")
|
||||
end
|
||||
M.cmd(cmd, ctx, { ft = not native and "diff" or nil })
|
||||
end
|
||||
|
||||
---@param ctx snacks.picker.preview.ctx
|
||||
function M.git_status(ctx)
|
||||
local ss = ctx.item.status
|
||||
|
|
|
@ -2,6 +2,8 @@ local M = {}
|
|||
|
||||
local uv = vim.uv or vim.loop
|
||||
|
||||
local commit_pat = ("[a-z0-9]"):rep(7)
|
||||
|
||||
---@class snacks.picker
|
||||
---@field git_files fun(opts?: snacks.picker.git.files.Config): snacks.Picker
|
||||
---@field git_log fun(opts?: snacks.picker.git.log.Config): snacks.Picker
|
||||
|
@ -173,13 +175,12 @@ function M.branches(opts, ctx)
|
|||
local cwd = vim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil
|
||||
cwd = Snacks.git.get_root(cwd)
|
||||
|
||||
local pattern_hash = "[a-zA-Z0-9]+"
|
||||
local patterns = {
|
||||
-- stylua: ignore start
|
||||
--- e.g. "* (HEAD detached at f65a2c8) f65a2c8 chore(build): auto-generate docs"
|
||||
"^(.)%s(%b())%s+(" .. pattern_hash .. ")%s*(.*)$",
|
||||
"^(.)%s(%b())%s+(" .. commit_pat .. ")%s*(.*)$",
|
||||
--- e.g. " main d2b2b7b [origin/main: behind 276] chore(build): auto-generate docs"
|
||||
"^(.)%s(%S+)%s+(".. pattern_hash .. ")%s*(.*)$",
|
||||
"^(.)%s(%S+)%s+(".. commit_pat .. ")%s*(.*)$",
|
||||
-- stylua: ignore end
|
||||
} ---@type string[]
|
||||
|
||||
|
@ -211,4 +212,36 @@ function M.branches(opts, ctx)
|
|||
}, ctx)
|
||||
end
|
||||
|
||||
---@param opts snacks.picker.Config
|
||||
---@type snacks.picker.finder
|
||||
function M.stash(opts, ctx)
|
||||
local args = { "--no-pager", "stash", "list" }
|
||||
local cwd = vim.fs.normalize(opts and opts.cwd or uv.cwd() or ".") or nil
|
||||
cwd = Snacks.git.get_root(cwd)
|
||||
|
||||
return require("snacks.picker.source.proc").proc({
|
||||
opts,
|
||||
{
|
||||
cwd = cwd,
|
||||
cmd = "git",
|
||||
args = args,
|
||||
---@param item snacks.picker.finder.Item
|
||||
transform = function(item)
|
||||
item.cwd = cwd
|
||||
local stash, branch, msg = item.text:gsub(": On main:", ": WIP on main:"):match("^(%S+): WIP on (%S+): (.*)$")
|
||||
if stash then
|
||||
local commit, m = msg:match("^(" .. commit_pat .. ") (.*)")
|
||||
item.stash = stash
|
||||
item.branch = branch
|
||||
item.commit = commit
|
||||
item.msg = m or msg
|
||||
return
|
||||
end
|
||||
Snacks.notify.warn("failed to parse stash:\n```git\n" .. item.text .. "\n```")
|
||||
return false -- skip items we could not parse
|
||||
end,
|
||||
},
|
||||
}, ctx)
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue