Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,5 +204,6 @@ These `keymaps` are active in the reviewer window (the diff view).
```
c Create a comment for the lines that the following {motion} moves over
s Create a suggestion for the lines that the following {motion} moves over
S Create a suggestion with preview in a new tab for the lines that the following {motion} moves over
a Jump to the comment in the discussion tree
```
4 changes: 2 additions & 2 deletions cmd/app/comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ type DeleteCommentRequest struct {
DiscussionId string `json:"discussion_id" validate:"required"`
}

/* deleteComment deletes a note, multiline comment, or comment, which are all considered discussion notes. */
/* deleteComment deletes a note or comment, which are all considered discussion notes. */
func (a commentService) deleteComment(w http.ResponseWriter, r *http.Request) {
payload := r.Context().Value(payload("payload")).(*DeleteCommentRequest)

Expand Down Expand Up @@ -81,7 +81,7 @@ func (comment CommentWithPosition) GetPositionData() PositionData {
return comment.PositionData
}

/* postComment creates a note, multiline comment, or comment. */
/* postComment creates a note or comment. */
func (a commentService) postComment(w http.ResponseWriter, r *http.Request) {
payload := r.Context().Value(payload("payload")).(*PostCommentRequest)

Expand Down
91 changes: 47 additions & 44 deletions doc/gitlab.nvim.txt
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,22 @@ you call this function with no values the defaults will be used:
toggle_unresolved_discussions = "U", -- Open or close all unresolved discussions
refresh_data = "<C-R>", -- Refresh the data in the view by hitting Gitlab's APIs again
print_node = "<leader>p", -- Print the current node (for debugging)
edit_suggestion = "se", -- Edit comment with suggestion preview in a new tab
reply_with_suggestion = "sr", -- Reply to comment with a suggestion preview in a new tab
apply_suggestion = "sa", -- Apply the suggestion to the local file with a preview in a new tab
},
suggestion_preview = {
apply_changes = "ZZ", -- Close suggestion preview tab, and post comment to Gitlab (discarding changes to local file). In "apply mode", accept suggestion, commit changes, then push to remote and resolve thread
discard_changes = "ZQ", -- Close suggestion preview tab and discard changes in local file
attach_file = "ZA", -- Attach a file from the `settings.attachment_dir`
apply_changes_locally = "Zz", -- Only in "apply mode", close suggestion preview tab and write suggestion buffer to local file (no changes posted to Gitlab)
paste_default_suggestion = "glS", -- Paste the default suggestion below the cursor (overrides default "glS" (start review) keybinding for the "Note" buffer)
},
reviewer = {
disable_all = false, -- Disable all default mappings for the reviewer windows
create_comment = "c", -- Create a comment for the lines that the following {motion} moves over. Repeat the key(s) for creating comment for the current line
create_suggestion = "s", -- Create a suggestion for the lines that the following {motion} moves over. Repeat the key(s) for creating comment for the current line
create_suggestion_with_preview = "S", -- In a new tab create a suggestion with a diff preview for the lines that the following {motion} moves over. Repeat the key(s) for creating comment for the current line
move_to_discussion_tree = "a", -- Jump to the comment in the discussion tree
},
},
Expand Down Expand Up @@ -438,23 +449,19 @@ the configuration.

REVIEWING AN MR *gitlab.nvim.reviewing-an-mr*

The `review` action will open a diff of the changes. You can leave comments
using the `create_comment` action. In visual mode, add multiline comments with
the `create_multiline_comment` command, and add suggested changes with the
`create_comment_suggestion` command:
The `review` action opens a diff of the changes (see |gitlab.nvim.review|).
Alternatively, use `choose_merge_request` for more flexibility in choosing the
MR (see |gitlab.nvim.choose_merge_request|).
>lua
require("gitlab").review()
require("gitlab").create_comment()
require("gitlab").create_multiline_comment()
require("gitlab").create_comment_suggestion()
require("gitlab").choose_merge_request({ labels = {"include_mrs_with_label"} })
<
For suggesting changes you can use `create_comment_suggestion` in visual mode
which works similar to `create_multiline_comment` but prefills the comment
window with Gitlab’s suggest changes
<https://docs.gitlab.com/ee/user/project/merge_requests/reviews/suggestions.html>
code block with prefilled code from the visual selection. Just like the
summary, all the different kinds of comments are saved via the
`keymaps.popup.perform_action` keybinding.
You can leave comments in the reviewer windows using the `keymaps.reviewer`
keybindings which work in normal mode as operators and in visual mode they
create comments on the selected lines. Alternatively, you can use the
`create_comment` action in your custom mappings (see
|gitlab.nvim.create_comment|). See `settings.keymaps.popup` for the
keybindings available in the popup windows.

DRAFT NOTES *gitlab.nvim.draft-comments*

Expand Down Expand Up @@ -584,9 +591,11 @@ emojis that you have responded with.
UPLOADING FILES *gitlab.nvim.uploading-files*

