diff --git a/neovim/lua/plugins.lua b/neovim/lua/plugins.lua index 9237da3..550838f 100644 --- a/neovim/lua/plugins.lua +++ b/neovim/lua/plugins.lua @@ -1,4 +1,5 @@ -- Install packer +local utils = require("utils") local install_path = vim.fn.stdpath("data") .. "/site/pack/packer/opt/packer.nvim" local packer_bootstrap = false if vim.fn.empty(vim.fn.glob(install_path)) > 0 then @@ -16,20 +17,6 @@ local function config_dark_notify() }) end --- Pin version dependent packages due to unstable APIs -local pinned_commits = {} -if vim.fn.has("nvim-0.6.0") ~= 1 then - if vim.fn.has("nvim-0.5.1") == 1 then - -- Last commit compatible with 0.5.1 - pinned_commits["telescope"] = "80cdb00b221f69348afc4fb4b701f51eb8dd3120" - pinned_commits["null-ls"] = "739a98c12bedaa2430c4a3c08d1d22ad6c16513e" - elseif vim.fn.has("nvim-0.5.0") == 1 then - -- Last commit compatible with 0.5.0 - pinned_commits["telescope"] = "587a10d1494d8ffa1229246228f0655db2f0a48a" - pinned_commits["null-ls"] = "3e7390735501d0507bf2c2b5c2e7a16f58deeb81" - end -end - return require("packer").startup({ function(use) -- Load things faster! @@ -214,7 +201,11 @@ return require("packer").startup({ -- Generic linter/formatters in diagnostics API use({ "jose-elias-alvarez/null-ls.nvim", - commit = pinned_commits["null-ls"], + commit = utils.map_version_rule({ + [">=0.6.0"] = nil, + [">=0.5.1"] = "739a98c12bedaa2430c4a3c08d1d22ad6c16513e", + [">=0.5.0"] = "3e7390735501d0507bf2c2b5c2e7a16f58deeb81", + }), requires = { "nvim-lua/plenary.nvim", "neovim/nvim-lspconfig" }, }) @@ -289,7 +280,11 @@ return require("packer").startup({ "nvim-lua/plenary.nvim", "nvim-lua/popup.nvim", }, - commit = pinned_commits["telescope"], + commit = utils.map_version_rule({ + [">=0.6.0"] = nil, + [">=0.5.1"] = "80cdb00b221f69348afc4fb4b701f51eb8dd3120", + [">=0.5.0"] = "587a10d1494d8ffa1229246228f0655db2f0a48a", + }), config = function() require("plugins.telescope") end, diff --git a/neovim/lua/utils.lua b/neovim/lua/utils.lua index 6eab2fe..4366851 100644 --- a/neovim/lua/utils.lua +++ b/neovim/lua/utils.lua @@ -116,4 +116,88 @@ function M.try_require(name, on_found, on_notfound) end end +-- Compare sequenced integers used to compare versions. Eg {0, 6, 0} +function M.cmp_versions(a, b) + for i, part_a in pairs(a) do + local part_b = b[i] + if part_b == nil or part_a > part_b then + return 1 + elseif part_a < part_b then + return -1 + end + end + + return 0 +end + +-- Checks if a list contains a value +function M.list_contains(list, value) + for _, v in pairs(list) do + if v == value then + return true + end + end + return false +end + +-- Materializes an iterator into a list +function M.materialize_list(list, iterator) + if iterator == nil then + iterator = list + list = {} + end + for item in iterator do + table.insert(list, item) + end + + return list +end + +-- Maps a set of version rules to a value eg. [">0.5.0"] = "has 0.5.0" +-- If more than one rule matches, the one with the greatest version number is used +function M.map_version_rule(rules) + local v = vim.version() + local current_version = { v.major, v.minor, v.patch } + + -- Parse a constraint and version of a string + local parse_rule = function(rule_string) + local cmp, major, minor, patch = string.gmatch(rule_string, "([=<>]+)(%d+).(%d+).(%d+)")() + return cmp, tonumber(major), tonumber(minor), tonumber(patch) + end + + -- Checks if a constraint matches the current nvim instance + local matches = function(cmp, major, minor, patch) + local c = M.cmp_versions(current_version, { major, minor, patch }) + if c == 1 then + if M.list_contains({ ">", ">=" }, cmp) then + return true + end + elseif c == 0 then + if M.list_contains({ "==", ">=", "<=" }, cmp) then + return true + end + elseif c == -1 then + if M.list_contains({ "<", "<=" }, cmp) then + return true + end + end + return false + end + + local latest_version, latest_value = nil, nil + for rule, value in pairs(rules) do + local cmp, major, minor, patch = parse_rule(rule) + if matches(cmp, major, minor, patch) then + -- If the rule matches and the version that it matches is greater than the previous matches, save it + if latest_version == nil or M.cmp_versions({ major, minor, patch }, latest_version) == 1 then + latest_version = { major, minor, patch } + latest_value = value + end + end + end + + -- Return highest versioned matched value + return latest_value +end + return M