/octo.nvim

Edit and review GitHub issues and pull requests from the comfort of your favorite editor

Primary LanguageLuaMIT LicenseMIT

πŸ™ Octo.nvim

GitHub in NeoVim.

GitHub repository size Issues License
Say thanks Latest commit Repository's starts

image

Issue/Pull Request listing

image

Issue/Pull Request buffer

image

PR review panel

TL;DR

Edit and review GitHub issues and pull requests from the comfort of your favorite editor.

🌲 Table of Contents

✨ Features

  • Edit GitHub issues and PRs
  • Add/Modify/Delete comments
  • Add/Remove label, reactions, assignees, project cards, reviewers, etc.
  • Add Review PRs

⚑️Requirements

πŸ“¦ Installation

Use your favourite plugin manager to install it. eg:

use {'pwntester/octo.nvim', config=function()
  require"octo".setup()
end}

βš™οΈ Configuration

use {'pwntester/octo.nvim', config=function()
  require"octo".setup({
  date_format = "%Y %b %d %I:%M %p %Z";    -- date format
  default_remote = {"upstream", "origin"}; -- order to try remotes
  reaction_viewer_hint_icon = "ο‘„";         -- marker for user reactions
  user_icon = " ";                        -- user icon
  timeline_marker = "ο‘ ";                   -- timeline marker
  timeline_indent = "2";                   -- timeline indentation
  right_bubble_delimiter = "ξ‚΄";            -- Bubble delimiter
  left_bubble_delimiter = "ξ‚Ά";             -- Bubble delimiter
  github_hostname = "";                    -- GitHub Enterprise host
  snippet_context_lines = 4;               -- number or lines around commented lines
  file_panel = {
    size = 10,                             -- changed files panel rows
    use_icons = true                       -- use web-devicons in file panel
  },
  mappings = {
    issue = {
      close_issue = "<space>ic",           -- close issue
      reopen_issue = "<space>io",          -- reopen issue
      list_issues = "<space>il",           -- list open issues on same repo
      reload = "<C-r>",                    -- reload issue
      open_in_browser = "<C-o>",           -- open issue in browser
      add_assignee = "<space>aa",          -- add assignee
      remove_assignee = "<space>ad",       -- remove assignee
      add_label = "<space>la",             -- add label
      remove_label = "<space>ld",          -- remove label
      goto_issue = "<space>gi",            -- navigate to a local repo issue
      add_comment = "<space>ca",           -- add comment
      delete_comment = "<space>cd",        -- delete comment
      next_comment = "]c",                 -- go to next comment
      prev_comment = "[c",                 -- go to previous comment
      react_hooray = "<space>rp",          -- add/remove πŸŽ‰ reaction
      react_heart = "<space>rh",           -- add/remove ❀️ reaction
      react_eyes = "<space>re",            -- add/remove πŸ‘€ reaction
      react_thumbs_up = "<space>r+",       -- add/remove πŸ‘ reaction
      react_thumbs_down = "<space>r-",     -- add/remove πŸ‘Ž reaction
      react_rocket = "<space>rr",          -- add/remove πŸš€ reaction
      react_laugh = "<space>rl",           -- add/remove πŸ˜„ reaction
      react_confused = "<space>rc",        -- add/remove πŸ˜• reaction
    },
    pull_request = {
      checkout_pr = "<space>po",           -- checkout PR
      merge_pr = "<space>pm",              -- merge PR
      list_commits = "<space>pc",          -- list PR commits
      list_changed_files = "<space>pf",    -- list PR changed files
      show_pr_diff = "<space>pd",          -- show PR diff
      add_reviewer = "<space>va",          -- add reviewer
      remove_reviewer = "<space>vd",       -- remove reviewer request
      close_issue = "<space>ic",           -- close PR
      reopen_issue = "<space>io",          -- reopen PR
      list_issues = "<space>il",           -- list open issues on same repo
      reload = "<C-r>",                    -- reload PR
      open_in_browser = "<C-o>",           -- open PR in browser
      add_assignee = "<space>aa",          -- add assignee
      remove_assignee = "<space>ad",       -- remove assignee
      add_label = "<space>la",             -- add label
      remove_label = "<space>ld",          -- remove label
      goto_issue = "<space>gi",            -- navigate to a local repo issue
      add_comment = "<space>ca",           -- add comment
      delete_comment = "<space>cd",        -- delete comment
      next_comment = "]c",                 -- go to next comment
      prev_comment = "[c",                 -- go to previous comment
      react_hooray = "<space>rp",          -- add/remove πŸŽ‰ reaction
      react_heart = "<space>rh",           -- add/remove ❀️ reaction
      react_eyes = "<space>re",            -- add/remove πŸ‘€ reaction
      react_thumbs_up = "<space>r+",       -- add/remove πŸ‘ reaction
      react_thumbs_down = "<space>r-",     -- add/remove πŸ‘Ž reaction
      react_rocket = "<space>rr",          -- add/remove πŸš€ reaction
      react_laugh = "<space>rl",           -- add/remove πŸ˜„ reaction
      react_confused = "<space>rc",        -- add/remove πŸ˜• reaction
    },
    review_thread = {
      goto_issue = "<space>gi",            -- navigate to a local repo issue
      add_comment = "<space>ca",           -- add comment
      add_suggestion = "<space>sa",        -- add suggestion
      delete_comment = "<space>cd",        -- delete comment
      next_comment = "]c",                 -- go to next comment
      prev_comment = "[c",                 -- go to previous comment
      select_next_entry = "]q",            -- move to previous changed file
      select_prev_entry = "[q",            -- move to next changed file
      close_review_tab = "<C-c>",          -- close review tab
      react_hooray = "<space>rp",          -- add/remove πŸŽ‰ reaction
      react_heart = "<space>rh",           -- add/remove ❀️ reaction
      react_eyes = "<space>re",            -- add/remove πŸ‘€ reaction
      react_thumbs_up = "<space>r+",       -- add/remove πŸ‘ reaction
      react_thumbs_down = "<space>r-",     -- add/remove πŸ‘Ž reaction
      react_rocket = "<space>rr",          -- add/remove πŸš€ reaction
      react_laugh = "<space>rl",           -- add/remove πŸ˜„ reaction
      react_confused = "<space>rc",        -- add/remove πŸ˜• reaction
    },
    review_diff = {
      add_review_comment = "<space>ca",    -- add a new review comment
      add_review_suggestion = "<space>sa", -- add a new review suggestion
      focus_files = "<leader>e",           -- move focus to changed file panel
      toggle_files = "<leader>b",          -- hide/show changed files panel
      next_thread = "]t",                  -- move to next thread
      prev_thread = "[t",                  -- move to previous thread
      select_next_entry = "]q",            -- move to previous changed file
      select_prev_entry = "[q",            -- move to next changed file
      close_review_tab = "<C-c>",          -- close review tab
    },
    submit_win = {
      approve_review = "<C-a>",            -- approve review
      comment_review = "<C-m>",            -- comment review
      request_changes = "<C-r>",           -- request changes review
      close_review_tab = "<C-c>",          -- close review tab
    },
    file_panel = {
      next_entry = "j",                    -- move to next changed file
      prev_entry = "k",                    -- move to previous changed file
      select_entry = "<cr>",               -- show selected changed file diffs
      refresh_files = "R",                 -- refresh changed files panel
      focus_files = "<leader>e",           -- move focus to changed file panel
      toggle_files = "<leader>b",          -- hide/show changed files panel
      select_next_entry = "]q",            -- move to previous changed file
      select_prev_entry = "[q",            -- move to next changed file
      close_review_tab = "<C-c>",          -- close review tab
    }
  }
})
end}