To attach a file to an MR description, reply, comment, and so forth use the
`keymaps.popup.perform_linewise_action` keybinding when the popup is open.
This will open a picker that will look for files in the directory you specify
in the `settings.attachment_dir` folder (this must be an absolute path).
`keymaps.popup.perform_linewise_action` keybinding when the popup is open (or
the `keymaps.suggestion_preview.attach_file` in the comment buffer of the
suggestion preview). This will open a picker that will look for files in the
directory you specify in the `settings.attachment_dir` folder (this must be an
absolute path).

When you have picked the file, it will be added to the current buffer at the
current line.
Expand Down Expand Up @@ -870,35 +879,29 @@ have permission or has not previously approved the MR.
*gitlab.nvim.create_comment*
gitlab.create_comment() ~

Opens a popup to create a comment on the current line. Must be called when focused on the
reviewer pane (see the gitlab.nvim.review command), otherwise it will error.
Opens a popup to create a comment on the selected line(s) in the current
buffer. Must be called when focused on the reviewer pane (see the
|gitlab.nvim.review| command). In normal mode comments on the current line. In
visual mode comments on the selected lines:
>lua
require("gitlab").create_comment()

After the comment is typed, submit it to Gitlab via the
`keymaps.popup.perform_action` keybinding, by default `ZZ`.

*gitlab.nvim.create_multiline_comment*
gitlab.create_multiline_comment() ~

Opens a popup to create a multi-line comment. May only be called in visual
mode, and will use the currently selected lines.
>lua
require("gitlab").create_multiline_comment()

After the comment is typed, submit it to Gitlab via the
`keymaps.popup.perform_linewise_action` keybinding, by default `ZA`.

*gitlab.nvim.create_comment_suggestion*
gitlab.create_comment_suggestion() ~

Opens a popup to create a comment suggestion (aka a comment that makes a committable
change suggestion to the currently selected lines).
>lua
require("gitlab").create_multiline_comment()

After the comment is typed, submit it to Gitlab via the
`keymaps.popup.perform_linewise_action` keybinding, by default `ZA`.
require("gitlab").create_comment({ with_suggestion = true })
<
Parameters: ~
• {opts}: (table|nil) Keyword arguments that can be used to include
a suggestion in the comment.
• {with_suggestion} (boolean) When true, pastes into the comment
buffer Gitlab’s suggestion code block prefilled with the
original text from the visual selection. See
https://docs.gitlab.com/ee/user/project/merge_requests/reviews/suggestions.html.

In the popup, you can use the `keymaps.popup.perform_linewise_action`
keybinding (by default `ZA`) to attach a file to the comment. After the
comment is typed, submit it to Gitlab via the `keymaps.popup.perform_action`
keybinding, by default `ZZ`. Discard the comment with
`keymaps.popup.discard_changes` (`ZQ`), otherwise if you close the popup with
something like `<c-w>q`, the comment contents are saved to the temporary
register(s) (|gitlab.nvim.temp-registers|).

*gitlab.nvim.create_mr*
gitlab.create_mr({opts}) ~
Expand Down
124 changes: 56 additions & 68 deletions lua/gitlab/actions/comment.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,32 @@ local M = {
comment_popup = nil,
}

---Decide if the comment is a draft based on the draft popup field.
---@return boolean|nil is_draft True if the draft popup exists and the string it contains converts to `true`. If the draft popup does not exist, return nil.
local get_draft_value_from_popup = function()
local buf_is_valid = M.draft_popup and M.draft_popup.bufnr and vim.api.nvim_buf_is_valid(M.draft_popup.bufnr)
if buf_is_valid then
return u.string_to_bool(u.get_buffer_text(M.draft_popup.bufnr))
else
return nil
end
end

---Fires the API that sends the comment data to the Go server, called when you "confirm" creation
---via the M.settings.keymaps.popup.perform_action keybinding
---@param text string comment text
---@param unlinked boolean if true, the comment is not linked to a line
---@param discussion_id string | nil The ID of the discussion to which the reply is responding, nil if not a reply
local confirm_create_comment = function(text, unlinked, discussion_id)
M.confirm_create_comment = function(text, unlinked, discussion_id)
if text == nil then
u.notify("Reviewer did not provide text of change", vim.log.levels.ERROR)
return
end

local is_draft = M.draft_popup and u.string_to_bool(u.get_buffer_text(M.draft_popup.bufnr))
local is_draft = get_draft_value_from_popup()
if is_draft == nil then
is_draft = state.settings.discussion_tree.draft_mode
end

-- Creating a normal reply to a discussion
if discussion_id ~= nil and not is_draft then
Expand Down Expand Up @@ -188,13 +202,13 @@ M.create_comment_layout = function(opts)
---Keybinding for focus on draft section
popup.set_popup_keymaps(M.draft_popup, function()
local text = u.get_buffer_text(M.comment_popup.bufnr)
confirm_create_comment(text, unlinked, opts.discussion_id)
M.confirm_create_comment(text, unlinked, opts.discussion_id)
vim.api.nvim_set_current_win(current_win)
end, miscellaneous.toggle_bool, popup.non_editable_popup_opts)

