This MR adds the ability to sort discussions by file name, rather than just by date. This is an optional configuration that can be passed in on startup. The MR also introduces a test suite for the Lua code that runs through Neovim, so that the plugin can be fully tested with required dependencies and APIs. Major props to @johnybx for the hard work on this change!
260 lines
7.4 KiB
Lua
260 lines
7.4 KiB
Lua
-- This module is responsible for holding and setting shared state between
|
|
-- modules, such as keybinding data and other settings and configuration.
|
|
-- This module is also responsible for ensuring that the state of the plugin
|
|
-- is valid via dependencies
|
|
|
|
local u = require("gitlab.utils")
|
|
local M = {}
|
|
|
|
-- These are the default settings for the plugin
|
|
M.settings = {
|
|
port = nil, -- choose random port
|
|
debug = { go_request = false, go_response = false },
|
|
log_path = (vim.fn.stdpath("cache") .. "/gitlab.nvim.log"),
|
|
config_path = nil,
|
|
reviewer = "diffview",
|
|
attachment_dir = "",
|
|
popup = {
|
|
exit = "<Esc>",
|
|
perform_action = "<leader>s",
|
|
perform_linewise_action = "<leader>l",
|
|
},
|
|
discussion_tree = {
|
|
blacklist = {},
|
|
jump_to_file = "o",
|
|
jump_to_reviewer = "m",
|
|
edit_comment = "e",
|
|
delete_comment = "dd",
|
|
reply = "r",
|
|
toggle_node = "t",
|
|
toggle_resolved = "p",
|
|
relative = "editor",
|
|
position = "left",
|
|
size = "20%",
|
|
resolved = "✓",
|
|
unresolved = "",
|
|
tree_type = "simple",
|
|
},
|
|
info = {
|
|
enabled = true,
|
|
horizontal = false,
|
|
fields = {
|
|
"author",
|
|
"created_at",
|
|
"updated_at",
|
|
"merge_status",
|
|
"draft",
|
|
"conflicts",
|
|
"assignees",
|
|
"reviewers",
|
|
"branch",
|
|
"pipeline",
|
|
},
|
|
},
|
|
discussion_sign_and_diagnostic = {
|
|
skip_resolved_discussion = false,
|
|
skip_old_revision_discussion = false,
|
|
},
|
|
discussion_sign = {
|
|
-- See :h sign_define for details about sign configuration.
|
|
enabled = true,
|
|
text = "💬",
|
|
linehl = nil,
|
|
texthl = nil,
|
|
culhl = nil,
|
|
numhl = nil,
|
|
priority = 20,
|
|
helper_signs = {
|
|
-- For multiline comments the helper signs are used to indicate the whole context
|
|
-- Priority of helper signs is lower than the main sign (-1).
|
|
enabled = true,
|
|
start = "↑",
|
|
mid = "|",
|
|
["end"] = "↓",
|
|
},
|
|
},
|
|
discussion_diagnostic = {
|
|
-- If you want to customize diagnostics for discussions you can make special config
|
|
-- for namespace `gitlab_discussion`. See :h vim.diagnostic.config
|
|
enabled = true,
|
|
severity = vim.diagnostic.severity.INFO,
|
|
code = nil, -- see :h diagnostic-structure
|
|
display_opts = {}, -- this is dirrectly used as opts in vim.diagnostic.set, see :h vim.diagnostic.config.
|
|
},
|
|
pipeline = {
|
|
created = "",
|
|
pending = "",
|
|
preparing = "",
|
|
scheduled = "",
|
|
running = "ﰌ",
|
|
canceled = "ﰸ",
|
|
skipped = "ﰸ",
|
|
success = "✓",
|
|
failed = "",
|
|
},
|
|
go_server_running = false,
|
|
is_gitlab_project = false,
|
|
colors = {
|
|
discussion_tree = {
|
|
username = "Keyword",
|
|
date = "Comment",
|
|
chevron = "DiffviewNonText",
|
|
directory = "Directory",
|
|
directory_icon = "DiffviewFolderSign",
|
|
file_name = "Normal",
|
|
},
|
|
},
|
|
}
|
|
|
|
-- Merges user settings into the default settings, overriding them
|
|
M.merge_settings = function(args)
|
|
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
|
|
|
|
M.settings.file_separator = (u.is_windows() and "\\" or "/")
|
|
|
|
return true
|
|
end
|
|
|
|
M.print_settings = function()
|
|
vim.print(M.settings)
|
|
end
|
|
|
|
-- First reads environment variables into the settings module,
|
|
-- then attemps to read a `.gitlab.nvim` configuration file.
|
|
-- If after doing this, any variables are missing, alerts the user.
|
|
-- The `.gitlab.nvim` configuration file takes precedence.
|
|
M.setPluginConfiguration = function()
|
|
if M.initialized then
|
|
return true
|
|
end
|
|
|
|
local base_path
|
|
if M.settings.config_path ~= nil then
|
|
base_path = M.settings.config_path
|
|
else
|
|
base_path = vim.fn.trim(vim.fn.system({ "git", "rev-parse", "--show-toplevel" }))
|
|
if vim.v.shell_error ~= 0 then
|
|
u.notify(string.format("Could not get base directory: %s", base_path), vim.log.levels.ERROR)
|
|
return false
|
|
end
|
|
end
|
|
|
|
local config_file_path = base_path .. M.settings.file_separator .. ".gitlab.nvim"
|
|
local config_file_content = u.read_file(config_file_path)
|
|
|
|
local file_properties = {}
|
|
if config_file_content ~= nil then
|
|
local file = assert(io.open(config_file_path, "r"))
|
|
for line in file:lines() do
|
|
for key, value in string.gmatch(line, "(.-)=(.-)$") do
|
|
file_properties[key] = value
|
|
end
|
|
end
|
|
end
|
|
|
|
M.settings.auth_token = file_properties.auth_token or os.getenv("GITLAB_TOKEN")
|
|
M.settings.gitlab_url = file_properties.gitlab_url or os.getenv("GITLAB_URL") or "https://gitlab.com"
|
|
|
|
if M.settings.auth_token == nil then
|
|
vim.notify(
|
|
"Missing authentication token for Gitlab, please provide it as an environment variable or in the .gitlab.nvim file",
|
|
vim.log.levels.ERROR
|
|
)
|
|
return false
|
|
end
|
|
|
|
M.initialized = true
|
|
return true
|
|
end
|
|
|
|
local function exit(popup, cb)
|
|
popup:unmount()
|
|
if cb ~= nil then
|
|
cb()
|
|
end
|
|
end
|
|
|
|
-- These keymaps are buffer specific and are set dynamically when popups mount
|
|
M.set_popup_keymaps = function(popup, action, linewise_action, opts)
|
|
if opts == nil then
|
|
opts = {}
|
|
end
|
|
vim.keymap.set("n", M.settings.popup.exit, function()
|
|
exit(popup, opts.cb)
|
|
end, { buffer = popup.bufnr })
|
|
if action ~= nil then
|
|
vim.keymap.set("n", M.settings.popup.perform_action, function()
|
|
local text = u.get_buffer_text(popup.bufnr)
|
|
if opts.action_before_close then
|
|
action(text, popup.bufnr)
|
|
exit(popup)
|
|
else
|
|
exit(popup)
|
|
action(text, popup.bufnr)
|
|
end
|
|
end, { buffer = popup.bufnr })
|
|
end
|
|
|
|
if linewise_action ~= nil then
|
|
vim.keymap.set("n", M.settings.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 })
|
|
end
|
|
end
|
|
|
|
-- Dependencies
|
|
-- These tables are passed to the async.sequence function, which calls them in sequence
|
|
-- before calling an action. They are used to set global state that's required
|
|
-- for each of the actions to occur. This is necessary because some Gitlab behaviors (like
|
|
-- adding a reviewer) requires some initial state.
|
|
M.dependencies = {
|
|
info = { endpoint = "/info", key = "info", state = "INFO", refresh = false },
|
|
revisions = { endpoint = "/mr/revisions", key = "Revisions", state = "MR_REVISIONS", refresh = false },
|
|
project_members = {
|
|
endpoint = "/project/members",
|
|
key = "ProjectMembers",
|
|
state = "PROJECT_MEMBERS",
|
|
refresh = false,
|
|
},
|
|
}
|
|
|
|
-- This function clears out all of the previously fetched data. It's used
|
|
-- to reset the plugin state when the Go server is restarted
|
|
M.clear_data = function()
|
|
M.INFO = nil
|
|
for _, dep in ipairs(M.dependencies) do
|
|
M[dep.state] = nil
|
|
end
|
|
end
|
|
|
|
return M
|