πŸš€ Usage

Just edit the issue title, body or comments as a regular buffer and use :w(rite) to sync the issue with GitHub.

πŸ€– Commands

There is only an Octo <object> <action> [arguments] command: If no command is passed, the argument to Octo is treated as a URL from where an issue or pr repo and number are extracted

Object Action Arguments
issue close Close the current issue
reopen Reopen the current issue
create [repo] Creates a new issue in the current or specified repo
edit [repo] Edit issue <number> in current or specified repo
list [repo] [key=value] (1) List all issues satisfying given filter
search Live issue search
reload Reload issue. Same as doing e!
browser Open current issue in the browser
pr list [repo] [key=value] (2) List all PRs satisfying given filter
search Live issue search
edit [repo] Edit PR <number> in current or specified repo
reopen Reopen the current PR
close Close the current PR
checkout Checkout PR
commits List all PR commits
changes Show all PR changes (diff hunks)
diff Show PR diff
merge [commit|rebase|squash] [delete] Merge current PR using the specified method
ready Mark a draft PR as ready for review
checks Show the status of all checks run on the PR
reload Reload PR. Same as doing e!
browser Open current PR in the browser
gist list [repo] [key=value] List user gists
comment add Add a new comment
delete Delete a comment
thread resolve Mark a review thread as resolved
unresolve Mark a review thread as unresolved
label add Add a label from available label menu
remove Remove a label
assignees add Assign a user
remove Unassign a user
reviewer add Assign a PR reviewer
reaction thumbs_up | +1 Add πŸ‘ reaction
thumbs_down | -1 Add πŸ‘Ž reaction
eyes Add πŸ‘€ reaction
laugh Add πŸ˜„ reaction
confused Add πŸ˜• reaction
rocket Add πŸš€ reaction
heart Add ❀️ reaction
hooray | party | tada Add πŸŽ‰ reaction
card add Assign issue/PR to a project new card
remove Delete project card
move Move project card to different project/column
review start Start a new review
submit Submit the review
resume Edit a pending review for current PR
discard Deletes a pending review for current PR if any
comments View pending review comments
  1. [repo]: If repo is not provided, it will be derived from <cwd>/.git/config.

  2. In-menu mappings:

  1. In-menu mappings:
  1. In-menu mappings:
  • <CR>: Append Gist to buffer
  • <C-b>: Opens Gist in web browser Available keys: repo|public|secret

