From ffdaf83784003724e049554b424ccaa416be9e19 Mon Sep 17 00:00:00 2001 From: "Harrison (Harry) Cramer" <32515581+harrisoncramer@users.noreply.github.com> Date: Fri, 10 Nov 2023 17:38:28 -0500 Subject: [PATCH] BREAKING CHANGE: This is a breaking change, it deprecates the Delta Reviewer (#81) BREAKING This is a breaking change which deprecates support for the Delta reviewer. Now, only Diffview is supported. --- README.md | 25 +- .../actions/assignees_and_reviewers.lua | 4 +- lua/gitlab/actions/comment.lua | 13 +- lua/gitlab/actions/discussions.lua | 105 +++----- lua/gitlab/actions/miscellaneous.lua | 8 +- lua/gitlab/actions/pipeline.lua | 14 +- lua/gitlab/actions/summary.lua | 2 +- lua/gitlab/async.lua | 3 +- lua/gitlab/init.lua | 7 +- lua/gitlab/job.lua | 11 +- lua/gitlab/reviewer/delta.lua | 254 ------------------ lua/gitlab/reviewer/diffview.lua | 22 +- lua/gitlab/reviewer/init.lua | 9 +- lua/gitlab/server.lua | 13 +- lua/gitlab/state.lua | 46 ++-- lua/gitlab/utils/init.lua | 22 +- 16 files changed, 127 insertions(+), 431 deletions(-) delete mode 100644 lua/gitlab/reviewer/delta.lua diff --git a/README.md b/README.md index 3ead4cb..245bfc0 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,6 @@ https://github.com/harrisoncramer/gitlab.nvim/assets/32515581/50f44eaf-5f99-4cb3 ## Quick Start 1. Install Go -2. Install reviewer: delta or diffview 3. Add configuration (see Installation section) 4. Checkout your feature branch: `git checkout feature-branch` 5. Open Neovim @@ -36,12 +35,13 @@ return { dependencies = { "MunifTanjim/nui.nvim", "nvim-lua/plenary.nvim", + "sindrets/diffview.nvim", "stevearc/dressing.nvim", -- Recommended but not required. Better UI for pickers. enabled = true, }, build = function () require("gitlab.server").build(true) end, -- Builds the Go binary config = function() - require("gitlab").setup() -- Uses delta reviewer by default + require("gitlab").setup() end, } ``` @@ -54,6 +54,7 @@ use { requires = { "MunifTanjim/nui.nvim", "nvim-lua/plenary.nvim" + "sindrets/diffview.nvim", }, run = function() require("gitlab.server").build(true) end, config = function() @@ -87,7 +88,6 @@ require("gitlab").setup({ port = nil, -- The port of the Go server, which runs in the background, if omitted or `nil` the port will be chosen automatically log_path = vim.fn.stdpath("cache") .. "/gitlab.nvim.log", -- Log path for the Go server debug = { go_request = false, go_response = false }, -- Which values to log - reviewer = "delta", -- The reviewer type ("delta" or "diffview") attachment_dir = nil, -- The local directory for files (see the "summary" section) popup = { -- The popup for comment creation, editing, and replying exit = "", @@ -109,19 +109,6 @@ require("gitlab").setup({ resolved = '✓', -- Symbol to show next to resolved discussions unresolved = '✖', -- Symbol to show next to unresolved discussions }, - review_pane = { -- Specific settings for different reviewers - delta = { - added_file = "", -- The symbol to show next to added files - modified_file = "", -- The symbol to show next to modified files - removed_file = "", -- The symbol to show next to removed files - } - }, - dialogue = { -- The confirmation dialogue for deleting comments - focus_next = { "j", "", "" }, - focus_prev = { "k", "", "" }, - close = { "", "" }, - submit = { "", "" }, - }, pipeline = { created = "", pending = "", @@ -170,14 +157,12 @@ The `review` action will open a diff of the changes. You can leave comments usin ```lua require("gitlab").review() require("gitlab").create_comment() -require("gitlab").create_multiline_comment() -- Only supported for diffview reviewer -require("gitlab").create_comment_suggestion() -- Only supported for diffview reviewer +require("gitlab").create_multiline_comment() +require("gitlab").create_comment_suggestion() ``` 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 [suggest changes](https://docs.gitlab.com/ee/user/project/merge_requests/reviews/suggestions.html) code block with prefilled code from visual selection. -The reviewer is Delta by default, but you can configure the plugin to use Diffview instead. - ### Discussions and Notes Gitlab groups threads of comments together into "discussions." diff --git a/lua/gitlab/actions/assignees_and_reviewers.lua b/lua/gitlab/actions/assignees_and_reviewers.lua index 2898cfc..8c99cbc 100644 --- a/lua/gitlab/actions/assignees_and_reviewers.lua +++ b/lua/gitlab/actions/assignees_and_reviewers.lua @@ -38,7 +38,7 @@ M.add_popup = function(type) table.insert(current_ids, choice.id) local body = { ids = current_ids } job.run_job("/mr/" .. type, "PUT", body, function(data) - vim.notify(data.message, vim.log.levels.INFO) + u.notify(data.message, vim.log.levels.INFO) state.INFO[plural] = data[plural] end) end) @@ -59,7 +59,7 @@ M.delete_popup = function(type) local ids = u.extract(M.filter_eligible(current, { choice }), "id") local body = { ids = ids } job.run_job("/mr/" .. type, "PUT", body, function(data) - vim.notify(data.message, vim.log.levels.INFO) + u.notify(data.message, vim.log.levels.INFO) state.INFO[plural] = data[plural] end) end) diff --git a/lua/gitlab/actions/comment.lua b/lua/gitlab/actions/comment.lua index 2254926..8be3312 100644 --- a/lua/gitlab/actions/comment.lua +++ b/lua/gitlab/actions/comment.lua @@ -46,11 +46,6 @@ M.create_comment_suggestion = function() local backticks = "```" local selected_lines = reviewer.get_lines(start_line, end_line) - if selected_lines == nil then - -- TODO: remove when delta is supported - return - end - for line in ipairs(selected_lines) do if string.match(line, "^```$") then backticks = "````" @@ -65,7 +60,7 @@ M.create_comment_suggestion = function() suggestion_start = backticks .. "suggestion:-" .. range .. "+0" else -- This should never happen afaik - vim.notify("Unexpected suggestion position", vim.log.levels.ERROR) + u.notify("Unexpected suggestion position", vim.log.levels.ERROR) return end suggestion_start = suggestion_start @@ -117,14 +112,14 @@ end ---@param unlinked boolean | nil if true, the comment is not linked to a line M.confirm_create_comment = function(text, range, unlinked) if text == nil then - vim.notify("Reviewer did not provide text of change", vim.log.levels.ERROR) + u.notify("Reviewer did not provide text of change", vim.log.levels.ERROR) return end if unlinked then local body = { comment = text } job.run_job("/comment", "POST", body, function(data) - vim.notify("Note created!", vim.log.levels.INFO) + u.notify("Note created!", vim.log.levels.INFO) discussions.add_discussion({ data = data, unlinked = true }) end) return @@ -149,7 +144,7 @@ M.confirm_create_comment = function(text, range, unlinked) } job.run_job("/comment", "POST", body, function(data) - vim.notify("Comment created!", vim.log.levels.INFO) + u.notify("Comment created!", vim.log.levels.INFO) discussions.add_discussion({ data = data, unlinked = false }) end) end diff --git a/lua/gitlab/actions/discussions.lua b/lua/gitlab/actions/discussions.lua index f1245e9..e24ef90 100644 --- a/lua/gitlab/actions/discussions.lua +++ b/lua/gitlab/actions/discussions.lua @@ -3,7 +3,6 @@ -- and marking discussions as resolved/unresolved. local Split = require("nui.split") local Popup = require("nui.popup") -local Menu = require("nui.menu") local NuiTree = require("nui.tree") local Layout = require("nui.layout") local job = require("gitlab.job") @@ -40,7 +39,7 @@ M.toggle = function() job.run_job("/discussions", "POST", { blacklist = state.settings.discussion_tree.blacklist }, function(data) if type(data.discussions) ~= "table" and type(data.unlinked_discussions) ~= "table" then - vim.notify("No discussions or notes for this MR", vim.log.levels.WARN) + u.notify("No discussions or notes for this MR", vim.log.levels.WARN) return end @@ -86,7 +85,7 @@ M.send_reply = function(tree, discussion_id) return function(text) local body = { discussion_id = discussion_id, reply = text } job.run_job("/reply", "POST", body, function(data) - vim.notify("Sent reply!", vim.log.levels.INFO) + u.notify("Sent reply!", vim.log.levels.INFO) M.add_reply_to_tree(tree, data.note, discussion_id) end) end @@ -94,74 +93,48 @@ end -- This function (settings.discussion_tree.delete_comment) will trigger a popup prompting you to delete the current comment M.delete_comment = function(tree, unlinked) - local menu = Menu({ - position = "50%", - size = { - width = 25, - }, - border = { - style = "single", - text = { - top = "Delete Comment?", - top_align = "center", - }, - }, - win_options = { - winhighlight = "Normal:Normal,FloatBorder:Normal", - }, - }, { - lines = { - Menu.item("Confirm"), - Menu.item("Cancel"), - }, - max_width = 20, - keymap = { - focus_next = state.settings.dialogue.focus_next, - focus_prev = state.settings.dialogue.focus_prev, - close = state.settings.dialogue.close, - submit = state.settings.dialogue.submit, - }, - on_submit = function(item) - M.send_deletion(tree, item, unlinked) - end, - }) - menu:mount() + vim.ui.select({ "Confirm", "Cancel" }, { + prompt = "Delete comment?", + }, function(choice) + if choice == "Cancel" then + return + end + M.send_deletion(tree, unlinked) + end) end -- This function will actually send the deletion to Gitlab -- when you make a selection, and re-render the tree -M.send_deletion = function(tree, item, unlinked) - if item.text == "Confirm" then - local current_node = tree:get_node() +M.send_deletion = function(tree, unlinked) + 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) - local note_id = note_node.is_root and root_node.root_note_id or note_node.id + local note_node = M.get_note_node(tree, current_node) + local root_node = M.get_root_node(tree, current_node) + local note_id = note_node.is_root and root_node.root_note_id or note_node.id - local body = { discussion_id = root_node.id, note_id = note_id } + local body = { discussion_id = root_node.id, note_id = note_id } - job.run_job("/comment", "DELETE", body, function(data) - vim.notify(data.message, vim.log.levels.INFO) - if not note_node.is_root then - tree:remove_node("-" .. note_id) -- Note is not a discussion root, safe to remove - tree:render() + job.run_job("/comment", "DELETE", body, function(data) + u.notify(data.message, vim.log.levels.INFO) + if not note_node.is_root then + tree:remove_node("-" .. note_id) -- Note is not a discussion root, safe to remove + tree:render() + else + if unlinked then + M.unlinked_discussions = u.remove_first_value(M.unlinked_discussions) + M.rebuild_unlinked_discussion_tree() else - if unlinked then - M.unlinked_discussions = u.remove_first_value(M.unlinked_discussions) - M.rebuild_unlinked_discussion_tree() - else - M.discussions = u.remove_first_value(M.discussions) - M.rebuild_discussion_tree() - end + M.discussions = u.remove_first_value(M.discussions) + M.rebuild_discussion_tree() end - M.switch_can_edit_bufs(true) - M.add_empty_titles({ - { M.linked_section_bufnr, M.discussions, "No Discussions for this MR" }, - { M.unlinked_section_bufnr, M.unlinked_discussions, "No Notes (Unlinked Discussions) for this MR" }, - }) - M.switch_can_edit_bufs(false) - end) - end + end + M.switch_can_edit_bufs(true) + M.add_empty_titles({ + { M.linked_section_bufnr, M.discussions, "No Discussions for this MR" }, + { M.unlinked_section_bufnr, M.unlinked_discussions, "No Notes (Unlinked Discussions) for this MR" }, + }) + M.switch_can_edit_bufs(false) + end) end -- This function (settings.discussion_tree.edit_comment) will open the edit popup for the current comment in the discussion tree @@ -199,7 +172,7 @@ M.send_edits = function(discussion_id, note_id, unlinked) comment = text, } job.run_job("/comment", "PATCH", body, function(data) - vim.notify(data.message, vim.log.levels.INFO) + u.notify(data.message, vim.log.levels.INFO) if unlinked then M.unlinked_discussions = M.replace_text(M.unlinked_discussions, discussion_id, note_id, text) M.rebuild_unlinked_discussion_tree() @@ -225,7 +198,7 @@ M.toggle_resolved = function(tree) } job.run_job("/comment", "PATCH", body, function(data) - vim.notify(data.message, vim.log.levels.INFO) + u.notify(data.message, vim.log.levels.INFO) M.redraw_resolved_status(tree, note, not note.resolved) end) end @@ -234,7 +207,7 @@ end M.jump_to_reviewer = function(tree) local file_name, new_line, old_line, error = M.get_note_location(tree) if error ~= nil then - vim.notify(error, vim.log.levels.ERROR) + u.notify(error, vim.log.levels.ERROR) return end reviewer.jump(file_name, new_line, old_line) @@ -244,7 +217,7 @@ end M.jump_to_file = function(tree) local file_name, new_line, old_line, error = M.get_note_location(tree) if error ~= nil then - vim.notify(error, vim.log.levels.ERROR) + u.notify(error, vim.log.levels.ERROR) return end vim.cmd.tabnew() diff --git a/lua/gitlab/actions/miscellaneous.lua b/lua/gitlab/actions/miscellaneous.lua index faaf640..12208c9 100644 --- a/lua/gitlab/actions/miscellaneous.lua +++ b/lua/gitlab/actions/miscellaneous.lua @@ -6,7 +6,7 @@ local M = {} M.open_in_browser = function() local url = state.INFO.web_url if url == nil then - vim.notify("Could not get Gitlab URL", vim.log.levels.ERROR) + u.notify("Could not get Gitlab URL", vim.log.levels.ERROR) return end if vim.fn.has("mac") == 1 then @@ -14,21 +14,21 @@ M.open_in_browser = function() elseif vim.fn.has("unix") == 1 then vim.fn.jobstart({ "xdg-open", url }) else - vim.notify("Opening a Gitlab URL is not supported on this OS!", vim.log.levels.ERROR) + u.notify("Opening a Gitlab URL is not supported on this OS!", vim.log.levels.ERROR) end end M.attach_file = function() local attachment_dir = state.settings.attachment_dir if not attachment_dir or attachment_dir == "" then - vim.notify("Must provide valid attachment_dir in plugin setup", vim.log.levels.ERROR) + u.notify("Must provide valid attachment_dir in plugin setup", vim.log.levels.ERROR) return end local files = u.list_files_in_folder(attachment_dir) if files == nil then - vim.notify(string.format("Could not list files in %s", attachment_dir), vim.log.levels.ERROR) + u.notify(string.format("Could not list files in %s", attachment_dir), vim.log.levels.ERROR) return end diff --git a/lua/gitlab/actions/pipeline.lua b/lua/gitlab/actions/pipeline.lua index f6ab421..6ccce65 100644 --- a/lua/gitlab/actions/pipeline.lua +++ b/lua/gitlab/actions/pipeline.lua @@ -14,7 +14,7 @@ local function get_pipeline() local pipeline = state.INFO.head_pipeline or state.INFO.pipeline if type(pipeline) ~= "table" or (type(pipeline) == "table" and u.table_size(pipeline) == 0) then - vim.notify("Pipeline not found", vim.log.levels.WARN) + u.notify("Pipeline not found", vim.log.levels.WARN) return end return pipeline @@ -86,12 +86,12 @@ M.retrigger = function() end local body = { pipeline_id = pipeline.id } if pipeline.status ~= "failed" then - vim.notify("Pipeline is not in a failed state!", vim.log.levels.WARN) + u.notify("Pipeline is not in a failed state!", vim.log.levels.WARN) return end job.run_job("/pipeline", "POST", body, function() - vim.notify("Pipeline re-triggered!", vim.log.levels.INFO) + u.notify("Pipeline re-triggered!", vim.log.levels.INFO) end) end @@ -101,7 +101,7 @@ M.see_logs = function() local text = u.get_line_content(bufnr, linnr) local last_word = u.get_last_chunk(text) if last_word == nil then - vim.notify("Cannot find job name", vim.log.levels.ERROR) + u.notify("Cannot find job name", vim.log.levels.ERROR) return end @@ -113,7 +113,7 @@ M.see_logs = function() end if j == nil then - vim.notify("Cannot find job in state", vim.log.levels.ERROR) + u.notify("Cannot find job in state", vim.log.levels.ERROR) return end @@ -121,7 +121,7 @@ M.see_logs = function() job.run_job("/job", "GET", body, function(data) local file = data.file if file == "" then - vim.notify("Log trace is empty", vim.log.levels.WARN) + u.notify("Log trace is empty", vim.log.levels.WARN) return end @@ -131,7 +131,7 @@ M.see_logs = function() end if #lines == 0 then - vim.notify("Log trace lines could not be parsed", vim.log.levels.ERROR) + u.notify("Log trace lines could not be parsed", vim.log.levels.ERROR) return end diff --git a/lua/gitlab/actions/summary.lua b/lua/gitlab/actions/summary.lua index 7ea38a7..4c8046c 100644 --- a/lua/gitlab/actions/summary.lua +++ b/lua/gitlab/actions/summary.lua @@ -63,7 +63,7 @@ M.edit_summary = function() local title = u.get_buffer_text(M.title_bufnr):gsub("\n", " ") local body = { title = title, description = description } job.run_job("/mr/summary", "PUT", body, function(data) - vim.notify(data.message, vim.log.levels.INFO) + u.notify(data.message, vim.log.levels.INFO) state.INFO.description = data.mr.description state.INFO.title = data.mr.title M.layout:unmount() diff --git a/lua/gitlab/async.lua b/lua/gitlab/async.lua index 281ace0..71b16a0 100644 --- a/lua/gitlab/async.lua +++ b/lua/gitlab/async.lua @@ -3,6 +3,7 @@ local server = require("gitlab.server") local job = require("gitlab.job") local state = require("gitlab.state") +local u = require("gitlab.utils") local M = {} @@ -48,7 +49,7 @@ M.sequence = function(dependencies, cb) handler:init(cb) if not state.is_gitlab_project then - vim.notify("The gitlab.nvim state was not set. Do you have a .gitlab.nvim file configured?", vim.log.levels.ERROR) + u.notify("The gitlab.nvim state was not set. Do you have a .gitlab.nvim file configured?", vim.log.levels.ERROR) return end diff --git a/lua/gitlab/init.lua b/lua/gitlab/init.lua index e76f0fd..be39239 100644 --- a/lua/gitlab/init.lua +++ b/lua/gitlab/init.lua @@ -22,10 +22,11 @@ return { end server.build() -- Builds the Go binary if it doesn't exist state.setPluginConfiguration() -- Sets configuration from `.gitlab.nvim` file - state.merge_settings(args) -- Sets keymaps and other settings from setup function + if not state.merge_settings(args) then -- Sets keymaps and other settings from setup function + return + end require("gitlab.colors") -- Sets colors - reviewer.init() -- Picks and initializes reviewer (default is Delta) - u.has_reviewer(args.reviewer or "delta") + reviewer.init() end, -- Global Actions 🌎 summary = async.sequence({ info }, summary.summary), diff --git a/lua/gitlab/job.lua b/lua/gitlab/job.lua index 5de022f..499c574 100644 --- a/lua/gitlab/job.lua +++ b/lua/gitlab/job.lua @@ -1,6 +1,7 @@ -- This module is responsible for making API calls to the Go server and -- running the callbacks associated with those jobs when the JSON is returned local Job = require("plenary.job") +local u = require("gitlab.utils") local M = {} M.run_job = function(endpoint, method, body, callback) @@ -27,7 +28,7 @@ M.run_job = function(endpoint, method, body, callback) if type(output) == "string" then msg = string.format(msg .. ", got: '%s'", output) end - vim.notify(string.format(msg, endpoint, output), vim.log.levels.WARN) + u.notify(string.format(msg, endpoint, output), vim.log.levels.WARN) return end if data ~= nil then @@ -36,23 +37,23 @@ M.run_job = function(endpoint, method, body, callback) callback(data) elseif status == "success" then local message = string.format("%s", data.message) - vim.notify(message, vim.log.levels.INFO) + u.notify(message, vim.log.levels.INFO) else local message = string.format("%s: %s", data.message, data.details) - vim.notify(message, vim.log.levels.ERROR) + u.notify(message, vim.log.levels.ERROR) end end end, 0) end, on_stderr = function() vim.defer_fn(function() - vim.notify("Could not run command!", vim.log.levels.ERROR) + u.notify("Could not run command!", vim.log.levels.ERROR) end, 0) end, on_exit = function(_, status) vim.defer_fn(function() if status ~= 0 then - vim.notify(string.format("Go server exited with non-zero code: %d", status), vim.log.levels.ERROR) + u.notify(string.format("Go server exited with non-zero code: %d", status), vim.log.levels.ERROR) end end, 0) end, diff --git a/lua/gitlab/reviewer/delta.lua b/lua/gitlab/reviewer/delta.lua deleted file mode 100644 index 98eacf2..0000000 --- a/lua/gitlab/reviewer/delta.lua +++ /dev/null @@ -1,254 +0,0 @@ --- This Module contains all of the code specific to the Delta reviewer. -local state = require("gitlab.state") -local u = require("gitlab.utils") - -local M = { - bufnr = nil, -} - --- Public Functions --- These functions are exposed externally and are used --- when the reviewer is consumed by other code. They must follow the specification --- outlined in the reviewer/init.lua file -M.open = function() - local current_buf = vim.api.nvim_get_current_buf() - if current_buf == state.discussion_buf then - vim.api.nvim_command("wincmd w") - end - - vim.cmd.enew() - if M.bufnr ~= nil then - vim.api.nvim_set_current_buf(M.bufnr) - return - end - - local term_command_template = - "GIT_PAGER='delta --hunk-header-style omit --line-numbers --paging never --file-added-label %s --file-removed-label %s --file-modified-label %s' git diff %s...HEAD" - - local term_command = string.format( - term_command_template, - state.settings.review_pane.delta.added_file, - state.settings.review_pane.delta.removed_file, - state.settings.review_pane.delta.modified_file, - state.INFO.target_branch - ) - - vim.fn.termopen(term_command) -- Calls delta and sends the output to the currently blank buffer - M.bufnr = vim.api.nvim_get_current_buf() - M.winnr = vim.api.nvim_get_current_win() -end - -M.jump = function(file_name, new_line, old_line) - local linnr, error = M.get_jump_location(file_name, new_line, old_line) - if error ~= nil then - vim.notify(error, vim.log.levels.ERROR) - return - end - - vim.api.nvim_set_current_win(M.winnr) - u.jump_to_buffer(M.bufnr, linnr) -end - ----Get the location of a line within the delta buffer. If range is specified, then also the location ----of the lines in range. ----@param range LineRange | nil Line range to get location for ----@return ReviewerInfo | nil nil is returned only if error was encountered -M.get_location = function(range) - if M.bufnr == nil then - vim.notify("Delta reviewer must be initialized first", vim.log.levels.ERROR) - return - end - - if range then - vim.notify("Multiline comments are not yet supported for delta reviewer", vim.log.levels.ERROR) - return - end - - local bufnr = vim.api.nvim_get_current_buf() - if bufnr ~= M.bufnr then - vim.notify("Line location can only be determined within reviewer window") - return - end - - local line_num = u.get_current_line_number() - local file_name = M.get_file_from_review_buffer(u.get_current_line_number()) - - local review_range, error = M.get_review_buffer_range(file_name) - - if error ~= nil then - vim.notify(error, vim.log.levels.ERROR) - return - end - - if review_range == nil then - vim.notify("Review buffer range could not be identified", vim.log.levels.ERROR) - return - end - - -- In case the comment is left on a line without change information, we - -- iterate backward until we find it within the range of the changes - local current_line_changes = nil - local num = line_num - while review_range ~= nil and num >= review_range[1] and current_line_changes == nil do - local content = u.get_line_content(M.bufnr, num) - local change_nums = M.get_change_nums(content) - current_line_changes = change_nums - num = num - 1 - end - - if current_line_changes == nil then - vim.notify("Could not find current line change information", vim.log.levels.ERROR) - return - end - - local new_line_num = line_num + 1 - local next_line_changes = nil - while review_range ~= nil and new_line_num <= review_range[2] and next_line_changes == nil do - local content = u.get_line_content(M.bufnr, new_line_num) - local change_nums = M.get_change_nums(content) - next_line_changes = change_nums - new_line_num = new_line_num + 1 - end - - if next_line_changes == nil then - vim.notify("Could not find next line change information", vim.log.levels.ERROR) - return - end - - local result = { file_name = file_name } - -- This is actually a modified line if these conditions are met - if - current_line_changes.old_line - and not current_line_changes.new_line - and not next_line_changes.old_line - and next_line_changes.new_line - then - result.old_line = current_line_changes.old - result.new_line = next_line_changes.new_line - else - vim.notify("Could not determine line location", vim.log.levels.ERROR) - return - end - - return result -end - --- Helper Functions 🤝 --- These functions are not exported and should be private --- to the delta reviewer, they are used to support the public functions -M.get_jump_location = function(file_name, new_line, old_line) - local range, error = M.get_review_buffer_range(file_name) - if error ~= nil then - return nil, error - end - if range == nil then - return nil, "Review buffer range could not be identified" - end - - local linnr = nil - - local lines = M.get_review_buffer_lines(range) - for _, line in ipairs(lines) do - local line_data = M.get_change_nums(line.line_content) - if line_data and old_line == line_data.old_line and new_line == line_data.new_line then - linnr = line.line_number - break - end - end - if linnr == nil then - return nil, "Could not find matching line" - end - return linnr, nil -end - -M.get_file_from_review_buffer = function(linenr) - for i = linenr, 0, -1 do - local line_content = u.get_line_content(M.bufnr, i) - if M.starts_with_file_symbol(line_content) then - local file_name = u.get_last_chunk(line_content) - return file_name - end - end -end - -M.get_change_nums = function(line) - local data, _ = line:match("(.-)" .. "│" .. "(.*)") - local line_data = {} - if data == nil then - return nil - end - - if data ~= nil and data ~= "" then - local old_line = u.trim(u.get_first_chunk(data, "[^" .. "⋮" .. "]+")) - local new_line = u.trim(u.get_last_chunk(data, "[^" .. "⋮" .. "]+")) - line_data.new_line = tonumber(new_line) - line_data.old_line = tonumber(old_line) - end - - if line_data.new_line == nil and line_data.old_line == nil then - return nil - end - - return line_data -end - -M.get_review_buffer_range = function(file_name) - if M.bufnr == nil then - return nil, "Delta reviewer must be initialized first" - end - local lines = vim.api.nvim_buf_get_lines(M.bufnr, 0, -1, false) - local start = nil - local stop = nil - - for i, line in ipairs(lines) do - if start ~= nil and stop ~= nil then - return { start, stop } - end - if M.starts_with_file_symbol(line) then - -- Check if the file name matches the node name - local delta_file_name = u.get_last_chunk(line) - if file_name == delta_file_name then - start = i - elseif start ~= nil then - stop = i - end - end - end - - -- We've reached the end of the file, set "stop" in case we already found start - stop = #lines - if start ~= nil and stop ~= nil then - return { start, stop } - end -end - -M.starts_with_file_symbol = function(line) - for _, substring in ipairs({ - state.settings.review_pane.delta.added_file, - state.settings.review_pane.delta.removed_file, - state.settings.review_pane.delta.modified_file, - }) do - if string.sub(line, 1, string.len(substring)) == substring then - return true - end - end - return false -end - -M.get_review_buffer_lines = function(review_buffer_range) - local lines = {} - for i = review_buffer_range[1], review_buffer_range[2], 1 do - local line_content = vim.api.nvim_buf_get_lines(M.bufnr, i - 1, i, false)[1] - if string.find(line_content, "⋮") then - table.insert(lines, { line_content = line_content, line_number = i }) - end - end - return lines -end - ---- This function is not supported for delta -M.get_lines = function() - vim.notify("Getting lines in delta is not supported yet", vim.log.levels.ERROR) - return nil -end -return M diff --git a/lua/gitlab/reviewer/diffview.lua b/lua/gitlab/reviewer/diffview.lua index f53d0ee..6c4ff23 100644 --- a/lua/gitlab/reviewer/diffview.lua +++ b/lua/gitlab/reviewer/diffview.lua @@ -1,4 +1,4 @@ --- This Module contains all of the code specific to the Diffview reviewer. +-- This Module contains all of the reviewer code for diffview local u = require("gitlab.utils") local state = require("gitlab.state") local async_ok, async = pcall(require, "diffview.async") @@ -8,10 +8,6 @@ local M = { tabnr = nil, } --- Public Functions --- These functions are exposed externally and are used --- when the reviewer is consumed by other code. They must follow the specification --- outlined in the reviewer/init.lua file M.open = function() vim.api.nvim_command(string.format("DiffviewOpen %s", state.INFO.target_branch)) M.tabnr = vim.api.nvim_get_current_tabpage() @@ -19,14 +15,14 @@ end M.jump = function(file_name, new_line, old_line) if M.tabnr == nil then - vim.notify("Can't jump to Diffvew. Is it open?", vim.log.levels.ERROR) + u.notify("Can't jump to Diffvew. Is it open?", vim.log.levels.ERROR) return end vim.api.nvim_set_current_tabpage(M.tabnr) vim.cmd("DiffviewFocusFiles") local view = require("diffview.lib").get_current_view() if view == nil then - vim.notify("Could not find Diffview view", vim.log.levels.ERROR) + u.notify("Could not find Diffview view", vim.log.levels.ERROR) return end local files = view.panel:ordered_file_list() @@ -34,7 +30,7 @@ M.jump = function(file_name, new_line, old_line) for _, file in ipairs(files) do if file.path == file_name then if not async_ok then - vim.notify("Could not load Diffview async", vim.log.levels.ERROR) + u.notify("Could not load Diffview async", vim.log.levels.ERROR) return end async.await(view:set_file(file)) @@ -56,7 +52,7 @@ end ---@return ReviewerInfo | nil nil is returned only if error was encountered M.get_location = function(range) if M.tabnr == nil then - vim.notify("Diffview reviewer must be initialized first") + u.notify("Diffview reviewer must be initialized first") return end local bufnr = vim.api.nvim_get_current_buf() @@ -65,14 +61,14 @@ M.get_location = function(range) -- check if we are in the diffview tab local tabnr = vim.api.nvim_get_current_tabpage() if tabnr ~= M.tabnr then - vim.notify("Line location can only be determined within reviewer window") + u.notify("Line location can only be determined within reviewer window") return end -- check if we are in the diffview buffer local view = require("diffview.lib").get_current_view() if view == nil then - vim.notify("Could not find Diffview view", vim.log.levels.ERROR) + u.notify("Could not find Diffview view", vim.log.levels.ERROR) return end local layout = view.cur_layout @@ -90,13 +86,13 @@ M.get_location = function(range) type = "new" is_new = true else - vim.notify("Line location can only be determined within reviewer window") + u.notify("Line location can only be determined within reviewer window") return end local hunks = u.parse_hunk_headers(result.file_name, state.INFO.target_branch) if hunks == nil then - vim.notify("Could not parse hunks", vim.log.levels.ERROR) + u.notify("Could not parse hunks", vim.log.levels.ERROR) return end diff --git a/lua/gitlab/reviewer/init.lua b/lua/gitlab/reviewer/init.lua index 1cced8d..f2edc29 100644 --- a/lua/gitlab/reviewer/init.lua +++ b/lua/gitlab/reviewer/init.lua @@ -1,7 +1,4 @@ --- This Module will pick the reviewer set in the user's --- settings and then map all of it's functions local state = require("gitlab.state") -local delta = require("gitlab.reviewer.delta") local diffview = require("gitlab.reviewer.diffview") local M = { @@ -9,14 +6,16 @@ local M = { } local reviewer_map = { - delta = delta, diffview = diffview, } M.init = function() local reviewer = reviewer_map[state.settings.reviewer] if reviewer == nil then - vim.notify(string.format("gitlab.nvim could not find reviewer %s", state.settings.reviewer), vim.log.levels.ERROR) + vim.notify( + string.format("gitlab.nvim could not find reviewer %s, only diffview is supported", state.settings.reviewer), + vim.log.levels.ERROR + ) return end diff --git a/lua/gitlab/server.lua b/lua/gitlab/server.lua index 6144b8e..a7f6eb5 100644 --- a/lua/gitlab/server.lua +++ b/lua/gitlab/server.lua @@ -48,7 +48,7 @@ M.start = function(callback) callback() callback_called = true elseif not callback_called then - vim.notify("Failed to parse server port", vim.log.levels.ERROR) + u.notify("Failed to parse server port", vim.log.levels.ERROR) end end, on_stderr = function(_, errors) @@ -60,18 +60,15 @@ M.start = function(callback) end if err_msg ~= "" then - vim.notify(err_msg, vim.log.levels.ERROR) + u.notify(err_msg, vim.log.levels.ERROR) end end, on_exit = function(job_id, exit_code) - vim.notify( - "Golang gitlab server exited: job_id: " .. job_id .. ", exit_code: " .. exit_code, - vim.log.levels.ERROR - ) + u.notify("Golang gitlab server exited: job_id: " .. job_id .. ", exit_code: " .. exit_code, vim.log.levels.ERROR) end, }) if job_id <= 0 then - vim.notify("Could not start gitlab.nvim binary", vim.log.levels.ERROR) + u.notify("Could not start gitlab.nvim binary", vim.log.levels.ERROR) end end @@ -96,7 +93,7 @@ M.build = function(override) local null = u.is_windows() and " >NUL" or " > /dev/null" local installCode = os.execute(command .. null) if installCode ~= 0 then - vim.notify("Could not install gitlab.nvim!", vim.log.levels.ERROR) + u.notify("Could not install gitlab.nvim!", vim.log.levels.ERROR) return false end return true diff --git a/lua/gitlab/state.lua b/lua/gitlab/state.lua index c4d98ba..6e778ec 100644 --- a/lua/gitlab/state.lua +++ b/lua/gitlab/state.lua @@ -11,7 +11,7 @@ M.settings = { port = nil, -- choose random port debug = { go_request = false, go_response = false }, log_path = (vim.fn.stdpath("cache") .. "/gitlab.nvim.log"), - reviewer = "delta", + reviewer = "diffview", attachment_dir = "", popup = { exit = "", @@ -33,13 +33,6 @@ M.settings = { resolved = "✓", unresolved = "", }, - review_pane = { - delta = { - added_file = "", - modified_file = "", - removed_file = "", - }, - }, pipeline = { created = "", pending = "", @@ -51,12 +44,6 @@ M.settings = { success = "✓", failed = "", }, - dialogue = { - focus_next = { "j", "", "" }, - focus_prev = { "k", "", "" }, - close = { "", "" }, - submit = { "", "" }, - }, go_server_running = false, is_gitlab_project = false, colors = { @@ -70,10 +57,35 @@ M.settings = { -- Merges user settings into the default settings, overriding them M.merge_settings = function(args) - if args == nil then - return - end M.settings = u.merge(M.settings, args) + + -- Check deprecated settings and alert users! + if M.settings.dialogue ~= nil then + u.notify("The dialogue field has been deprecated, please remove it from your setup function", vim.log.levels.WARN) + end + + if M.settings.reviewer == "delta" then + u.notify( + "Delta is no longer a supported reviewer, please use diffview and update your setup function", + vim.log.levels.ERROR + ) + return false + end + + local diffview_ok, _ = pcall(require, "diffview") + if not diffview_ok then + u.notify("Please install diffview, it is required") + return false + end + + if M.settings.review_pane ~= nil then + u.notify( + "The review_pane field is only relevant for Delta, which has been deprecated, please remove it from your setup function", + vim.log.levels.WARN + ) + end + + return true end M.print_settings = function() diff --git a/lua/gitlab/utils/init.lua b/lua/gitlab/utils/init.lua index 2fcffa7..abb3f01 100644 --- a/lua/gitlab/utils/init.lua +++ b/lua/gitlab/utils/init.lua @@ -1,6 +1,10 @@ local Job = require("plenary.job") local M = {} +M.notify = function(msg, lvl) + vim.notify("gitlab.nvim: " .. msg, lvl) +end + M.get_colors_for_group = function(group) local normal_fg = vim.fn.synIDattr(vim.fn.synIDtrans((vim.fn.hlID(group))), "fg") local normal_bg = vim.fn.synIDattr(vim.fn.synIDtrans((vim.fn.hlID(group))), "bg") @@ -11,20 +15,6 @@ M.get_current_line_number = function() return vim.api.nvim_call_function("line", { "." }) end -M.has_reviewer = function(reviewer) - if reviewer == "diffview" then - local diffview_ok, _ = pcall(require, "diffview") - if not diffview_ok then - error("Please install diffview or change your reviewer") - end - else - local has_reviewer = vim.fn.executable("delta") == 1 - if not has_reviewer then - error(string.format("Please install delta or change your reviewer", reviewer)) - end - end -end - M.is_windows = function() if vim.fn.has("win32") == 1 or vim.fn.has("win32unix") == 1 then return true @@ -350,7 +340,7 @@ M.parse_hunk_headers = function(file_path, base_branch) end end else - vim.notify("Failed to get git diff: " .. j:stderr(), vim.log.levels.WARN) + M.notify("Failed to get git diff: " .. j:stderr(), vim.log.levels.WARN) end end, }) @@ -444,7 +434,7 @@ end M.check_visual_mode = function() local mode = vim.api.nvim_get_mode().mode if mode ~= "v" and mode ~= "V" then - vim.notify("Code suggestions are only available in visual mode", vim.log.levels.WARN) + M.notify("Code suggestions are only available in visual mode", vim.log.levels.WARN) return false end return true