Skip to content

Commit 19468a3

Browse files
BREAKING CHANGE: Delta Pager + Large Refactor (#43)
BREAKING CHANGE: This MR addresses an underlying issue with the original implementation in regards to detecting line numbers for comments. As such, this is a major breaking change. The setup function signature has changed, please review the `README.md` for the new arguments. The delta pager has also been added as a dependency: https://github.com/dandavison/delta There will be future work to implement a native solution for parsing changes and line numbers.
1 parent ed67a03 commit 19468a3

19 files changed

+1269
-963
lines changed

README.md

+68-61
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ This Neovim plugin is designed to make it easy to review Gitlab MRs from within
66
- Approve or revoke approval for an MR
77
- Add or remove reviewers and assignees
88
- Resolve, reply to, and unresolve discussion threads
9-
- Create, edit, delete, and reply to comments on an MR *
10-
11-
(*) This feature is currently in review, see https://github.com/harrisoncramer/gitlab.nvim/issues/25
9+
- Create, edit, delete, and reply to comments on an MR
1210

1311
And a lot more!
1412

@@ -18,6 +16,15 @@ https://github.com/harrisoncramer/gitlab.nvim/assets/32515581/dfd3aa8a-6fc4-4e43
1816

1917
- <a href="https://go.dev/">Go</a>
2018
- <a href="https://www.gnu.org/software/make/manual/make.html">make (for install)</a>
19+
- <a href="https://github.com/dandavison/delta">delta</a>
20+
21+
## Quick Start
22+
23+
1. Ensure Dependencies (Linux/Mac users can run the install script: ./install)
24+
2. Add config (below)
25+
3. Check out feature branch
26+
4. Open Neovim
27+
5. Run `:lua require("gitlab").review()` to open the reviewer pane, or `:lua require("gitlab").summary() to read the MR description and get started.
2128

2229
## Installation
2330

@@ -29,10 +36,10 @@ return {
2936
dependencies = {
3037
"MunifTanjim/nui.nvim",
3138
"nvim-lua/plenary.nvim",
32-
"stevearc/dressing.nvim" -- Recommended but not required. Better UI for pickers.
39+
"stevearc/dressing.nvim", -- Recommended but not required. Better UI for pickers.
3340
enabled = true,
3441
},
35-
build = function () require("gitlab").build() end, -- Builds the Go binary
42+
build = function () require("gitlab.server").build() end, -- Builds the Go binary
3643
config = function()
3744
require("gitlab").setup()
3845
end,
@@ -48,7 +55,7 @@ use {
4855
"MunifTanjim/nui.nvim",
4956
"nvim-lua/plenary.nvim"
5057
},
51-
run = function() require("gitlab").build() end,
58+
run = function() require("gitlab.server").build() end,
5259
config = function()
5360
require("gitlab").setup()
5461
end,
@@ -77,35 +84,40 @@ Here is the default setup function. All of these values are optional, and if you
7784

7885
```lua
7986
require("gitlab").setup({
80-
port = 20136, -- The port of the Go server, which runs in the background
81-
log_path = vim.fn.stdpath("cache") .. "gitlab.nvim.log", -- Log path for the Go server
82-
keymaps = {
83-
popup = { -- The popup for comment creation, editing, and replying
84-
exit = "<Esc>",
85-
perform_action = "<leader>s", -- Once in normal mode, does action (like saving comment or editing description, etc)
86-
},
87-
discussion_tree = { -- The discussion tree that holds all comments
88-
jump_to_location = "o", -- Jump to comment location in file
89-
edit_comment = "e", -- Edit coment
90-
delete_comment = "dd", -- Delete comment
91-
reply_to_comment = "r", -- Reply to comment
92-
toggle_resolved = "p" -- Toggles the resolved status of the discussion
93-
toggle_node = "t", -- Opens or closes the discussion
94-
position = "left", -- "top", "right", "bottom" or "left"
95-
relative = "editor" -- Position of tree split relative to "editor" or "window"
96-
size = "20%", -- Size of split
97-
},
98-
dialogue = { -- The confirmation dialogue for deleting comments
99-
focus_next = { "j", "<Down>", "<Tab>" },
100-
focus_prev = { "k", "<Up>", "<S-Tab>" },
101-
close = { "<Esc>", "<C-c>" },
102-
submit = { "<CR>", "<Space>" },
103-
}
87+
port = 21036, -- The port of the Go server, which runs in the background
88+
log_path = vim.fn.stdpath("cache") .. "/gitlab.nvim.log", -- Log path for the Go server
89+
reviewer = "delta", -- The reviewer type (only delta is currently supported)
90+
popup = { -- The popup for comment creation, editing, and replying
91+
exit = "<Esc>",
92+
perform_action = "<leader>s", -- Once in normal mode, does action (like saving comment or editing description, etc)
10493
},
105-
symbols = {
94+
discussion_tree = { -- The discussion tree that holds all comments
95+
jump_to_file = "o", -- Jump to comment location in file
96+
jump_to_reviewer = "m", -- Jump to the location in the reviewer window
97+
edit_comment = "e", -- Edit coment
98+
delete_comment = "dd", -- Delete comment
99+
reply = "r", -- Reply to comment
100+
toggle_node = "t", -- Opens or closes the discussion
101+
toggle_resolved = "p", -- Toggles the resolved status of the discussion
102+
position = "left", -- "top", "right", "bottom" or "left"
103+
size = "20%", -- Size of split
104+
relative = "editor", -- Position of tree split relative to "editor" or "window"
106105
resolved = '', -- Symbol to show next to resolved discussions
107106
unresolved = '', -- Symbol to show next to unresolved discussions
108-
}
107+
},
108+
review_pane = { -- Specific settings for different reviewers
109+
delta = {
110+
added_file = "", -- The symbol to show next to added files
111+
modified_file = "", -- The symbol to show next to modified files
112+
removed_file = "", -- The symbol to show next to removed files
113+
}
114+
},
115+
dialogue = { -- The confirmation dialogue for deleting comments
116+
focus_next = { "j", "<Down>", "<Tab>" },
117+
focus_prev = { "k", "<Up>", "<S-Tab>" },
118+
close = { "<Esc>", "<C-c>" },
119+
submit = { "<CR>", "<Space>" },
120+
},
109121
})
110122
```
111123

@@ -117,31 +129,42 @@ First, check out the branch that you want to review locally.
117129
git checkout feature-branch
118130
```
119131

120-
Then open Neovim and the reviewer will be initialized. The `project_id` you specify in your configuration file must match the project_id of the Gitlab project your terminal is inside of.
132+
Then open Neovim. The `project_id` you specify in your configuration file must match the project_id of the Gitlab project your terminal is inside of.
121133

122134
The `summary` command will pull down the MR description into a buffer so that you can read it. To edit the description, edit the buffer and press the `perform_action` keybinding when in normal mode (it's `<leader>s` by default):
123135

124136
```lua
125137
require("gitlab").summary()
126138
```
127139

128-
129-
The `approve` command will approve the merge request for the current branch:
140+
The `review` command will open up view of all the changes that have been made in this MR compared to the target branch in a review pane. You can leave comments on the changes.
130141

131142
```lua
132-
require("gitlab").approve()
143+
require("gitlab").review()
144+
require("gitlab").create_comment()
133145
```
134146

135-
The `revoke` command will revoke approval for the merge request for the current branch:
147+
Gitlab groups threads of comments together into "discussions."
148+
149+
To display discussions for the current MR, use the `list_discussions()` command, which will show the discussions in a split window.
150+
151+
You can jump to the comment's location the reviewer window by using the `m` key, or the actual file with the 'j' key, when hovering over the line in the tree.
152+
153+
Within the discussion tree, you can delete/edit/reply to comments, or toggle them as resolved or not.
136154

137155
```lua
138-
require("gitlab").revoke()
156+
require("gitlab").list_discussions()
157+
require("gitlab").delete_comment()
158+
require("gitlab").edit_comment()
159+
require("gitlab").reply()
160+
require("gitlab").toggle_resolved()
139161
```
140162

141-
The `comment` command will open up a NUI popover that will allow you to create a Gitlab comment on the current line. To send the comment, use `<leader>s` while the comment popup is open:
163+
You can approve or revoke approval for an MR:
142164

143165
```lua
144-
require("gitlab").create_comment()
166+
require("gitlab").approve()
167+
require("gitlab").revoke()
145168
```
146169

147170
The `add_reviewer` and `delete_reviewer` commands, as well as the `add_assignee` and `delete_assignee` functions, will let you choose from a list of users who are availble in the current project:
@@ -163,23 +186,6 @@ require("dressing").setup({
163186
})
164187
```
165188

166-
### Discussions
167-
168-
Gitlab groups threads of notes together into "discussions." To get a list of all the discussions for the current MR, use the `list_discussions` command. This command will open up a split view of all the comments on the current merge request. You can jump to the comment location by using the `o` key in the tree buffer, and you can reply to a thread by using the `r` keybinding in the tree buffer:
169-
170-
```lua
171-
require("gitlab").list_discussions()
172-
```
173-
174-
Within the discussion tree, there are several functions that you can call, however, it's better to use the keybindings provided in the setup function. If you want to call them manually, they are:
175-
176-
```lua
177-
require("gitlab").delete_comment()
178-
require("gitlab").edit_comment()
179-
require("gitlab").reply()
180-
require("gitlab").toggle_resolved()
181-
```
182-
183189
## Keybindings
184190

185191
The plugin does not set up any keybindings outside of these buffers, you need to set them up yourself. Here's what I'm using:
@@ -189,8 +195,7 @@ local gitlab = require("gitlab")
189195
vim.keymap.set("n", "<leader>gls", gitlab.summary)
190196
vim.keymap.set("n", "<leader>glA", gitlab.approve)
191197
vim.keymap.set("n", "<leader>glR", gitlab.revoke)
192-
vim.keymap.set("n", "<leader>glc", gitlab.create_comment)
193-
vim.keymap.set("n", "<leader>gld", gitlab.list_discussions)
198+
vim.keymap.set("n", "<leader>glr", gitlab.review)
194199
vim.keymap.set("n", "<leader>glaa", gitlab.add_assignee)
195200
vim.keymap.set("n", "<leader>glad", gitlab.delete_assignee)
196201
vim.keymap.set("n", "<leader>glra", gitlab.add_reviewer)
@@ -199,11 +204,13 @@ vim.keymap.set("n", "<leader>glrd", gitlab.delete_reviewer)
199204

200205
## Troubleshooting
201206

207+
**To check that the current settings of the plugin are configured correctly, please run: `:lua require("gitlab").print_settings()`**
208+
202209
This plugin uses a Golang server to reach out to Gitlab. It's possible that something is going wrong when starting that server or connecting with Gitlab. The Golang server runs outside of Neovim, and can be interacted with directly in order to troubleshoot. To start the server, check out your feature branch and run these commands:
203210

204211
```
205-
:lua require("gitlab").build()
206-
:lua require("gitlab").start_server()
212+
:lua require("gitlab.server").build()
213+
:lua require("gitlab.server").start()
207214
```
208215

209216
You can directly interact with the Go server like any other process:

cmd/comment.go

+4-13
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ const mrVersionsUrl = "%s/api/v4/projects/%s/merge_requests/%d/versions"
1414
type PostCommentRequest struct {
1515
Comment string `json:"comment"`
1616
FileName string `json:"file_name"`
17-
LineNumber int `json:"line_number"`
17+
NewLine int `json:"new_line"`
18+
OldLine int `json:"old_line"`
1819
HeadCommitSHA string `json:"head_commit_sha"`
1920
BaseCommitSHA string `json:"base_commit_sha"`
2021
StartCommitSHA string `json:"start_commit_sha"`
@@ -113,18 +114,8 @@ func PostComment(w http.ResponseWriter, r *http.Request) {
113114
BaseSHA: postCommentRequest.BaseCommitSHA,
114115
NewPath: postCommentRequest.FileName,
115116
OldPath: postCommentRequest.FileName,
116-
}
117-
118-
/* TODO: This switch statement relates to #25, for now we are just sending both
119-
the old line and new line but we will eventually have to fix this */
120-
switch postCommentRequest.Type {
121-
case "addition":
122-
position.NewLine = postCommentRequest.LineNumber
123-
case "subtraction":
124-
position.OldLine = postCommentRequest.LineNumber
125-
case "modification":
126-
position.NewLine = postCommentRequest.LineNumber
127-
position.OldLine = postCommentRequest.LineNumber
117+
NewLine: postCommentRequest.NewLine,
118+
OldLine: postCommentRequest.OldLine,
128119
}
129120

130121
discussion, _, err := c.git.Discussions.CreateMergeRequestDiscussion(

lua/gitlab/actions/approvals.lua

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
local job = require("gitlab.job")
2+
3+
local M = {}
4+
5+
M.approve = function()
6+
job.run_job("/approve", "POST")
7+
end
8+
9+
M.revoke = function()
10+
job.run_job("/revoke", "POST")
11+
end
12+
13+
return M

lua/gitlab/assignees_and_reviewers.lua renamed to lua/gitlab/actions/assignees_and_reviewers.lua

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
-- This module is responsible for the assignment of reviewers
2+
-- and assignees in Gitlab, those who must review an MR.
13
local u = require("gitlab.utils")
24
local job = require("gitlab.job")
35
local state = require("gitlab.state")
@@ -33,7 +35,7 @@ M.add_popup = function(type)
3335
local current_ids = u.extract(current, 'id')
3436
table.insert(current_ids, choice.id)
3537
local json = vim.json.encode({ ids = current_ids })
36-
job.run_job("mr/" .. type, "PUT", json, function(data)
38+
job.run_job("/mr/" .. type, "PUT", json, function(data)
3739
vim.notify(data.message, vim.log.levels.INFO)
3840
state.INFO[plural] = data[plural]
3941
end)
@@ -52,7 +54,7 @@ M.delete_popup = function(type)
5254
if not choice then return end
5355
local ids = u.extract(M.filter_eligible(current, { choice }), 'id')
5456
local json = vim.json.encode({ ids = ids })
55-
job.run_job("mr/" .. type, "PUT", json, function(data)
57+
job.run_job("/mr/" .. type, "PUT", json, function(data)
5658
vim.notify(data.message, vim.log.levels.INFO)
5759
state.INFO[plural] = data[plural]
5860
end)

lua/gitlab/actions/comment.lua

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
-- This module is responsible for creating new comments
2+
-- in the reviewer's buffer. The reviewer will pass back
3+
-- to this module the data required to make the API calls
4+
local Popup = require("nui.popup")
5+
local state = require("gitlab.state")
6+
local job = require("gitlab.job")
7+
local u = require("gitlab.utils")
8+
local discussions = require("gitlab.actions.discussions")
9+
local reviewer = require("gitlab.reviewer")
10+
local M = {}
11+
12+
local comment_popup = Popup(u.create_popup_state("Comment", "40%", "60%"))
13+
14+
-- This function will open a comment popup in order to create a comment on the changed/updated line in the current MR
15+
M.create_comment = function()
16+
comment_popup:mount()
17+
state.set_popup_keymaps(comment_popup, M.confirm_create_comment)
18+
end
19+
20+
-- This function (settings.popup.perform_action) will send the comment to the Go server
21+
M.confirm_create_comment = function(text)
22+
local file_name, line_numbers, error = reviewer.get_location()
23+
24+
if error then
25+
vim.notify(error, vim.log.levels.ERROR)
26+
return
27+
end
28+
29+
if file_name == nil then
30+
vim.notify("Reviewer did not provide file name", vim.log.levels.ERROR)
31+
return
32+
end
33+
34+
if line_numbers == nil then
35+
vim.notify("Reviewer did not provide line numbers of change", vim.log.levels.ERROR)
36+
return
37+
end
38+
39+
if text == nil then
40+
vim.notify("Reviewer did not provide text of change", vim.log.levels.ERROR)
41+
return
42+
end
43+
44+
local revision = state.MR_REVISIONS[1]
45+
local jsonTable = {
46+
comment = text,
47+
file_name = file_name,
48+
old_line = line_numbers.old_line,
49+
new_line = line_numbers.new_line,
50+
base_commit_sha = revision.base_commit_sha,
51+
start_commit_sha = revision.start_commit_sha,
52+
head_commit_sha = revision.head_commit_sha,
53+
type = "modification"
54+
}
55+
56+
local json = vim.json.encode(jsonTable)
57+
58+
job.run_job("/comment", "POST", json, function(data)
59+
vim.notify("Comment created")
60+
discussions.refresh_tree()
61+
end)
62+
end
63+
64+
return M

0 commit comments

Comments
 (0)