docs/gh.md
A modern GitHub CLI integration for Neovim that brings GitHub issues and pull requests directly into your editor.
gh) - must be installed and authenticated{
"folke/snacks.nvim",
opts = {
gh = {
-- your gh configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
},
picker = {
sources = {
gh_issue = {
-- your gh_issue picker configuration comes here
-- or leave it empty to use the default settings
},
gh_pr = {
-- your gh_pr picker configuration comes here
-- or leave it empty to use the default settings
}
}
},
},
keys = {
{ "<leader>gi", function() Snacks.picker.gh_issue() end, desc = "GitHub Issues (open)" },
{ "<leader>gI", function() Snacks.picker.gh_issue({ state = "all" }) end, desc = "GitHub Issues (all)" },
{ "<leader>gp", function() Snacks.picker.gh_pr() end, desc = "GitHub Pull Requests (open)" },
{ "<leader>gP", function() Snacks.picker.gh_pr({ state = "all" }) end, desc = "GitHub Pull Requests (all)" },
},
}
-- Browse open issues
Snacks.picker.gh_issue()
-- Browse all issues (including closed)
Snacks.picker.gh_issue({ state = "all" })
-- Browse open pull requests
Snacks.picker.gh_pr()
-- Browse all pull requests
Snacks.picker.gh_pr({ state = "all" })
-- View PR diff
Snacks.picker.gh_diff({ pr = 123 })
-- Open issue/PR in buffer
Snacks.gh.open({ type = "issue", number = 123, repo = "owner/repo" })
When viewing an issue or PR in the picker, press <cr> to show available actions:
Snacks.gh makes extensive use of Snacks.scratch for editing comments and descriptions.
Common Actions:
Pull Request/Issue Specific:
When you open an issue or PR in a buffer, you get a beautiful rendered view with:
Default Keymaps in GitHub Buffers:
| Key | Action | Description |
|---|---|---|
<cr> | Select Action | Show available actions menu |
i | Edit | Edit issue/PR title and body |
a | Add Comment | Add a new comment |
c | Close | Close the issue/PR |
o | Reopen | Reopen a closed issue/PR |
See the config section to customize these keymaps.
<!-- docgen -->-- lazy.nvim
{
"folke/snacks.nvim",
---@type snacks.Config
opts = {
gh = {
-- your gh configuration comes here
-- or leave it empty to use the default settings
-- refer to the configuration section below
}
}
}
---@class snacks.gh.Config
{
--- Keymaps for GitHub buffers
---@type table<string, snacks.gh.Keymap|false>?
keys = {
select = { "<cr>", "gh_actions", desc = "Select Action" },
edit = { "i" , "gh_edit" , desc = "Edit" },
comment = { "a" , "gh_comment", desc = "Add Comment" },
close = { "c" , "gh_close" , desc = "Close" },
reopen = { "o" , "gh_reopen" , desc = "Reopen" },
},
---@type vim.wo|{}
wo = {
breakindent = true,
wrap = true,
showbreak = "",
linebreak = true,
number = false,
relativenumber = false,
foldexpr = "v:lua.vim.treesitter.foldexpr()",
foldmethod = "expr",
concealcursor = "n",
conceallevel = 2,
list = false,
winhighlight = Snacks.util.winhl({
Normal = "SnacksGhNormal",
NormalFloat = "SnacksGhNormalFloat",
FloatBorder = "SnacksGhBorder",
FloatTitle = "SnacksGhTitle",
FloatFooter = "SnacksGhFooter",
}),
},
---@type vim.bo|{}
bo = {},
diff = {
min = 4, -- minimum number of lines changed to show diff
wrap = 80, -- wrap diff lines at this length
},
scratch = {
height = 15, -- height of scratch window
},
icons = {
logo = "ï ",
user= "ïœ ",
checkmark = "ïź ",
crossmark = "î©¶ ",
block = "â ",
file = "ï„ ",
checks = {
pending = "ïș ",
success = "ïź ",
failure = "ï§",
skipped = "îȘœ ",
},
issue = {
open = "ï ",
completed = "ï ",
other = "îȘœ "
},
pr = {
open = "î©€ ",
closed = "îŻ ",
merged = "ï ",
draft = "îŻ ",
other = "îŻ ",
},
review = {
approved = "ïź ",
changes_requested = "î ",
commented = "ï ",
dismissed = "ï± ",
pending = "ïș ",
},
merge_status = {
clean = "ïź ",
dirty = "î©¶ ",
blocked = "îȘœ ",
unstable = "ï± "
},
reactions = {
thumbs_up = "đ",
thumbs_down = "đ",
eyes = "đ",
confused = "đ",
heart = "â€ïž",
hooray = "đ",
laugh = "đ",
rocket = "đ",
},
},
}
---@alias snacks.gh.Keymap.fn fun(item:snacks.picker.gh.Item, buf:snacks.gh.Buf)
---@class snacks.gh.Keymap: vim.keymap.set.Opts
---@field [1] string lhs
---@field [2] string|snacks.gh.Keymap.fn rhs
---@field mode? string|string[] defaults to `n`
---@class snacks.gh
---@field api snacks.gh.api
---@field item snacks.picker.gh.Item
Snacks.gh = {}
Snacks.gh.issue()---@param opts? snacks.picker.gh.issue.Config
Snacks.gh.issue(opts)
Snacks.gh.pr()---@param opts? snacks.picker.gh.pr.Config
Snacks.gh.pr(opts)