πŸ”₯ Examples

Octo https://github.com/pwntester/octo.nvim/issues/12
Octo issue create
Octo issue create pwntester/octo.nvim
Octo comment add
Octo reaction add hooray
Octo issue edit pwntester/octo.nvim 1
Octo issue edit 1
Octo issue list createdBy=pwntester
Octo issue list neovim/neovim labels=bug,help\ wanted states=OPEN

πŸ“‹ PR review

  • Open the PR (eg: Octo pr list or Octo pr edit XXX)
  • Start a review with Octo review start or resume a pending review with Octo review resume
  • Quickfix will be populated with the PR changed files
  • Change quickfix entries with ]q and [q or by selecting an entry in the quickfix window
  • Add comments with <space>ca or suggestions with <space>sa on single or multiple visual-selected lines
    • A new buffer will appear in the alternate diff window. Cursor will be positioned in the new buffer
    • When ready, save the buffer to commit changes to GitHub
    • Move back to the diff window and move the cursor, the thread buffer will hide
  • Hold the cursor on a line with a comment to show a thread buffer with all the thread comments
    • To modify, delete, react or reply to a comment, move to the window containing the thread buffer
    • Perform any operations as if you were in a regular issue buffer
  • Review pending comments with Octo review comments
    • Use to jump to the selected pending comment
  • When ready, submit the review with Octo review submit
  • A new float window will pop up. Enter the top level review comment and exit to normal mode. Then press <C-m> to submit a comment, <C-a> to approve it or <C-r> to request changes

🍞 Completion

  • Issue/PR id completion (#)
  • User completion (@)

🎨 Colors

Highlight Group Defaults to
OctoDirty ErrorMsg
OctoIssueTitle PreProc
OctoIssueId Question
OctoEmpty Comment
OctoFloat NormalNC
OctoDate Comment
OctoSymbol Comment
OctoTimelineItemHeading Comment
OctoDetailsLabel Title
OctoMissingDetails Comment
*OctoDetailsValue * Identifier
OctoDiffHunkPosition NormalFloat
OctoCommentLine TabLineSel
OctoEditable NormalFloat
OctoViewer GitHub color
OctoBubble NormalFloat
OctoBubbleGreen GitHub color
OctoBubbleRed GitHub color
OctoUser OctoBubble
OctoUserViewer OctoViewer
OctoReaction OctoBubble
OctoReactionViewer OctoViewer
OctoPassingTest GitHub color
OctoFailingTest GitHub color
OctoPullAdditions GitHub color
OctoPullDeletions GitHub color
OctoPullModifications GitHub color
OctoStateOpen GitHub color
OctoStateClosed GitHub color
OctoStateMerge GitHub color
OctoStatePending GitHub color
OctoStateApproved OctoStateOpen
OctoStateChangesRequested OctoStateClosed
OctoStateCommented Normal
OctoStateDismissed OctoStateClosed

The term GitHub color refers to the colors used in the WebUI. The (addition) viewer means the user of the plugin or more precisely the user authenticated via the gh CLI tool used to retrieve the data from GitHub.

πŸ™‹ FAQ

How can I disable bubbles for XYZ?

Each text-object that makes use of a bubble (except labels) do use their own highlight group that linkes per default to the main bubble highlight group. To disable most bubbles at once you can simply link OctoBubble to Normal. To only disable them for a certain plain do the same for the specific sub-group (e.g. OctoUser).

Why do my issue titles or markdown syntax do not get highlighted properly?

The title, body and comments of an issue or PR are special as they get special highlighting applied and is an editable section. Due to the latter property it gets the OctoEditable highlighting via a special signs linehl setting. This takes precedence over the buffer internal highlights. To only get the background highlighted by the editable section, set OctoEditable to a highlight with a background color definition only.

βœ‹ Contributing

Contributions are always welcome!

See CONTRIBUTING for ways to get started.

Please adhere to this project's CODE_OF_CONDUCT.

🌟 Credits

The PR review panel is heavily inspired in diffview.nvim

πŸ“œ License

MIT