From cc68476b15d3bd89105c4c01dd4a24e264bb92c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20F=2E=20Bortl=C3=ADk?= Date: Tue, 5 Dec 2023 14:06:32 +0100 Subject: [PATCH] Make Popups Configurable (#129) This makes the popups in the plugin (those for editing and creating comments, replies, the pipeline, etc) configurable. Users can change the default width, height, transparency, and border properties, and set overrides per popup. --- .github/CONTRIBUTING.md | 12 +++++----- .gitignore | 1 + README.md | 29 ++++++++++++++++--------- lua/gitlab/actions/comment.lua | 12 ++++++++-- lua/gitlab/actions/discussions/init.lua | 18 +++++++-------- lua/gitlab/actions/pipeline.lua | 5 +++-- lua/gitlab/state.lua | 15 ++++++++++--- lua/gitlab/utils/init.lua | 20 ++++++++++++----- 8 files changed, 75 insertions(+), 37 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index aa3ff10..b840306 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -20,7 +20,7 @@ If you are using Lazy as a plugin manager, the easiest way to work on changes is build = function() require("gitlab.server").build() end, - dir = "~/.path/to/your-closed-version", -- Pass in the path to your cloned repository + dir = "~/.path/to/your-cloned-version", -- Pass in the path to your cloned repository config = function() require("gitlab").setup({}) end, @@ -31,18 +31,18 @@ If you are making changes to the Go codebase, don't forget to run `make compile` 3. Apply formatters and linters to your changes -For changes to the Go codbase: We use gofmt to check formatting and golangci-lint to check linting. Run these commands in the root of the repository: +For changes to the Go codebase: We use gofmt to check formatting and golangci-lint to check linting. Run these commands in the root of the repository: ```bash -$ stylua . -$ luacheck --globals vim busted --no-max-line-length -- . +$ go fmt ./... +$ golangci-lint run ``` For changes to the Lua codebase: We use stylua for formatting and luacheck for linting. Run these commands in the root of the repository: ```bash -$ go fmt ./... -$ golangci-lint run +$ stylua . +$ luacheck --globals vim busted --no-max-line-length -- . ``` 4. Make the merge request to the `main` branch of `.gitlab.nvim` diff --git a/.gitignore b/.gitignore index 58519d8..cb0abe5 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ bin tests/plugins !tests/plugins/.placeholder luacov.* +tags diff --git a/README.md b/README.md index cfe3e58..cf6f896 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,8 @@ use { "MunifTanjim/nui.nvim", "nvim-lua/plenary.nvim", "sindrets/diffview.nvim", - "stevearc/dressing.nvim", + "stevearc/dressing.nvim", -- Recommended but not required. Better UI for pickers. + "nvim-tree/nvim-web-devicons", -- Recommended but not required. Icons in discussion tree. }, run = function() require("gitlab.server").build(true) end, config = function() @@ -120,6 +121,15 @@ require("gitlab").setup({ exit = "", perform_action = "s", -- Once in normal mode, does action (like saving comment or editing description, etc) perform_linewise_action = "l", -- Once in normal mode, does the linewise action (see logs for this job, etc) + width = "40%", + height = "60%", + border = "rounded", -- One of "rounded", "single", "double", "solid" + opacity = 1.0, -- From 0.0 (fully transparent) to 1.0 (fully opaque) + comment = nil, -- Individual popup overrides, e.g. { width = "60%", height = "80%", border = "single", opacity = 0.85 }, + edit = nil, + note = nil, + pipeline = nil, + reply = nil, }, discussion_tree = { -- The discussion tree that holds all comments blacklist = {}, -- List of usernames to remove from tree (bots, CI, etc) @@ -252,7 +262,7 @@ To display all discussions for the current MR, use the `toggle_discussions` acti require("gitlab").toggle_discussions() ``` -You can jump to the comment's location in the reviewer window by using the `state.settings.discussion_tree.jump_to_reviewer` key, or the actual file with the 'state.settings.discussion_tree.jump_to_file' key. +You can jump to the comment's 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. Within the discussion tree, you can delete/edit/reply to comments with the `state.settings.discussion_tree.SOME_ACTION` keybindings. @@ -264,26 +274,26 @@ require("gitlab").create_note() ### Discussion signs and diagnostics -By default when reviewing files you will see signs and diagnostics ( if enabled in configuration ). When cursor is on diagnostic line you can view discussion thread by using `vim.diagnostic.show`. You can also jump to discussion tree where you can reply, edit or delete discussion. +By default when reviewing files you will see signs and diagnostics (if enabled in configuration). When cursor is on diagnostic line you can view discussion thread by using `vim.diagnostic.show`. You can also jump to discussion tree where you can reply, edit or delete discussion. ```lua require("gitlab").move_to_discussion_tree_from_diagnostic() ``` -The `discussion_sign` configuration controls the display of signs for discussions in the reviewer pane. Keep in mind that the highlights provided here can be overridden by other highlights (for example from diffview.nvim). This allows users to jump to comments in the current buffer in the reviewer pane directly. +The `discussion_sign` configuration controls the display of signs for discussions in the reviewer pane. This allows users to jump to comments in the current buffer in the reviewer pane directly. Keep in mind that the highlights provided here can be overridden by other highlights (for example from `diffview.nvim`). -These diagnostics are configurable in the same way that diagnostics are typically configurable in Neovim. For instance, the `severity` key sets the diagnostic severity level and should be set to one of `vim.diagnostic.severity.ERROR`, `vim.diagnostic.severity.WARN`, `vim.diagnostic.severity.INFO`, or `vim.diagnostic.severity.HINT`. The `display_opts` option configures the diagnostic display options where you can configure values like (this is directly used as opts in vim.diagnostic.set): +These diagnostics are configurable in the same way that diagnostics are typically configurable in Neovim. For instance, the `severity` key sets the diagnostic severity level and should be set to one of `vim.diagnostic.severity.ERROR`, `vim.diagnostic.severity.WARN`, `vim.diagnostic.severity.INFO`, or `vim.diagnostic.severity.HINT`. The `display_opts` option configures the diagnostic display options (this is directly used as opts in vim.diagnostic.set). Here you can configure values like: - `virtual_text` - Show virtual text for diagnostics. - `underline` - Underline text for diagnostics. -Diagnostics for discussions use the `gitlab_discussion` namespace. See `:h vim.diagnostic.config` and `:h diagnostic-structure` for more details. Signs and diagnostics have common settings in `discussion_sign_and_diagnostics`. This allows customizing if discussions that are resolved or no longer relevant should still display visual indicators in the editor. The `skip_resolved_discussion` Boolean will control visibility of resolved discussions, and `skip_old_revision_discussion` whether to show signs and diagnostics for discussions on outdated diff revisions. +Diagnostics for discussions use the `gitlab_discussion` namespace. See `:h vim.diagnostic.config` and `:h diagnostic-structure` for more details. Signs and diagnostics have common settings in `discussion_sign_and_diagnostic`. This allows customizing if discussions that are resolved or no longer relevant should still display visual indicators in the editor. The `skip_resolved_discussion` Boolean will control visibility of resolved discussions, and `skip_old_revision_discussion` whether to show signs and diagnostics for discussions on outdated diff revisions. When interacting with multiline comments, the cursor must be on the "main" line of diagnostic, where the `discussion_sign.text` is shown, otherwise `vim.diagnostic.show` and `jump_to_discussion_tree_from_diagnostic` will not work. ### 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. This will open a picker that will look in the directory you specify in the `settings.attachment_dir` folder (this must be an absolute path) for 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. 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. @@ -331,8 +341,7 @@ require("dressing").setup({ ### Restarting or Shutting Down -The `gitlab.nvim` server will shut down automatically when you exit Neovim. However, if you would like to manage this yourself (for instance, restart the server when you check out a new branch) you may do so via the `restart` command, or `shutdown` commands, which -both accept callbacks. +The `gitlab.nvim` server will shut down automatically when you exit Neovim. However, if you would like to manage this yourself (for instance, restart the server when you check out a new branch) you may do so via the `restart` command, or `shutdown` commands, which both accept callbacks. ```lua require("gitlab.server").restart() @@ -382,7 +391,7 @@ vim.keymap.set("n", "glo", gitlab.open_in_browser) **To check that the current settings of the plugin are configured correctly, please run: `:lua require("gitlab").print_settings()`** -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: +This plugin uses a Go server to reach out to Gitlab. It's possible that something is going wrong when starting that server or connecting with Gitlab. The Go 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: ```lua :lua require("gitlab.server").build(true) diff --git a/lua/gitlab/actions/comment.lua b/lua/gitlab/actions/comment.lua index f4661e1..06a56f5 100644 --- a/lua/gitlab/actions/comment.lua +++ b/lua/gitlab/actions/comment.lua @@ -10,12 +10,17 @@ local miscellaneous = require("gitlab.actions.miscellaneous") local reviewer = require("gitlab.reviewer") local M = {} -local comment_popup = Popup(u.create_popup_state("Comment", "40%", "60%")) -local note_popup = Popup(u.create_popup_state("Note", "40%", "60%")) +-- Popup creation is wrapped in a function so that it is performed *after* user +-- configuration has been merged with default configuration, not when this file is being +-- required. +local function create_comment_popup() + return Popup(u.create_popup_state("Comment", state.settings.popup.comment)) +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() + local comment_popup = create_comment_popup() comment_popup:mount() state.set_popup_keymaps(comment_popup, function(text) M.confirm_create_comment(text) @@ -27,6 +32,7 @@ M.create_multiline_comment = function() if not u.check_visual_mode() then return end + local comment_popup = create_comment_popup() local start_line, end_line = u.get_visual_selection_boundaries() comment_popup:mount() state.set_popup_keymaps(comment_popup, function(text) @@ -40,6 +46,7 @@ M.create_comment_suggestion = function() if not u.check_visual_mode() then return end + local comment_popup = create_comment_popup() local start_line, end_line = u.get_visual_selection_boundaries() local current_line = vim.api.nvim_win_get_cursor(0)[1] local range = end_line - start_line @@ -81,6 +88,7 @@ M.create_comment_suggestion = function() end M.create_note = function() + local note_popup = Popup(u.create_popup_state("Note", state.settings.popup.note)) note_popup:mount() state.set_popup_keymaps(note_popup, function(text) M.confirm_create_comment(text, nil, true) diff --git a/lua/gitlab/actions/discussions/init.lua b/lua/gitlab/actions/discussions/init.lua index f104a00..3c02c8f 100644 --- a/lua/gitlab/actions/discussions/init.lua +++ b/lua/gitlab/actions/discussions/init.lua @@ -13,8 +13,6 @@ local reviewer = require("gitlab.reviewer") local miscellaneous = require("gitlab.actions.miscellaneous") local discussions_tree = require("gitlab.actions.discussions.tree") -local edit_popup = Popup(u.create_popup_state("Edit Comment", "80%", "80%")) -local reply_popup = Popup(u.create_popup_state("Reply", "80%", "80%")) local discussion_sign_name = "gitlab_discussion" local discussion_helper_sign_start = "gitlab_discussion_helper_start" local discussion_helper_sign_mid = "gitlab_discussion_helper_mid" @@ -470,6 +468,7 @@ 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. M.reply = function(tree) + local reply_popup = Popup(u.create_popup_state("Reply", state.settings.popup.reply)) local node = tree:get_node() local discussion_node = M.get_root_node(tree, node) local id = tostring(discussion_node.id) @@ -536,6 +535,7 @@ end -- This function (settings.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() local note_node = M.get_note_node(tree, current_node) local root_node = M.get_root_node(tree, current_node) @@ -811,37 +811,37 @@ M.set_tree_keymaps = function(tree, bufnr, unlinked) if M.is_current_node_note(tree) then M.edit_comment(tree, unlinked) end - end, { buffer = bufnr }) + end, { buffer = bufnr, desc = "Edit comment" }) 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 }) + end, { buffer = bufnr, desc = "Delete comment" }) vim.keymap.set("n", state.settings.discussion_tree.toggle_resolved, function() if M.is_current_node_note(tree) then M.toggle_discussion_resolved(tree) end - end, { buffer = bufnr }) + end, { buffer = bufnr, desc = "Toggle resolved" }) vim.keymap.set("n", state.settings.discussion_tree.toggle_node, function() M.toggle_node(tree) - end, { buffer = bufnr }) + end, { buffer = bufnr, desc = "Toggle node" }) 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 }) + end, { buffer = bufnr, desc = "Reply" }) if not unlinked then vim.keymap.set("n", state.settings.discussion_tree.jump_to_file, function() if M.is_current_node_note(tree) then M.jump_to_file(tree) end - end, { buffer = bufnr }) + 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 M.jump_to_reviewer(tree) end - end, { buffer = bufnr }) + end, { buffer = bufnr, desc = "Jump to reviewer" }) end end diff --git a/lua/gitlab/actions/pipeline.lua b/lua/gitlab/actions/pipeline.lua index 2407210..7cb086d 100644 --- a/lua/gitlab/actions/pipeline.lua +++ b/lua/gitlab/actions/pipeline.lua @@ -1,4 +1,4 @@ --- This module is responsible for the MR pipline +-- This module is responsible for the MR pipeline -- This lets the user see the current status of the pipeline -- and retrigger the pipeline from within the editor local Popup = require("nui.popup") @@ -42,7 +42,8 @@ M.open = function() local width = string.len(pipeline.web_url) + 10 local height = 6 + #pipeline_jobs + 3 - local pipeline_popup = Popup(u.create_popup_state("Loading Pipeline...", width, height)) + local pipeline_popup = + Popup(u.create_popup_state("Loading Pipeline...", state.settings.popup.pipeline, width, height)) M.pipeline_popup = pipeline_popup pipeline_popup:mount() diff --git a/lua/gitlab/state.lua b/lua/gitlab/state.lua index 3efb444..a2decb1 100644 --- a/lua/gitlab/state.lua +++ b/lua/gitlab/state.lua @@ -18,6 +18,15 @@ M.settings = { exit = "", perform_action = "s", perform_linewise_action = "l", + width = "40%", + height = "60%", + border = "rounded", + opacity = 1.0, + edit = nil, + reply = nil, + comment = nil, + note = nil, + pipeline = nil, }, discussion_tree = { blacklist = {}, @@ -207,7 +216,7 @@ M.set_popup_keymaps = function(popup, action, linewise_action, opts) end vim.keymap.set("n", M.settings.popup.exit, function() exit(popup, opts.cb) - end, { buffer = popup.bufnr }) + end, { buffer = popup.bufnr, desc = "Exit popup" }) if action ~= nil then vim.keymap.set("n", M.settings.popup.perform_action, function() local text = u.get_buffer_text(popup.bufnr) @@ -218,7 +227,7 @@ M.set_popup_keymaps = function(popup, action, linewise_action, opts) exit(popup) action(text, popup.bufnr) end - end, { buffer = popup.bufnr }) + end, { buffer = popup.bufnr, desc = "Perform action" }) end if linewise_action ~= nil then @@ -227,7 +236,7 @@ M.set_popup_keymaps = function(popup, action, linewise_action, opts) 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 }) + end, { buffer = popup.bufnr, desc = "Perform linewise action" }) end end diff --git a/lua/gitlab/utils/init.lua b/lua/gitlab/utils/init.lua index 2763b50..5e893ac 100644 --- a/lua/gitlab/utils/init.lua +++ b/lua/gitlab/utils/init.lua @@ -344,8 +344,16 @@ M.jump_to_buffer = function(bufnr, line_number) vim.api.nvim_win_set_cursor(0, { line_number, 0 }) end -M.create_popup_state = function(title, width, height) - return { +---Get the popup view_opts +---@param title string The string to appear on top of the popup +---@param settings table User defined popup settings +---@param width string Override default width +---@param height string Override default height +---@return table +M.create_popup_state = function(title, settings, width, height) + local default_settings = require("gitlab.state").settings.popup + local user_settings = settings or {} + local view_opts = { buf_options = { filetype = "markdown", }, @@ -353,17 +361,19 @@ M.create_popup_state = function(title, width, height) enter = true, focusable = true, border = { - style = "rounded", + style = user_settings.border or default_settings.border, text = { top = title, }, }, position = "50%", size = { - width = width, - height = height, + width = user_settings.width or width or default_settings.width, + height = user_settings.height or height or default_settings.height, }, + opacity = user_settings.opacity or default_settings.opacity, } + return view_opts end M.read_file = function(file_path)