feat!: Implements default keybindings for all actions.

This is a breaking change to the way the plugin is configured. If users are using the old configuration the plugin will warn them which fields have been removed in their configuration. Old keybindings can be found here: https://github.com/harrisoncramer/gitlab.nvim/pull/340#issuecomment-2282756924 (#331)

feat: Customize discussion tree chevrons (#339)
This commit is contained in:
Harrison (Harry) Cramer
2024-08-11 22:25:36 -04:00
committed by Harrison Cramer
parent 1eb1046e52
commit 9fc47bd3bc
14 changed files with 866 additions and 284 deletions

View File

@@ -122,37 +122,7 @@ For a list of all these settings please run `:h gitlab.nvim.configuring-the-plug
## Keybindings
The plugin does not set up any keybindings outside of the special buffers it creates,
you need to set them up yourself. Here's what I'm using:
```lua
local gitlab = require("gitlab")
local gitlab_server = require("gitlab.server")
vim.keymap.set("n", "glb", gitlab.choose_merge_request)
vim.keymap.set("n", "glr", gitlab.review)
vim.keymap.set("n", "gls", gitlab.summary)
vim.keymap.set("n", "glA", gitlab.approve)
vim.keymap.set("n", "glR", gitlab.revoke)
vim.keymap.set("n", "glc", gitlab.create_comment)
vim.keymap.set("v", "glc", gitlab.create_multiline_comment)
vim.keymap.set("v", "glC", gitlab.create_comment_suggestion)
vim.keymap.set("n", "glO", gitlab.create_mr)
vim.keymap.set("n", "glm", gitlab.move_to_discussion_tree_from_diagnostic)
vim.keymap.set("n", "gln", gitlab.create_note)
vim.keymap.set("n", "gld", gitlab.toggle_discussions)
vim.keymap.set("n", "glaa", gitlab.add_assignee)
vim.keymap.set("n", "glad", gitlab.delete_assignee)
vim.keymap.set("n", "glla", gitlab.add_label)
vim.keymap.set("n", "glld", gitlab.delete_label)
vim.keymap.set("n", "glra", gitlab.add_reviewer)
vim.keymap.set("n", "glrd", gitlab.delete_reviewer)
vim.keymap.set("n", "glp", gitlab.pipeline)
vim.keymap.set("n", "glo", gitlab.open_in_browser)
vim.keymap.set("n", "glM", gitlab.merge)
vim.keymap.set("n", "glu", gitlab.copy_mr_url)
vim.keymap.set("n", "glP", gitlab.publish_all_drafts)
vim.keymap.set("n", "glD", gitlab.toggle_draft_mode)
```
The plugin sets up a number of useful keybindings in the special buffers it creates, and some global keybindings as well. Refer to the relevant section of the manual `:h gitlab.nvim.keybindings` for more details.
For more information about each of these commands, and about the APIs in general, run `:h gitlab.nvim.api`

View File

@@ -2,22 +2,29 @@ if filereadable($VIMRUNTIME . '/syntax/markdown.vim')
source $VIMRUNTIME/syntax/markdown.vim
endif
syntax match Username "\%([]\)\@<= @\S*"
syntax match Mention "\%([] \)\@<!@\S*"
syntax match Date "\v\d+\s+\w+\s+ago"
syntax match ChevronDown ""
syntax match ChevronRight ""
syntax match Resolved /\s✓\s\?/
syntax match Unresolved /\s-\s\?/
syntax match Pencil //
highlight link Username GitlabUsername
highlight link Mention GitlabMention
highlight link Date GitlabDate
highlight link ChevronDown GitlabChevron
highlight link ChevronRight GitlabChevron
highlight link Resolved GitlabResolved
highlight link Unresolved GitlabUnresolved
highlight link Pencil GitlabDraft
let b:current_syntax = "gitlab"
execute 'syntax match Unresolved /\s' . g:gitlab_discussion_tree_unresolved . '\s\?/'
highlight link Unresolved GitlabUnresolved
execute 'syntax match Resolved /\s' . g:gitlab_discussion_tree_resolved . '\s\?/'
highlight link Resolved GitlabResolved
execute 'syntax match GitlabDiscussionOpen /^\s*' . g:gitlab_discussion_tree_expander_open . '/'
highlight link GitlabDiscussionOpen GitlabExpander
execute 'syntax match GitlabDiscussionClosed /^\s*' . g:gitlab_discussion_tree_expander_closed . '/'
highlight link GitlabDiscussionClosed GitlabExpander
execute 'syntax match Draft /' . g:gitlab_discussion_tree_draft . '/'
highlight link Draft GitlabDraft
execute 'syntax match Username "@[a-zA-Z0-9.]\+"'
highlight link Username GitlabUsername
execute 'syntax match Mention "\%(' . g:gitlab_discussion_tree_expander_open . '\|'
\ . g:gitlab_discussion_tree_expander_closed . '\)\@<!@[a-zA-Z0-9.]*"'
highlight link Mention GitlabMention
let b:current_syntax = 'gitlab'

View File

@@ -166,14 +166,71 @@ you call this function with no values the defaults will be used:
connection_settings = {
insecure = false, -- Like curl's --insecure option, ignore bad x509 certificates on connection
},
help = "g?", -- Opens a help popup for local keymaps when a relevant view is focused (popup, discussion panel, etc)
popup = { -- The popup for comment creation, editing, and replying
keymaps = {
keymaps = {
disable_all = false, -- Disable all mappings created by the plugin
help = "g?", -- Open a help popup for local keymaps when a relevant view is focused (popup, discussion panel, etc)
global = {
disable_all = false, -- Disable all global mappings created by the plugin
add_assignee = "glaa",
delete_assignee = "glad",
add_label = "glla",
delete_label = "glld",
add_reviewer = "glra",
delete_reviewer = "glrd",
approve = "glA", -- Approve MR
revoke = "glR", -- Revoke MR approval
merge = "glM", -- Merge the feature branch to the target branch and close MR
create_mr = "glC", -- Create a new MR for currently checked-out feature branch
choose_merge_request = "glc", -- Chose MR for review (if necessary check out the feature branch)
start_review = "glS", -- Start review for the currently checked-out branch
summary = "gls", -- Show the editable summary of the MR
copy_mr_url = "glu", -- Copy the URL of the MR to the system clipboard
open_in_browser = "glo", -- Openthe URL of the MR in the default Internet browser
create_note = "gln", -- Create a note (comment not linked to a specific line)
pipeline = "glp", -- Show the pipeline status
toggle_discussions = "gld", -- Toggle the discussions window
toggle_draft_mode = "glD", -- Toggle between draft mode (comments posted as drafts) and live mode (comments are posted immediately)
publish_all_drafts = "glP", -- Publish all draft comments/notes
},
popup = {
disable_all = false, -- Disable all default mappings for the popup windows (comments, summary, MR creation, etc.)
next_field = "<Tab>", -- Cycle to the next field. Accepts |count|.
prev_field = "<S-Tab>", -- Cycle to the previous field. Accepts |count|.
perform_action = "ZZ", -- Once in normal mode, does action (like saving comment or applying description edit, etc)
perform_linewise_action = "ZA", -- Once in normal mode, does the linewise action (see logs for this job, etc)
discard_changes = "ZQ", -- Quit the popup discarding changes, the popup content is not saved to the `temp_registers` (see `:h gitlab.nvim.temp-registers`)
},
perform_action = "<leader>s", -- Once in normal mode, does action (like saving comment or editing description, etc)
perform_linewise_action = "<leader>l", -- Once in normal mode, does the linewise action (see logs for this job, etc)
discussion_tree = {
disable_all = false, -- Disable all default mappings for the discussion tree window
add_emoji = "Ea", -- Add an emoji to the note/comment
delete_emoji = "Ed", -- Remove an emoji from a note/comment
delete_comment = "dd", -- Delete comment
edit_comment = "e", -- Edit comment
reply = "r", -- Reply to comment
toggle_resolved = "-", -- Toggle the resolved status of the whole discussion
jump_to_file = "o", -- Jump to comment location in file
jump_to_reviewer = "a", -- Jump to the comment location in the reviewer window
open_in_browser = "b", -- Jump to the URL of the current note/discussion
copy_node_url = "u", -- Copy the URL of the current node to clipboard
switch_view = "c", -- Toggle between the notes and discussions views
toggle_tree_type = "i", -- Toggle type of discussion tree - "simple", or "by_file_name"
publish_draft = "P", -- Publish the currently focused note/comment
toggle_draft_mode = "D", -- Toggle between draft mode (comments posted as drafts) and live mode (comments are posted immediately)
toggle_node = "t", -- Open or close the discussion
toggle_all_discussions = "T", -- Open or close separately both resolved and unresolved discussions
toggle_resolved_discussions = "R", -- Open or close all resolved discussions
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)
},
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
move_to_discussion_tree = "a", -- Jump to the comment in the discussion tree
},
},
popup = { -- The popup for comment creation, editing, and replying
width = "40%",
height = "60%",
border = "rounded", -- One of "rounded", "single", "double", "solid"
@@ -187,36 +244,22 @@ you call this function with no values the defaults will be used:
temp_registers = {}, -- List of registers for backing up popup content (see `:h gitlab.nvim.temp-registers`)
},
discussion_tree = { -- The discussion tree that holds all comments
expanders = { -- Discussion tree icons
expanded = " ", -- Icon for expanded discussion thread
collapsed = " ", -- Icon for collapsed discussion thread
indentation = " ", -- Indentation Icon
},
auto_open = true, -- Automatically open when the reviewer is opened
switch_view = "S", -- Toggles between the notes and discussions views
default_view = "discussions" -- Show "discussions" or "notes" by default
blacklist = {}, -- List of usernames to remove from tree (bots, CI, etc)
jump_to_file = "o", -- Jump to comment location in file
jump_to_reviewer = "m", -- Jump to the location in the reviewer window
edit_comment = "e", -- Edit comment
delete_comment = "dd", -- Delete comment
refresh_data = "a", -- Refreshes the data in the view by hitting Gitlab's APIs again
reply = "r", -- Reply to comment
toggle_node = "t", -- Opens or closes the discussion
add_emoji = "Ea" -- Add an emoji to the note/comment
delete_emoji = "Ed" -- Remove an emoji from a note/comment
toggle_all_discussions = "T", -- Open or close separately both resolved and unresolved discussions
toggle_resolved_discussions = "R", -- Open or close all resolved discussions
toggle_unresolved_discussions = "U", -- Open or close all unresolved discussions
keep_current_open = false, -- If true, current discussion stays open even if it should otherwise be closed when toggling
publish_draft = "P", -- Publishes the currently focused note/comment
toggle_resolved = "p" -- Toggles the resolved status of the whole discussion
position = "left", -- "top", "right", "bottom" or "left"
open_in_browser = "b" -- Jump to the URL of the current note/discussion
copy_node_url = "u", -- Copy the URL of the current node to clipboard
size = "20%", -- Size of split
relative = "editor", -- Position of tree split relative to "editor" or "window"
resolved = '✓', -- Symbol to show next to resolved discussions
unresolved = '-', -- Symbol to show next to unresolved discussions
tree_type = "simple", -- Type of discussion tree - "simple" means just list of discussions, "by_file_name" means file tree with discussions under file
toggle_tree_type = "i", -- Toggle type of discussion tree - "simple", or "by_file_name"
draft_mode = false, -- Whether comments are posted as drafts as part of a review
toggle_draft_mode = "D" -- Toggle between draft mode (comments posted as drafts) and live mode (comments are posted immediately)
winbar = nil -- Custom function to return winbar title, should return a string. Provided with WinbarTable (defined in annotations.lua)
-- If using lualine, please add "gitlab" to disabled file types, otherwise you will not see the winbar.
},
@@ -285,7 +328,7 @@ you call this function with no values the defaults will be used:
username = "Keyword",
mention = "WarningMsg",
date = "Comment",
chevron = "DiffviewNonText",
expander = "DiffviewNonText",
directory = "Directory",
directory_icon = "DiffviewFolderSign",
file_name = "Normal",
@@ -314,7 +357,7 @@ The `summary` action will open the MR title and description:
require("gitlab").summary()
<
After editing the description or title, you may save your changes via the
`settings.popup.perform_action` keybinding.
`keymaps.popup.perform_action` keybinding.
By default this plugin will also show additional metadata about the MR in a
separate pane underneath the description. This can be disabled, and these
@@ -338,20 +381,20 @@ 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 Gitlabs 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
`settings.popup.perform_action` keybinding.
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.
DRAFT NOTES *gitlab.nvim.draft-comments*
When you publish a "draft" of any of the above resources, the comment will be
added to a review. You can configure the default commenting mode (draft vs
live) via the `state.settings.discussion_tree.draft_mode` setting, and you can
toggle the setting with the `state.settings.discussion_tree.toggle_draft_mode`
toggle the setting with the `keymaps.discussion_tree.toggle_draft_mode`
keybinding, or by calling the `gitlab.toggle_draft_mode()` function. You may
publish all draft comments via the `gitlab.publish_all_drafts()` function, and
you can publish an individual comment or note by pressing the
`state.settings.discussion_tree.publish_draft` keybinding.
`keymaps.discussion_tree.publish_draft` keybinding.
Draft notes do not support replying or emojis.
@@ -372,9 +415,13 @@ else. Using the clipboard register lets you easily use the text outside of
nvim.
NOTE: The `temp_registers` are also filled with the contents of the popup when
pressing the `settings.popup.perform_action` keybinding, even if the action
pressing the `keymaps.popup.perform_action` keybinding, even if the action
that was supposed to be performed fails.
If you don't want the popup contents to be saved to the `temp_registers`, quit
the popup using the `keymaps.pupup.discard_changes` keybinding, which is `ZQ`
by default (compare the builtin |ZQ| command).
DISCUSSIONS AND NOTES *gitlab.nvim.discussions-and-notes*
Gitlab groups threads of comments together into "discussions."
@@ -386,11 +433,11 @@ action, which will show the discussions in a split window:
<
You can jump to the comments location in the reviewer window by using the
`state.settings.discussion_tree.jump_to_reviewer` key, or to the actual file
with the `state.settings.discussion_tree.jump_to_file` key.
`keymaps.discussion_tree.jump_to_reviewer` keybinding, or to the actual file
with the `keymaps.discussion_tree.jump_to_file` keybinding.
Within the discussion tree, you can delete/edit/reply to comments with the
`state.settings.discussion_tree.SOME_ACTION` keybindings.
`keymaps.discussion_tree.SOME_ACTION` keybindings.
If youd like to create a note in an MR (like a comment, but not linked to a
specific line) use the `create_note` action. The same keybindings for
@@ -466,14 +513,14 @@ 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
`settings.popup.perform_linewise_action` keybinding when the popup is open.
`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).
When you have picked the file, it will be added to the current buffer at the
current line.
Use the `settings.popup.perform_action` to send the changes to Gitlab.
Use the `keymaps.popup.perform_action` to send the changes to Gitlab.
MR APPROVALS *gitlab.nvim.mr-approvals*
@@ -515,8 +562,8 @@ action.
require("gitlab").pipeline()
<
To re-trigger failed jobs in the pipeline manually, use the
`settings.popup.perform_action` keybinding. To open the log trace of a job in a
new Neovim buffer, use your `settings.popup.perform_linewise_action`
`keymaps.popup.perform_action` keybinding. To open the log trace of a job in a
new Neovim buffer, use your `keymaps.popup.perform_linewise_action`
keybinding.
@@ -565,34 +612,75 @@ reviewer when checking out a new branch:
KEYBINDINGS *gitlab.nvim.keybindings*
The plugin does not set up any keybindings outside of the special buffers it
creates, you need to set them up yourself. Heres what Im using (note that
the `<leader>` prefix is not necessary, as `gl` does not have a special meaning
in normal mode):
The `gitlab.nvim` plugin sets up a number of default keybindings for the
discussion tree, the popup windows and the reviewer windows, and also some
global keybindings that are available in any buffer. You can find the defaults
in the `keymaps` section of the configuration table (see
|gitlab.nvim.configuring-the-plugin|) and you can see the current buffer-local
mappings by pressing the `keymaps.help` keybinding (`g?` by default). The
`help` mapping is not set in the reviewer windows which are managed by the
Diffview plugin, see |diffview-config-keymaps|.
You can set any of the mappings to whatever you want. You can also prevent the
plugin from setting up any keybindings whatsoever, or any keybindings for
individual buffers by setting `keymaps.disable_all`,
`keymaps.global.disable_all`, `keymaps.popup.disable_all`, etc. to `true`.
Alternatively, you can disable individual keybindings by setting the value of
the field to `false`, e.g., `keymaps = {global {merge = false}}`, which will
leave all the other keybindings in place.
The global keymaps all use the `gl` prefix as it does not have a special
meaning in normal mode. You can add your own global keybindings by calling
something like this after the `gitlab.setup()` call:
>lua
local gitlab = require("gitlab")
local gitlab_server = require("gitlab.server")
vim.keymap.set("n", "glr", gitlab.review)
vim.keymap.set("n", "gls", gitlab.summary)
vim.keymap.set("n", "glA", gitlab.approve)
vim.keymap.set("n", "glR", gitlab.revoke)
vim.keymap.set("n", "glc", gitlab.create_comment)
vim.keymap.set("v", "glc", gitlab.create_multiline_comment)
vim.keymap.set("v", "glC", gitlab.create_comment_suggestion)
vim.keymap.set("n", "glO", gitlab.create_mr)
vim.keymap.set("n", "glm", gitlab.move_to_discussion_tree_from_diagnostic)
vim.keymap.set("n", "gln", gitlab.create_note)
vim.keymap.set("n", "gld", gitlab.toggle_discussions)
vim.keymap.set("n", "glaa", gitlab.add_assignee)
vim.keymap.set("n", "glad", gitlab.delete_assignee)
vim.keymap.set("n", "glra", gitlab.add_reviewer)
vim.keymap.set("n", "glrd", gitlab.delete_reviewer)
vim.keymap.set("n", "glp", gitlab.pipeline)
vim.keymap.set("n", "glo", gitlab.open_in_browser)
vim.keymap.set("n", "glM", gitlab.merge)
vim.keymap.set("n", "glu", gitlab.copy_mr_url)
vim.keymap.set("n", "glP", gitlab.publish_all_drafts)
vim.keymap.set("n", "glD", gitlab.toggle_draft_mode)
vim.keymap.set("n", "gl<c-s>", gitlab.print_settings, { desc = "Print gitlab.nvim settings"})
<
See |gitlab.nvim.api| for an overview of available API functions that you can
use in your mappings.
If you want to set up your own additional keybindings for the discussion tree,
you can put them in the `$XDG_CONFIG_HOME/nvim/after/ftplugin/gitlab.lua`
file. E.g., if you wanted to use the `j` and `k` keys to move to the next
discussion node instead of the next line, you could add to the |ftplugin| file
the following lines:
>lua
vim.keymap.set("n", "j", [[<Cmd>call search('[] @')<CR>]], { buffer = 0, desc = "Go to next node" })
vim.keymap.set("n", "k", [[<Cmd>call search('[] @', 'b')<CR>]], { buffer = 0, desc = "Go to previous node" })
<
Reviewer keybindings ~
Most of the keybindings `gitlab.nvim` sets are normal mode mappings, with the
exception of `keymaps.reviewer.create_comment` and
`keymaps.reviewer.create_suggestion` which work in both normal and visual
mode. In normal mode, these keybindings are |operator|s that accept a |motion|
(with an optional |count|). E.g., `c2j` will create a comment for the current
and the next 2 lines. Similarly, `sip` will create a suggestion for the "inner
paragraph". The operator forces |linewise| visual selection, so it works
correctly even if the motion itself works |characterwise| (e.g., |i(| for
selecting the inner parentheses block).
The keybindings also work in visual mode, e.g., if you first want to make
sure you are commenting on the right text segment/object, you can do `v4j` to
visually select the current and the next 4 lines, followed by either `c` for a
normal comment or `s` for a suggestion.
To create a comment or suggestion for the current line, just duplicate the
keybinding: `cc` and `ss`. Alternatively, you can use any motion that moves on
that line only, e.g., `c$`. The same logic applies also when you change these
keybindings, e.g., to something like `<leader>c`.
Delay in keybindings ~
You may experience a lag in some of the keybindings, because you have existing
keybinding starting with they same key(s). You can force the `gitlab.nvim`
mapping to use |nowait| and fire immediately (and lose your other mapping for
this buffer) by adding a special field called `nowait` to your keymap. For example,
if the name of the keybinding is `reviewer.create_comment`, then you add the
following to your config:
>lua
keymaps = { reviewer = { create_comment_nowait = true }}
<
TROUBLESHOOTING *gitlab.nvim.troubleshooting*
@@ -668,7 +756,7 @@ in the setup call.
require("gitlab").summary()
The summary can be edited. Once you have made changes, send them to Gitlab via
the `settings.popup.perform_action` keybinding.
the `keymaps.popup.perform_action` keybinding.
*gitlab.nvim.approve*
gitlab.approve() ~
@@ -694,8 +782,8 @@ reviewer pane (see the gitlab.nvim.review command), otherwise it will error.
>lua
require("gitlab").create_comment()
After the comment is typed, submit it to Gitlab via the `settings.popup.perform_action`
keybinding, by default `<leader>l`.
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() ~
@@ -705,8 +793,8 @@ 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 |settings.popup.perform_linewise_action|
keybinding, by default `<leader>l`.
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() ~
@@ -716,8 +804,8 @@ change suggestion to the currently selected lines).
>lua
require("gitlab").create_multiline_comment()
After the comment is typed, submit it to Gitlab via the |settings.popup.perform_linewise_action|
keybinding, by default |<leader>l|
After the comment is typed, submit it to Gitlab via the
`keymaps.popup.perform_linewise_action` keybinding, by default `ZA`.
*gitlab.nvim.create_mr*
gitlab.create_mr({opts}) ~
@@ -751,12 +839,12 @@ Starts the process of creating an MR for the currently checked out branch.
After selecting all necessary details, you'll be presented with a confirmation
window. You can cycle through the individual fields with the keymaps defined
in `settings.popup.keymaps.next_field` and `settings.popup.keymaps.prev_field`.
Both keymaps accept a count, i.g., 2<Tab> goes to the 2nd next field.
In the "Delete source branch", "Squash commits", and "Target branch" fields,
you can use the `settings.popup.perform_linewise_action` keymap to either
toggle the Boolean value or to select a new target branch, respectively.
Use the `settings.popup.perform_action` keymap to POST the MR to Gitlab.
in `keymaps.popup.next_field` and `keymaps.popup.prev_field`. Both keymaps
accept a count, i.g., 2<Tab> goes to the 2nd next field. In the "Delete source
branch", "Squash commits", and "Target branch" fields, you can use the
`keymaps.popup.perform_linewise_action` keymap to either toggle the Boolean
value or to select a new target branch, respectively. Use the
`keymaps.popup.perform_action` keymap to POST the MR to Gitlab.
*gitlab.nvim.move_to_discussion_tree_from_diagnostic*
gitlab.move_to_discussion_tree_from_diagnostic() ~
@@ -776,8 +864,8 @@ tied to specific changes in an MR.
>lua
require("gitlab").create_note()
After the comment is typed, submit it to Gitlab via the `settings.popup.perform_action`
keybinding, by default |<leader>s|.
After the comment is typed, submit it to Gitlab via the
`keymaps.popup.perform_action` keybinding, by default `ZZ`.
*gitlab.nvim.toggle_discussions*
gitlab.toggle_discussions() ~
@@ -786,15 +874,16 @@ Toggles visibility of the discussion tree.
>lua
require("gitlab").toggle_discussions()
Once the discussion tree is open, a number of different keybindings are available
for interacting with different discussions. Please see the `settings.discussion_tree`
section of the setup call for more information about different keybindings.
Once the discussion tree is open, a number of different keybindings are
available for interacting with different discussions. Please see the
`keymaps.discussion_tree` section of the setup call for more information about
different keybindings.
*gitlab.nvim.publish_all_drafts*
gitlab.publish_all_drafts() ~
Publishes all unpublished draft notes. Used to finish a review and make all notes and
comments visible.
Publishes all unpublished draft notes. Used to finish a review and make all
notes and comments visible.
>lua
require("gitlab").publish_all_drafts()
<
@@ -853,8 +942,9 @@ Opens up a popup with information about the pipeline for the current merge reque
>lua
require("gitlab").pipeline()
<
To re-trigger failed jobs in the pipeline manually, use the `settings.popup.perform_action` keybinding.
To open the log trace of a job in a new Neovim buffer, use your `settings.popup.perform_linewise_action`
To re-trigger failed jobs in the pipeline manually, use the
`keymaps.popup.perform_action` keybinding. To open the log trace of a job in a
new Neovim buffer, use your `keymaps.popup.perform_linewise_action`
keybinding.
*gitlab.nvim.open_in_browser*
@@ -891,8 +981,8 @@ Gitlab online. You can see the current settings in the Summary view, see
• {squash}: (bool) If true, the commits will be squashed. If
you enable {squash} you will be prompted for a squash
message. To use the default message, leave the popup empty.
Use the `settings.popup.perform_action` to merge the MR with
your message.
Use the `keymaps.popup.perform_action` to merge the MR
with your message.
*gitlab.nvim.data*
gitlab.data({resources}, {cb}) ~