---Keybinding for focus on text section
popup.set_popup_keymaps(M.comment_popup, function(text)
confirm_create_comment(text, unlinked, opts.discussion_id)
M.confirm_create_comment(text, unlinked, opts.discussion_id)
vim.api.nvim_set_current_win(current_win)
end, miscellaneous.attach_file, popup.editable_popup_opts)

Expand All @@ -206,29 +220,33 @@ M.create_comment_layout = function(opts)
return layout
end

--- This function will open a comment popup in order to create a comment on the changed/updated
--- line in the current MR
M.create_comment = function()
--- Creates a comment on the selected line(s) in the current buffer.
--- In normal mode comments on the current line.
--- In visual mode comments on the whole selection.
---@param opts CreateCommentsOpts?
M.create_comment = function(opts)
opts = opts or {}
M.location = Location.new()
if not M.can_create_comment(false) then
return
end

local suggestion_lines = require("gitlab.actions.suggestions").build_suggestion(
vim.api.nvim_buf_get_lines(0, 0, -1, false),
M.location.visual_range.start_line,
M.location.visual_range.end_line
)

local layout = M.create_comment_layout({ unlinked = false })
layout:mount()
end

--- This function will open a multi-line comment popup in order to create a multi-line comment
--- on the changed/updated line in the current MR
M.create_multiline_comment = function()
M.location = Location.new()
if not M.can_create_comment(true) then
u.press_escape()
return
if opts.with_suggestion then
vim.schedule(function()
if suggestion_lines then
vim.api.nvim_buf_set_lines(M.comment_popup.bufnr, 0, -1, false, suggestion_lines)
end
end)
end

local layout = M.create_comment_layout({ unlinked = false })
layout:mount()
end

--- This function will open a a popup to create a "note" (e.g. unlinked comment)
Expand All @@ -238,61 +256,31 @@ M.create_note = function()
layout:mount()
end

---Given the current visually selected area of text, builds text to fill in the
---comment popup with a suggested change
---@return LineRange|nil
local build_suggestion = function()
local current_line = vim.api.nvim_win_get_cursor(0)[1]
local range_length = M.location.visual_range.end_line - M.location.visual_range.start_line
local backticks = "```"
local selected_lines = u.get_lines(M.location.visual_range.start_line, M.location.visual_range.end_line)

for _, line in ipairs(selected_lines) do
if string.match(line, "^```%S*$") then
backticks = "````"
break
end
end

local suggestion_start
if M.location.visual_range.start_line == current_line then
suggestion_start = backticks .. "suggestion:-0+" .. range_length
elseif M.location.visual_range.end_line == current_line then
suggestion_start = backticks .. "suggestion:-" .. range_length .. "+0"
else
--- This should never happen afaik
u.notify("Unexpected suggestion position", vim.log.levels.ERROR)
return nil
end
suggestion_start = suggestion_start
local suggestion_lines = {}
table.insert(suggestion_lines, suggestion_start)
vim.list_extend(suggestion_lines, selected_lines)
table.insert(suggestion_lines, backticks)

return suggestion_lines
end

--- This function will open a a popup to create a suggestion comment
--- on the changed/updated line in the current MR
--- See: https://docs.gitlab.com/ee/user/project/merge_requests/reviews/suggestions.html
M.create_comment_suggestion = function()
--- This function will create a new tab with a suggestion preview for the changed/updated line in
--- the current MR.
M.create_comment_with_suggestion = function()
M.location = Location.new()
if not M.can_create_comment(true) then
u.press_escape()
return
end

local suggestion_lines = build_suggestion()

local layout = M.create_comment_layout({ unlinked = false })
layout:mount()

vim.schedule(function()
if suggestion_lines then
vim.api.nvim_buf_set_lines(M.comment_popup.bufnr, 0, -1, false, suggestion_lines)
end
end)
local old_file_name = M.location.reviewer_data.old_file_name ~= "" and M.location.reviewer_data.old_file_name
or M.location.reviewer_data.file_name
local is_new_sha = M.location.reviewer_data.new_sha_focused

---@type ShowPreviewOpts
local opts = {
old_file_name = old_file_name,
new_file_name = M.location.reviewer_data.file_name,
start_line = M.location.visual_range.start_line,
end_line = M.location.visual_range.end_line,
is_new_sha = is_new_sha,
revision = is_new_sha and "HEAD" or require("gitlab.state").INFO.target_branch,
note_header = "comment",
comment_type = "new",
}
require("gitlab.actions.suggestions").show_preview(opts)
end

---Returns true if it's possible to create an Inline Comment
Expand Down Expand Up @@ -353,7 +341,7 @@ M.can_create_comment = function(must_be_visual)
return false
end

-- Check we're in visual mode for code suggestions and multiline comments
-- Check we're in visual mode for code suggestions
if must_be_visual and not u.check_visual_mode() then
return false
end
Expand Down
Loading
Loading