From c1df54640ebad3a49f1a695444cdec46642f4309 Mon Sep 17 00:00:00 2001 From: nelsonacsg Date: Sat, 2 Aug 2025 17:29:29 +0800 Subject: [PATCH 1/5] port rust logic to lua --- lua/crates/semver.lua | 102 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 6 deletions(-) diff --git a/lua/crates/semver.lua b/lua/crates/semver.lua index 2035033..e59ffc5 100644 --- a/lua/crates/semver.lua +++ b/lua/crates/semver.lua @@ -200,22 +200,112 @@ function M.parse_requirements(str) return requirements end --- TODO: port https://github.com/dtolnay/semver/blob/master/src%2Fimpls.rs#L51-L107 ---@param version? string ---@param req? string ---@return integer function M.compare_pre(version, req) - if version and req then - if version < req then + -- Handle identical strings (optimization) + if version == req then + return 0 + end + + -- Handle empty prerelease cases + local version_empty = not version or version == "" + local req_empty = not req or req == "" + + if version_empty and req_empty then + return 0 + elseif version_empty then + -- A real release compares greater than prerelease + return 1 + elseif req_empty then + -- Prerelease compares less than the real release + return -1 + end + + -- Both are non-empty prerelease strings, compare them + ---@param str string + ---@return string[] + local function split_identifiers(str) + local parts = {} + for part in str:gmatch("[^%.]+") do + table.insert(parts, part) + end + return parts + end + + ---@param str string + ---@return boolean + local function is_numeric(str) + return str:match("^%d+$") ~= nil + end + + ---@param a string + ---@param b string + ---@return integer + local function compare_numeric_strings(a, b) + -- First compare by length (shorter number is smaller) + local len_cmp = #a - #b + if len_cmp ~= 0 then + return len_cmp + end + -- If same length, compare lexically + if a < b then return -1 - elseif version == req then + elseif a > b then + return 1 + else return 0 - elseif version > req then + end + end + + local version_parts = version and split_identifiers(version) or {} + local req_parts = req and split_identifiers(req) or {} + + local max_len = math.max(#version_parts, #req_parts) + + for i = 1, max_len do + local version_part = version_parts[i] + local req_part = req_parts[i] + + -- If one side has no more parts, the longer one is greater + if not version_part then + return -1 + elseif not req_part then return 1 end + + local version_numeric = is_numeric(version_part) + local req_numeric = is_numeric(req_part) + + ---@type integer + local cmp + if version_numeric and req_numeric then + -- Both numeric: compare numerically + cmp = compare_numeric_strings(version_part, req_part) + elseif version_numeric and not req_numeric then + -- Numeric has lower precedence than non-numeric + cmp = -1 + elseif not version_numeric and req_numeric then + -- Non-numeric has higher precedence than numeric + cmp = 1 + else + -- Both non-numeric: compare lexically + if version_part < req_part then + cmp = -1 + elseif version_part > req_part then + cmp = 1 + else + cmp = 0 + end + end + + if cmp ~= 0 then + return cmp + end end - return (req and 1 or 0) - (version and 1 or 0) + return 0 end -- TODO: port https://github.com/dtolnay/semver/blob/master/src/impls.rs#L109-L153 From 7f9729ed55421afebee60a5ddf4421ff55a034a5 Mon Sep 17 00:00:00 2001 From: nelsonacsg Date: Sat, 2 Aug 2025 18:05:45 +0800 Subject: [PATCH 2/5] remove comment --- lua/crates/semver.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/crates/semver.lua b/lua/crates/semver.lua index e59ffc5..cdc162d 100644 --- a/lua/crates/semver.lua +++ b/lua/crates/semver.lua @@ -223,7 +223,6 @@ function M.compare_pre(version, req) return -1 end - -- Both are non-empty prerelease strings, compare them ---@param str string ---@return string[] local function split_identifiers(str) From 3521c2fe37c3453274686e5b4791070d5efacba0 Mon Sep 17 00:00:00 2001 From: nelsonacsg Date: Sat, 2 Aug 2025 20:54:42 +0800 Subject: [PATCH 3/5] replace with vim.split --- lua/crates/semver.lua | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/lua/crates/semver.lua b/lua/crates/semver.lua index cdc162d..3719662 100644 --- a/lua/crates/semver.lua +++ b/lua/crates/semver.lua @@ -223,16 +223,6 @@ function M.compare_pre(version, req) return -1 end - ---@param str string - ---@return string[] - local function split_identifiers(str) - local parts = {} - for part in str:gmatch("[^%.]+") do - table.insert(parts, part) - end - return parts - end - ---@param str string ---@return boolean local function is_numeric(str) @@ -258,8 +248,8 @@ function M.compare_pre(version, req) end end - local version_parts = version and split_identifiers(version) or {} - local req_parts = req and split_identifiers(req) or {} + local version_parts = version and vim.split(version, ".") or {} + local req_parts = req and vim.split(req, ".") or {} local max_len = math.max(#version_parts, #req_parts) From 8c60f6a9aa841733115dad61b7e58163910e4bb0 Mon Sep 17 00:00:00 2001 From: nelsonacsg Date: Sat, 2 Aug 2025 21:03:44 +0800 Subject: [PATCH 4/5] revert vim.split changes --- lua/crates/semver.lua | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lua/crates/semver.lua b/lua/crates/semver.lua index 3719662..cdc162d 100644 --- a/lua/crates/semver.lua +++ b/lua/crates/semver.lua @@ -223,6 +223,16 @@ function M.compare_pre(version, req) return -1 end + ---@param str string + ---@return string[] + local function split_identifiers(str) + local parts = {} + for part in str:gmatch("[^%.]+") do + table.insert(parts, part) + end + return parts + end + ---@param str string ---@return boolean local function is_numeric(str) @@ -248,8 +258,8 @@ function M.compare_pre(version, req) end end - local version_parts = version and vim.split(version, ".") or {} - local req_parts = req and vim.split(req, ".") or {} + local version_parts = version and split_identifiers(version) or {} + local req_parts = req and split_identifiers(req) or {} local max_len = math.max(#version_parts, #req_parts) From 8d64f7ae20a18b10f46f5075e56440e150b88201 Mon Sep 17 00:00:00 2001 From: nelsonacsg Date: Sat, 2 Aug 2025 21:33:22 +0800 Subject: [PATCH 5/5] vim.split with escape char --- lua/crates/semver.lua | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/lua/crates/semver.lua b/lua/crates/semver.lua index cdc162d..a52b48c 100644 --- a/lua/crates/semver.lua +++ b/lua/crates/semver.lua @@ -223,16 +223,6 @@ function M.compare_pre(version, req) return -1 end - ---@param str string - ---@return string[] - local function split_identifiers(str) - local parts = {} - for part in str:gmatch("[^%.]+") do - table.insert(parts, part) - end - return parts - end - ---@param str string ---@return boolean local function is_numeric(str) @@ -258,8 +248,8 @@ function M.compare_pre(version, req) end end - local version_parts = version and split_identifiers(version) or {} - local req_parts = req and split_identifiers(req) or {} + local version_parts = version and vim.split(version, "%.") or {} + local req_parts = req and vim.split(req, "%.") or {} local max_len = math.max(#version_parts, #req_parts)