View File

@@ -22,7 +22,7 @@ local M = {
}
---Fires the API that sends the comment data to the Go server, called when you "confirm" creation
---via the M.settings.popup.perform_action keybinding
---via the M.settings.keymaps.popup.perform_action keybinding
---@param text string comment text
---@param visual_range LineRange | nil range of visual selection or nil
---@param unlinked boolean if true, the comment is not linked to a line

View File

@@ -263,7 +263,7 @@ M.get_line_number_from_node = function(root_node)
end
end
-- This function (settings.discussion_tree.jump_to_reviewer) will jump the cursor to the reviewer's location associated with the note. The implementation depends on the reviewer
-- This function (settings.keymaps.discussion_tree.jump_to_reviewer) will jump the cursor to the reviewer's location associated with the note. The implementation depends on the reviewer
M.jump_to_reviewer = function(tree, callback)
local node = tree:get_node()
local root_node = M.get_root_node(tree, node)
@@ -280,7 +280,7 @@ M.jump_to_reviewer = function(tree, callback)
callback()
end
-- This function (settings.discussion_tree.jump_to_file) will jump to the file changed in a new tab
-- This function (settings.keymaps.discussion_tree.jump_to_file) will jump to the file changed in a new tab
M.jump_to_file = function(tree)
local node = tree:get_node()
local root_node = M.get_root_node(tree, node)

View File

@@ -74,6 +74,7 @@ M.initialize_discussions = function()
reviewer.set_callback_for_file_changed(function()
M.refresh_diagnostics_and_winbar()
M.modifiable(false)
reviewer.set_reviewer_keymaps()
end)
reviewer.set_callback_for_reviewer_enter(function()
M.modifiable(false)
@@ -82,6 +83,7 @@ M.initialize_discussions = function()
signs.clear_signs()
diagnostics.clear_diagnostics()
M.modifiable(true)
reviewer.del_reviewer_keymaps()
end)
end
@@ -219,7 +221,7 @@ M.move_to_discussion_tree = function()
end
end
-- The reply popup will mount in a window when you trigger it (settings.discussion_tree.reply) when hovering over a node in the discussion tree.
-- The reply popup will mount in a window when you trigger it (settings.keymaps.discussion_tree.reply) when hovering over a node in the discussion tree.
M.reply = function(tree)
if M.is_draft_note(tree) then
u.notify("Gitlab does not support replying to draft notes", vim.log.levels.WARN)
@@ -241,7 +243,7 @@ M.reply = function(tree)
layout:mount()
end
-- This function (settings.discussion_tree.delete_comment) will trigger a popup prompting you to delete the current comment
-- This function (settings.keymaps.discussion_tree.delete_comment) will trigger a popup prompting you to delete the current comment
M.delete_comment = function(tree, unlinked)
vim.ui.select({ "Confirm", "Cancel" }, {
prompt = "Delete comment?",
@@ -267,7 +269,7 @@ M.delete_comment = function(tree, unlinked)
end)
end
-- This function (settings.discussion_tree.edit_comment) will open the edit popup for the current comment in the discussion tree
-- This function (settings.keymaps.discussion_tree.edit_comment) will open the edit popup for the current comment in the discussion tree
M.edit_comment = function(tree, unlinked)
local edit_popup = Popup(u.create_popup_state("Edit Comment", state.settings.popup.edit))
local current_node = tree:get_node()
@@ -312,7 +314,7 @@ M.edit_comment = function(tree, unlinked)
end
end
-- This function (settings.discussion_tree.toggle_discussion_resolved) will toggle the resolved status of the current discussion and send the change to the Go server
-- This function (settings.keymaps.discussion_tree.toggle_discussion_resolved) will toggle the resolved status of the current discussion and send the change to the Go server
M.toggle_discussion_resolved = function(tree)
local note = tree:get_node()
if note == nil then
@@ -527,101 +529,215 @@ M.is_current_node_note = function(tree)
end
M.set_tree_keymaps = function(tree, bufnr, unlinked)
---Keybindings only relevant for linked (comment) view
if not unlinked then
vim.keymap.set("n", state.settings.discussion_tree.jump_to_file, function()
if M.is_current_node_note(tree) then
common.jump_to_file(tree)
end
end, { buffer = bufnr, desc = "Jump to file" })
vim.keymap.set("n", state.settings.discussion_tree.jump_to_reviewer, function()
if M.is_current_node_note(tree) then
common.jump_to_reviewer(tree, M.refresh_diagnostics_and_winbar)
end
end, { buffer = bufnr, desc = "Jump to reviewer" })
vim.keymap.set("n", state.settings.discussion_tree.toggle_tree_type, function()
M.toggle_tree_type()
end, { buffer = bufnr, desc = "Toggle tree type between `simple` and `by_file_name`" })
-- Require keymaps only after user settings have been merged with defaults
local keymaps = require("gitlab.state").settings.keymaps
if keymaps.disable_all or keymaps.discussion_tree.disable_all then
return
end
vim.keymap.set("n", state.settings.discussion_tree.refresh_data, function()
u.notify("Refreshing data...", vim.log.levels.INFO)
draft_notes.rebuild_view(unlinked, false)
end, { buffer = bufnr, desc = "Refreshes the view with Gitlab's APIs" })
---Keybindings only relevant for linked (comment) view
if not unlinked then
if keymaps.discussion_tree.jump_to_file then
vim.keymap.set("n", keymaps.discussion_tree.jump_to_file, function()
if M.is_current_node_note(tree) then
common.jump_to_file(tree)
end
end, { buffer = bufnr, desc = "Jump to file", nowait = keymaps.discussion_tree.jump_to_file_nowait })
end
vim.keymap.set("n", state.settings.discussion_tree.edit_comment, function()
if M.is_current_node_note(tree) then
M.edit_comment(tree, unlinked)
if keymaps.discussion_tree.jump_to_reviewer then
vim.keymap.set("n", keymaps.discussion_tree.jump_to_reviewer, function()
if M.is_current_node_note(tree) then
common.jump_to_reviewer(tree, M.refresh_diagnostics_and_winbar)
end
end, { buffer = bufnr, desc = "Jump to reviewer", nowait = keymaps.discussion_tree.jump_to_reviewer_nowait })
end
end, { buffer = bufnr, desc = "Edit comment" })
vim.keymap.set("n", state.settings.discussion_tree.publish_draft, function()
if M.is_draft_note(tree) then
draft_notes.publish_draft(tree)
if keymaps.discussion_tree.toggle_tree_type then
vim.keymap.set("n", keymaps.discussion_tree.toggle_tree_type, function()
M.toggle_tree_type()
end, {
buffer = bufnr,
desc = "Change tree type between `simple` and `by_file_name`",
nowait = keymaps.discussion_tree.toggle_tree_type_nowait,
})
end
end, { buffer = bufnr, desc = "Publish draft" })
vim.keymap.set("n", state.settings.discussion_tree.delete_comment, function()
if M.is_current_node_note(tree) then
M.delete_comment(tree, unlinked)
end
end, { buffer = bufnr, desc = "Delete comment" })
vim.keymap.set("n", state.settings.discussion_tree.toggle_draft_mode, function()
M.toggle_draft_mode()
end, { buffer = bufnr, desc = "Toggle between draft mode and live mode" })
vim.keymap.set("n", state.settings.discussion_tree.toggle_resolved, function()
if M.is_current_node_note(tree) and not M.is_draft_note(tree) then
M.toggle_discussion_resolved(tree)
end
end, { buffer = bufnr, desc = "Toggle resolved" })
vim.keymap.set("n", state.settings.discussion_tree.toggle_node, function()
tree_utils.toggle_node(tree)
end, { buffer = bufnr, desc = "Toggle node" })
vim.keymap.set("n", state.settings.discussion_tree.toggle_all_discussions, function()
tree_utils.toggle_nodes(M.split.winid, tree, unlinked, {
toggle_resolved = true,
toggle_unresolved = true,
keep_current_open = state.settings.discussion_tree.keep_current_open,
end
if keymaps.discussion_tree.refresh_data then
vim.keymap.set("n", keymaps.discussion_tree.refresh_data, function()
u.notify("Refreshing data...", vim.log.levels.INFO)
draft_notes.rebuild_view(unlinked, false)
end, {
buffer = bufnr,
desc = "Refresh the view with Gitlab's APIs",
nowait = keymaps.discussion_tree.refresh_data_nowait,
})
end, { buffer = bufnr, desc = "Toggle all nodes" })
vim.keymap.set("n", state.settings.discussion_tree.toggle_resolved_discussions, function()
tree_utils.toggle_nodes(M.split.winid, tree, unlinked, {
toggle_resolved = true,
toggle_unresolved = false,
keep_current_open = state.settings.discussion_tree.keep_current_open,
end
if keymaps.discussion_tree.edit_comment then
vim.keymap.set("n", keymaps.discussion_tree.edit_comment, function()
if M.is_current_node_note(tree) then
M.edit_comment(tree, unlinked)
end
end, { buffer = bufnr, desc = "Edit comment", nowait = keymaps.discussion_tree.edit_comment_nowait })
end
if keymaps.discussion_tree.publish_draft then
vim.keymap.set("n", keymaps.discussion_tree.publish_draft, function()
if M.is_draft_note(tree) then
draft_notes.publish_draft(tree)
end
end, { buffer = bufnr, desc = "Publish draft", nowait = keymaps.discussion_tree.publish_draft_nowait })
end
if keymaps.discussion_tree.delete_comment then
vim.keymap.set("n", keymaps.discussion_tree.delete_comment, function()
if M.is_current_node_note(tree) then
M.delete_comment(tree, unlinked)
end
end, { buffer = bufnr, desc = "Delete comment", nowait = keymaps.discussion_tree.delete_comment_nowait })
end
if keymaps.discussion_tree.toggle_draft_mode then
vim.keymap.set("n", keymaps.discussion_tree.toggle_draft_mode, function()
M.toggle_draft_mode()
end, {
buffer = bufnr,
desc = "Toggle between draft mode and live mode",
nowait = keymaps.discussion_tree.toggle_draft_mode_nowait,
})
end, { buffer = bufnr, desc = "Toggle resolved nodes" })
vim.keymap.set("n", state.settings.discussion_tree.toggle_unresolved_discussions, function()
tree_utils.toggle_nodes(M.split.winid, tree, unlinked, {
toggle_resolved = false,
toggle_unresolved = true,
keep_current_open = state.settings.discussion_tree.keep_current_open,
end
if keymaps.discussion_tree.toggle_resolved then
vim.keymap.set("n", keymaps.discussion_tree.toggle_resolved, function()
if M.is_current_node_note(tree) and not M.is_draft_note(tree) then
M.toggle_discussion_resolved(tree)
end
end, { buffer = bufnr, desc = "Toggle resolved", nowait = keymaps.discussion_tree.toggle_resolved_nowait })
end
if keymaps.discussion_tree.toggle_node then
vim.keymap.set("n", keymaps.discussion_tree.toggle_node, function()
tree_utils.toggle_node(tree)
end, { buffer = bufnr, desc = "Toggle node", nowait = keymaps.discussion_tree.toggle_node_nowait })
end
if keymaps.discussion_tree.toggle_all_discussions then
vim.keymap.set("n", keymaps.discussion_tree.toggle_all_discussions, function()
tree_utils.toggle_nodes(M.split.winid, tree, unlinked, {
toggle_resolved = true,
toggle_unresolved = true,
keep_current_open = state.settings.discussion_tree.keep_current_open,
})
end, {
buffer = bufnr,
desc = "Toggle all nodes",
nowait = keymaps.discussion_tree.toggle_all_discussions_nowait,
})
end, { buffer = bufnr, desc = "Toggle unresolved nodes" })
vim.keymap.set("n", state.settings.discussion_tree.reply, function()
if M.is_current_node_note(tree) then
M.reply(tree)
end
end, { buffer = bufnr, desc = "Reply" })
vim.keymap.set("n", state.settings.discussion_tree.switch_view, function()
winbar.switch_view_type()
end, { buffer = bufnr, desc = "Switch view type" })
vim.keymap.set("n", state.settings.help, function()
help.open()
end, { buffer = bufnr, desc = "Open help popup" })
vim.keymap.set("n", state.settings.discussion_tree.open_in_browser, function()
common.open_in_browser(tree)
end, { buffer = bufnr, desc = "Open the note in your browser" })
vim.keymap.set("n", state.settings.discussion_tree.copy_node_url, function()
common.copy_node_url(tree)
end, { buffer = bufnr, desc = "Copy the URL of the current node to clipboard" })
vim.keymap.set("n", "<leader>p", function()
common.print_node(tree)
end, { buffer = bufnr, desc = "Print current node (for debugging)" })
vim.keymap.set("n", state.settings.discussion_tree.add_emoji, function()
M.add_emoji_to_note(tree, unlinked)
end, { buffer = bufnr, desc = "Add an emoji reaction to the note/comment" })
vim.keymap.set("n", state.settings.discussion_tree.delete_emoji, function()
M.delete_emoji_from_note(tree, unlinked)
end, { buffer = bufnr, desc = "Remove an emoji reaction from the note/comment" })
end
if keymaps.discussion_tree.toggle_resolved_discussions then
vim.keymap.set("n", keymaps.discussion_tree.toggle_resolved_discussions, function()
tree_utils.toggle_nodes(M.split.winid, tree, unlinked, {
toggle_resolved = true,
toggle_unresolved = false,
keep_current_open = state.settings.discussion_tree.keep_current_open,
})
end, {
buffer = bufnr,
desc = "Toggle resolved nodes",
nowait = keymaps.discussion_tree.toggle_resolved_discussions_nowait,
})
end
if keymaps.discussion_tree.toggle_unresolved_discussions then
vim.keymap.set("n", keymaps.discussion_tree.toggle_unresolved_discussions, function()
tree_utils.toggle_nodes(M.split.winid, tree, unlinked, {
toggle_resolved = false,
toggle_unresolved = true,
keep_current_open = state.settings.discussion_tree.keep_current_open,
})
end, {
buffer = bufnr,
desc = "Toggle unresolved nodes",
nowait = keymaps.discussion_tree.toggle_unresolved_discussions_nowait,
})
end
if keymaps.discussion_tree.reply then
vim.keymap.set("n", keymaps.discussion_tree.reply, function()
if M.is_current_node_note(tree) then
M.reply(tree)
end
end, { buffer = bufnr, desc = "Reply", nowait = keymaps.discussion_tree.reply_nowait })
end
if keymaps.discussion_tree.switch_view then
vim.keymap.set("n", keymaps.discussion_tree.switch_view, function()
winbar.switch_view_type()
end, {
buffer = bufnr,
desc = "Change view type between discussions and notes",
nowait = keymaps.discussion_tree.switch_view_nowait,
})
end
if keymaps.help then
vim.keymap.set("n", keymaps.help, function()
help.open()
end, { buffer = bufnr, desc = "Open help popup", nowait = keymaps.help_nowait })
end
if keymaps.discussion_tree.open_in_browser then
vim.keymap.set("n", keymaps.discussion_tree.open_in_browser, function()
common.open_in_browser(tree)
end, {
buffer = bufnr,
desc = "Open the note in your browser",
nowait = keymaps.discussion_tree.open_in_browser_nowait,
})
end
if keymaps.discussion_tree.copy_node_url then
vim.keymap.set("n", keymaps.discussion_tree.copy_node_url, function()
common.copy_node_url(tree)
end, {
buffer = bufnr,
desc = "Copy the URL of the current node to clipboard",
nowait = keymaps.discussion_tree.copy_node_url_nowait,
})
end
if keymaps.discussion_tree.print_node then
vim.keymap.set("n", keymaps.discussion_tree.print_node, function()
common.print_node(tree)
end, {
buffer = bufnr,
desc = "Print current node (for debugging)",
nowait = keymaps.discussion_tree.print_node_nowait,
})
end
if keymaps.discussion_tree.add_emoji then
vim.keymap.set("n", keymaps.discussion_tree.add_emoji, function()
M.add_emoji_to_note(tree, unlinked)
end, {
buffer = bufnr,
desc = "Add an emoji reaction to the note/comment",
nowait = keymaps.discussion_tree.add_emoji_nowait,
})
end
if keymaps.discussion_tree.delete_emoji then
vim.keymap.set("n", keymaps.discussion_tree.delete_emoji, function()
M.delete_emoji_from_note(tree, unlinked)
end, {
buffer = bufnr,
desc = "Remove an emoji reaction from the note/comment",
nowait = keymaps.discussion_tree.delete_emoji_nowait,
})
end
emoji.init_popup(tree, bufnr)
end

View File

@@ -325,16 +325,17 @@ M.nui_tree_prepare_node = function(node)
for i, text in ipairs(texts) do
local line = NuiLine()
local expanders = state.settings.discussion_tree.expanders
line:append(string.rep(" ", node._depth - 1))
line:append(string.rep(expanders.indentation, node._depth - 1))
if i == 1 and node:has_children() then
line:append(node:is_expanded() and "" or "")
line:append(node:is_expanded() and expanders.expanded or expanders.collapsed)
if node.icon then
line:append(node.icon .. " ", node.icon_hl)
end
else
line:append(" ")
line:append(expanders.indentation)
end
line:append(text, node.text_hl)
@@ -368,7 +369,7 @@ end
---@field toggle_unresolved boolean Whether to toggle unresolved discussions.
---@field keep_current_open boolean Whether to keep the current discussion open even if it should otherwise be closed.
---This function (settings.discussion_tree.toggle_nodes) expands/collapses all nodes and their children according to the opts.
---This function expands/collapses all nodes and their children according to the opts.
---@param tree NuiTree
---@param winid integer
---@param unlinked boolean
@@ -433,7 +434,7 @@ M.restore_cursor_position = function(winid, tree, original_node, root_node)
end
end
---This function (settings.discussion_tree.expand_recursively) expands a node and its children.
---This function expands a node and its children.
---@param tree NuiTree
---@param node NuiTree.Node
---@param is_resolved boolean If true, expand resolved discussions. If false, expand unresolved discussions.
@@ -450,7 +451,7 @@ M.expand_recursively = function(tree, node, is_resolved)
end
end
---This function (settings.discussion_tree.collapse_recursively) collapses a node and its children.
---This function collapses a node and its children.
---@param tree NuiTree
---@param node NuiTree.Node
---@param current_root_node NuiTree.Node The root node of the current node.
@@ -483,7 +484,7 @@ M.open_node_by_id = function(tree, id)
end
end
-- This function (settings.discussion_tree.toggle_node) expands/collapses the current node and its children
-- This function (settings.keymaps.discussion_tree.toggle_node) expands/collapses the current node and its children
M.toggle_node = function(tree)
local node = tree:get_node()
if node == nil then

View File

@@ -61,7 +61,7 @@ local function content()
unlinked_draft_notes = #unlinked_draft_notes,
resolvable_notes = resolvable_notes,
resolved_notes = resolved_notes,
help_keymap = state.settings.help,
help_keymap = state.settings.keymaps.help,
}
return M.make_winbar(t)
@@ -130,7 +130,7 @@ M.make_winbar = function(t)
-- Join everything together and return it
local separator = "%#Comment#|"
local end_section = "%="
local help = "%#Comment#Help: " .. t.help_keymap:gsub(" ", "<space>") .. " "
local help = "%#Comment#Help: " .. (t.help_keymap and t.help_keymap:gsub(" ", "<space>") .. " " or "unmapped")
return string.format(
" %s %s %s %s %s %s %s",
discussion_title,

View File

@@ -78,14 +78,23 @@ end
---Setup keymaps for cycling popups. The keymap accepts count.
---@param popups table Table of Popups
M.set_cycle_popups_keymaps = function(popups)
local keymaps = require("gitlab.state").settings.keymaps
if keymaps.disable_all or keymaps.popup.disable_all then
return
end
local number_of_popups = #popups
for i, popup in ipairs(popups) do
popup:map("n", state.settings.popup.keymaps.next_field, function()
vim.api.nvim_set_current_win(popups[next_index(i, number_of_popups, vim.v.count)].winid)
end, { desc = "Go to next field (accepts count)" })
popup:map("n", state.settings.popup.keymaps.prev_field, function()
vim.api.nvim_set_current_win(popups[prev_index(i, number_of_popups, vim.v.count)].winid)
end, { desc = "Go to previous field (accepts count)" })
if keymaps.popup.next_field then
popup:map("n", keymaps.popup.next_field, function()
vim.api.nvim_set_current_win(popups[next_index(i, number_of_popups, vim.v.count)].winid)
end, { desc = "Go to next field (accepts count)", nowait = keymaps.popup.next_field_nowait })
end
if keymaps.popup.prev_field then
popup:map("n", keymaps.popup.prev_field, function()
vim.api.nvim_set_current_win(popups[prev_index(i, number_of_popups, vim.v.count)].winid)
end, { desc = "Go to previous field (accepts count)", nowait = keymaps.popup.prev_field_nowait })
end
end
end

View File

@@ -2,12 +2,20 @@ local state = require("gitlab.state")
local u = require("gitlab.utils")
local colors = state.settings.colors
local discussion = colors.discussion_tree
-- Set icons into global vim variables for syntax matching
local expanders = state.settings.discussion_tree.expanders
vim.g.gitlab_discussion_tree_expander_open = expanders.expanded
vim.g.gitlab_discussion_tree_expander_closed = expanders.collapsed
vim.g.gitlab_discussion_tree_draft = ""
vim.g.gitlab_discussion_tree_resolved = ""
vim.g.gitlab_discussion_tree_unresolved = "-"
local discussion = colors.discussion_tree
vim.api.nvim_set_hl(0, "GitlabUsername", u.get_colors_for_group(discussion.username))
vim.api.nvim_set_hl(0, "GitlabMention", u.get_colors_for_group(discussion.mention))
vim.api.nvim_set_hl(0, "GitlabDate", u.get_colors_for_group(discussion.date))
vim.api.nvim_set_hl(0, "GitlabChevron", u.get_colors_for_group(discussion.chevron))
vim.api.nvim_set_hl(0, "GitlabExpander", u.get_colors_for_group(discussion.expander))
vim.api.nvim_set_hl(0, "GitlabDirectory", u.get_colors_for_group(discussion.directory))
vim.api.nvim_set_hl(0, "GitlabDirectoryIcon", u.get_colors_for_group(discussion.directory_icon))
vim.api.nvim_set_hl(0, "GitlabFileName", u.get_colors_for_group(discussion.file_name))

View File

@@ -34,7 +34,8 @@ return {
args = {}
end
server.build() -- Builds the Go binary if it doesn't exist
state.merge_settings(args) -- Sets keymaps and other settings from setup function
state.merge_settings(args) -- Merges user settings with default settings
state.set_global_keymaps() -- Sets keymaps that are not bound to a specific buffer
require("gitlab.colors") -- Sets colors
reviewer.init()
discussions.initialize_discussions() -- place signs / diagnostics for discussions in reviewer

View File

@@ -276,4 +276,144 @@ M.set_callback_for_reviewer_enter = function(callback)
})
end
---Create the line-wise visual selection in the range of the motion and execute the gitlab.nvim API
---function. After that, restore the cursor position and the original operatorfunc.
---@param callback string Name of the gitlab.nvim API function to call
M.execute_callback = function(callback)
return function()
vim.api.nvim_cmd({ cmd = "normal", bang = true, args = { "'[V']" } }, {})
vim.api.nvim_cmd(
{ cmd = "lua", args = { ("require'gitlab'.%s()"):format(callback) }, mods = { lockmarks = true } },
{}
)
vim.api.nvim_win_set_cursor(M.old_winnr, M.old_cursor_position)
vim.opt.operatorfunc = M.old_opfunc
end
end
---Set the operatorfunc that will work on the lines defined by the motion that follows after the
---operator mapping, and enter the operator-pending mode.
---@param cb string Name of the gitlab.nvim API function to call, e.g., "create_multiline_comment".
local function execute_operatorfunc(cb)
M.old_opfunc = vim.opt.operatorfunc
M.old_winnr = vim.api.nvim_get_current_win()
M.old_cursor_position = vim.api.nvim_win_get_cursor(M.old_winnr)
vim.opt.operatorfunc = ("v:lua.require'gitlab.reviewer'.execute_callback'%s'"):format(cb)
vim.api.nvim_feedkeys("g@", "n", false)
end
---Set keymaps for creating comments, suggestions and for jumping to discussion tree.
---@param bufnr integer Number of the buffer for which the keybindings will be created.
---@param keymaps table The settings keymaps table.
local set_keymaps = function(bufnr, keymaps)
-- Set mappings for creating comments
if keymaps.reviewer.create_comment ~= false then
vim.keymap.set(
"o",
keymaps.reviewer.create_comment,
"$",
{ buffer = bufnr, desc = "Create comment for current line", nowait = keymaps.reviewer.create_comment_nowait }
)
vim.keymap.set(
"n",
keymaps.reviewer.create_comment,
function()
execute_operatorfunc("create_multiline_comment")
end,
{ buffer = bufnr, desc = "Create comment for range of motion", nowait = keymaps.reviewer.create_comment_nowait }
)
vim.keymap.set("v", keymaps.reviewer.create_comment, function()
require("gitlab").create_multiline_comment()
end, {
buffer = bufnr,
desc = "Create comment for selected text",
nowait = keymaps.reviewer.create_comment_nowait,
})
end
-- Set mappings for creating suggestions
if keymaps.reviewer.create_suggestion ~= false then
vim.keymap.set("o", keymaps.reviewer.create_suggestion, "$", {
buffer = bufnr,
desc = "Create suggestion for current line",
nowait = keymaps.reviewer.create_suggestion_nowait,
})
vim.keymap.set("n", keymaps.reviewer.create_suggestion, function()
execute_operatorfunc("create_comment_suggestion")
end, {
buffer = bufnr,
desc = "Create suggestion for range of motion",
nowait = keymaps.reviewer.create_suggestion_nowait,
})
vim.keymap.set("v", keymaps.reviewer.create_suggestion, function()
require("gitlab").create_comment_suggestion()
end, {
buffer = bufnr,
desc = "Create suggestion for selected text",
nowait = keymaps.reviewer.create_suggestion_nowait,
})
end
-- Set mapping for moving to discussion tree
if keymaps.reviewer.move_to_discussion_tree ~= false then
vim.keymap.set("n", keymaps.reviewer.move_to_discussion_tree, function()
require("gitlab").move_to_discussion_tree_from_diagnostic()
end, { buffer = bufnr, desc = "Move to discussion", nowait = keymaps.reviewer.move_to_discussion_tree_nowait })
end
end
--- Sets up keymaps for both buffers in the reviewer.
M.set_reviewer_keymaps = function()
-- Require keymaps only after user settings have been merged with defaults
local keymaps = require("gitlab.state").settings.keymaps
if keymaps.disable_all or keymaps.reviewer.disable_all then
return
end
local view = diffview_lib.get_current_view()
local a = view.cur_layout.a.file.bufnr
local b = view.cur_layout.b.file.bufnr
if a ~= nil and vim.api.nvim_buf_is_loaded(a) then
set_keymaps(a, keymaps)
end
if b ~= nil and vim.api.nvim_buf_is_loaded(b) then
set_keymaps(b, keymaps)
end
end
---Delete keymaps from reviewer buffers.
---@param bufnr integer Number of the buffer from which the keybindings will be removed.
---@param keymaps table The settings keymaps table.
local del_keymaps = function(bufnr, keymaps)
for _, func in ipairs({ "create_comment", "create_suggestion" }) do
if keymaps.reviewer[func] ~= false then
for _, mode in ipairs({ "n", "o", "v" }) do
pcall(vim.api.nvim_buf_del_keymap, bufnr, mode, keymaps.reviewer[func])
end
end
end
if keymaps.reviewer.move_to_discussion_tree ~= false then
pcall(vim.api.nvim_buf_del_keymap, bufnr, "n", keymaps.reviewer.move_to_discussion_tree)
end
end
--- Deletes keymaps from both buffers in the reviewer.
M.del_reviewer_keymaps = function()
-- Require keymaps only after user settings have been merged with defaults
local keymaps = require("gitlab.state").settings.keymaps
if keymaps.disable_all or keymaps.reviewer.disable_all then
return
end
local view = diffview_lib.get_current_view()
local a = view.cur_layout.a.file.bufnr
local b = view.cur_layout.b.file.bufnr
if a ~= nil and vim.api.nvim_buf_is_loaded(a) then
del_keymaps(a, keymaps)
end
if b ~= nil and vim.api.nvim_buf_is_loaded(b) then
del_keymaps(b, keymaps)
end
end
return M

View File

@@ -60,14 +60,71 @@ M.settings = {
insecure = true,
},
attachment_dir = "",
help = "g?",
popup = {
keymaps = {
keymaps = {
disable_all = false,
help = "g?",
global = {
disable_all = false,
add_assignee = "glaa",
delete_assignee = "glad",
add_label = "glla",
delete_label = "glld",
add_reviewer = "glra",
delete_reviewer = "glrd",
approve = "glA",
revoke = "glR",
merge = "glM",
create_mr = "glC",
choose_merge_request = "glc",
start_review = "glS",
summary = "gls",
copy_mr_url = "glu",
open_in_browser = "glo",
create_note = "gln",
pipeline = "glp",
toggle_discussions = "gld",
toggle_draft_mode = "glD",
publish_all_drafts = "glP",
},
popup = {
disable_all = false,
next_field = "<Tab>",
prev_field = "<S-Tab>",
perform_action = "ZZ",
perform_linewise_action = "ZA",
discard_changes = "ZQ",
},
perform_action = "<leader>s",
perform_linewise_action = "<leader>l",
discussion_tree = {
disable_all = false,
add_emoji = "Ea",
delete_emoji = "Ed",
delete_comment = "dd",
edit_comment = "e",
reply = "r",
toggle_resolved = "-",
jump_to_file = "o",
jump_to_reviewer = "a",
open_in_browser = "b",
copy_node_url = "u",
switch_view = "c",
toggle_tree_type = "i",
publish_draft = "P",
toggle_draft_mode = "D",
toggle_node = "t",
toggle_all_discussions = "T",
toggle_resolved_discussions = "R",
toggle_unresolved_discussions = "U",
refresh_data = "<C-R>",
print_node = "<leader>p",
},
reviewer = {
disable_all = false,
create_comment = "c",
create_suggestion = "s",
move_to_discussion_tree = "a",
},
},
popup = {
width = "40%",
height = "60%",
border = "rounded",
@@ -82,36 +139,22 @@ M.settings = {
temp_registers = {},
},
discussion_tree = {
expanders = {
expanded = "",
collapsed = "",
indentation = " ",
},
auto_open = true,
switch_view = "S",
default_view = "discussions",
blacklist = {},
jump_to_file = "o",
jump_to_reviewer = "m",
edit_comment = "e",
delete_comment = "dd",
refresh_data = "a",
reply = "r",
toggle_node = "t",
add_emoji = "Ea",
delete_emoji = "Ed",
toggle_all_discussions = "T",
toggle_resolved_discussions = "R",
toggle_unresolved_discussions = "U",
keep_current_open = false,
publish_draft = "P",
toggle_resolved = "p",
position = "left",
open_in_browser = "b",
copy_node_url = "u",
size = "20%",
relative = "editor",
resolved = "",
unresolved = "-",
tree_type = "simple",
toggle_tree_type = "i",
draft_mode = false,
toggle_draft_mode = "D",
},
create_mr = {
target = nil,
@@ -181,7 +224,7 @@ M.settings = {
username = "Keyword",
mention = "WarningMsg",
date = "Comment",
chevron = "DiffviewNonText",
expander = "DiffviewNonText",
directory = "Directory",
directory_icon = "DiffviewFolderSign",
file_name = "Normal",
@@ -202,6 +245,135 @@ M.unlinked_discussion_tree = {
unresolved_expanded = false,
}
-- These keymaps are set globally when the plugin is initialized
M.set_global_keymaps = function()
local keymaps = M.settings.keymaps
if keymaps.disable_all or keymaps.global.disable_all then
return
end
if keymaps.global.start_review then
vim.keymap.set("n", keymaps.global.start_review, function()
require("gitlab").review()
end, { desc = "Start Gitlab review", nowait = keymaps.global.start_review_nowait })
end
if keymaps.global.choose_merge_request then
vim.keymap.set("n", keymaps.global.choose_merge_request, function()
require("gitlab").choose_merge_request()
end, { desc = "Choose MR for review", nowait = keymaps.global.choose_merge_request_nowait })
end
if keymaps.global.summary then
vim.keymap.set("n", keymaps.global.summary, function()
require("gitlab").summary()
end, { desc = "Show MR summary", nowait = keymaps.global.summary_nowait })
end
if keymaps.global.approve then
vim.keymap.set("n", keymaps.global.approve, function()
require("gitlab").approve()
end, { desc = "Approve MR", nowait = keymaps.global.approve_nowait })
end
if keymaps.global.revoke then
vim.keymap.set("n", keymaps.global.revoke, function()
require("gitlab").revoke()
end, { desc = "Revoke approval", nowait = keymaps.global.revoke_nowait })
end
if keymaps.global.create_mr then
vim.keymap.set("n", keymaps.global.create_mr, function()
require("gitlab").create_mr()
end, { desc = "Create MR", nowait = keymaps.global.create_mr_nowait })
end
if keymaps.global.create_note then
vim.keymap.set("n", keymaps.global.create_note, function()
require("gitlab").create_note()
end, { desc = "Create MR note", nowait = keymaps.global.create_note_nowait })
end
if keymaps.global.toggle_discussions then
vim.keymap.set("n", keymaps.global.toggle_discussions, function()
require("gitlab").toggle_discussions()
end, { desc = "Toggle MR discussions", nowait = keymaps.global.toggle_discussions_nowait })
end
if keymaps.global.add_assignee then
vim.keymap.set("n", keymaps.global.add_assignee, function()
require("gitlab").add_assignee()
end, { desc = "Add MR assignee", nowait = keymaps.global.add_assignee_nowait })
end
if keymaps.global.delete_assignee then
vim.keymap.set("n", keymaps.global.delete_assignee, function()
require("gitlab").delete_assignee()
end, { desc = "Delete MR assignee", nowait = keymaps.global.delete_assignee_nowait })
end
if keymaps.global.add_label then
vim.keymap.set("n", keymaps.global.add_label, function()
require("gitlab").add_label()
end, { desc = "Add MR label", nowait = keymaps.global.add_label_nowait })
end
if keymaps.global.delete_label then
vim.keymap.set("n", keymaps.global.delete_label, function()
require("gitlab").delete_label()
end, { desc = "Delete MR label", nowait = keymaps.global.delete_label_nowait })
end
if keymaps.global.add_reviewer then
vim.keymap.set("n", keymaps.global.add_reviewer, function()
require("gitlab").add_reviewer()
end, { desc = "Add MR reviewer", nowait = keymaps.global.add_reviewer_nowait })
end
if keymaps.global.delete_reviewer then
vim.keymap.set("n", keymaps.global.delete_reviewer, function()
require("gitlab").delete_reviewer()
end, { desc = "Delete MR reviewer", nowait = keymaps.global.delete_reviewer_nowait })
end
if keymaps.global.pipeline then
vim.keymap.set("n", keymaps.global.pipeline, function()
require("gitlab").pipeline()
end, { desc = "Show MR pipeline status", nowait = keymaps.global.pipeline_nowait })
end
if keymaps.global.open_in_browser then
vim.keymap.set("n", keymaps.global.open_in_browser, function()
require("gitlab").open_in_browser()
end, { desc = "Open MR in browser", nowait = keymaps.global.open_in_browser_nowait })
end
if keymaps.global.merge then
vim.keymap.set("n", keymaps.global.merge, function()
require("gitlab").merge()
end, { desc = "Merge MR", nowait = keymaps.global.merge_nowait })
end
if keymaps.global.copy_mr_url then
vim.keymap.set("n", keymaps.global.copy_mr_url, function()
require("gitlab").copy_mr_url()
end, { desc = "Copy MR url", nowait = keymaps.global.copy_mr_url_nowait })
end
if keymaps.global.publish_all_drafts then
vim.keymap.set("n", keymaps.global.publish_all_drafts, function()
require("gitlab").publish_all_drafts()
end, { desc = "Publish all MR comment drafts", nowait = keymaps.global.publish_all_drafts_nowait })
end
if keymaps.global.toggle_draft_mode then
vim.keymap.set("n", keymaps.global.toggle_draft_mode, function()
require("gitlab").toggle_draft_mode()
end, { desc = "Toggle MR comment draft mode", nowait = keymaps.global.toggle_draft_mode_nowait })
end
end
-- Merges user settings into the default settings, overriding them
M.merge_settings = function(args)
M.settings = u.merge(M.settings, args)
@@ -225,9 +397,43 @@ M.merge_settings = function(args)
return false
end
if M.settings.review_pane ~= nil then
local removed_fields_in_user_config = {}
local removed_settings_fields = {
"discussion_tree.add_emoji",
"discussion_tree.copy_node_url",
"discussion_tree.delete_comment",
"discussion_tree.delete_emoji",
"discussion_tree.edit_comment",
"discussion_tree.jump_to_file",
"discussion_tree.jump_to_reviewer",
"discussion_tree.open_in_browser",
"discussion_tree.publish_draft",
"discussion_tree.refresh_data",
"discussion_tree.reply",
"discussion_tree.switch_view",
"discussion_tree.toggle_all_discussions",
"discussion_tree.toggle_draft_mode",
"discussion_tree.toggle_node",
"discussion_tree.toggle_resolved",
"discussion_tree.toggle_resolved_discussions",
"discussion_tree.toggle_tree_type",
"discussion_tree.toggle_unresolved_discussions",
"help",
"popup.keymaps.next_field",
"popup.keymaps.prev_field",
"popup.perform_action",
"popup.perform_linewise_action",
"review_pane", -- Only relevant for the Delta reviewer
}
for _, field in ipairs(removed_settings_fields) do
if u.get_nested_field(M.settings, field) ~= nil then
table.insert(removed_fields_in_user_config, field)
end
end
if #removed_fields_in_user_config ~= 0 then
u.notify(
"The review_pane field is only relevant for Delta, which has been deprecated, please remove it from your setup function",
"The following settings fields have been removed:\n" .. table.concat(removed_fields_in_user_config, "\n"),
vim.log.levels.WARN
)
end
@@ -284,17 +490,21 @@ end
-- These keymaps are buffer specific and are set dynamically when popups mount
M.set_popup_keymaps = function(popup, action, linewise_action, opts)
if M.settings.keymaps.disable_all or M.settings.keymaps.popup.disable_all then
return
end
if opts == nil then
opts = {}
end
if action ~= "Help" then -- Don't show help on the help popup
vim.keymap.set("n", M.settings.help, function()
if action ~= "Help" and M.settings.keymaps.help then -- Don't show help on the help popup
vim.keymap.set("n", M.settings.keymaps.help, function()
local help = require("gitlab.actions.help")
help.open()
end, { buffer = popup.bufnr, desc = "Open help" })
end, { buffer = popup.bufnr, desc = "Open help", nowait = M.settings.keymaps.help_nowait })
end
if action ~= nil then
vim.keymap.set("n", M.settings.popup.perform_action, function()
if action ~= nil and M.settings.keymaps.popup.perform_action then
vim.keymap.set("n", M.settings.keymaps.popup.perform_action, function()
local text = u.get_buffer_text(popup.bufnr)
if opts.action_before_close then
action(text, popup.bufnr)
@@ -303,16 +513,33 @@ M.set_popup_keymaps = function(popup, action, linewise_action, opts)
exit(popup, opts)
action(text, popup.bufnr)
end
end, { buffer = popup.bufnr, desc = "Perform action" })
end, { buffer = popup.bufnr, desc = "Perform action", nowait = M.settings.keymaps.popup.perform_action_nowait })
end
if linewise_action ~= nil then
vim.keymap.set("n", M.settings.popup.perform_linewise_action, function()
if linewise_action ~= nil and M.settings.keymaps.popup.perform_action then
vim.keymap.set("n", M.settings.keymaps.popup.perform_linewise_action, function()
local bufnr = vim.api.nvim_get_current_buf()
local linnr = vim.api.nvim_win_get_cursor(0)[1]
local text = u.get_line_content(bufnr, linnr)
linewise_action(text)
end, { buffer = popup.bufnr, desc = "Perform linewise action" })
end, {
buffer = popup.bufnr,
desc = "Perform linewise action",
nowait = M.settings.keymaps.popup.perform_linewise_action_nowait,
})
end
if M.settings.keymaps.popup.discard_changes then
vim.keymap.set("n", M.settings.keymaps.popup.discard_changes, function()
local temp_registers = M.settings.popup.temp_registers
M.settings.popup.temp_registers = {}
vim.cmd("quit!")
M.settings.popup.temp_registers = temp_registers
end, {
buffer = popup.bufnr,
desc = "Quit discarding changes",
nowait = M.settings.keymaps.popup.discard_changes_nowait,
})
end
if opts.save_to_temp_register then

View File

@@ -739,4 +739,17 @@ M.ensure_table = function(data)
return data
end
M.get_nested_field = function(table, field)
local subfield = string.match(field, "[^.]+")
local subtable = table[subfield]
if subtable ~= nil then
local new_field = string.gsub(field, "^" .. subfield .. ".?", "")
if new_field ~= "" then
return M.get_nested_field(subtable, new_field)
else
return subtable
end
end
end
return M