diff --git a/lua/precognition/ffi.lua b/lua/precognition/ffi.lua deleted file mode 100644 index 06528ef..0000000 --- a/lua/precognition/ffi.lua +++ /dev/null @@ -1,29 +0,0 @@ -local M = {} - ----@return ffi.namespace* -function M.load() - if not _G.precog_C then - local ffi = require("ffi") - local ok, err = pcall( - ffi.cdef, - [[ - int utf_class(const int c); - ]] - ) - ---@diagnostic disable-next-line: need-check-nil - if not ok then - error(err) - end - _G.precog_C = ffi.C - end - return _G.precog_C -end - -return setmetatable(M, { - __index = function(_, key) - return M.load()[key] - end, - __newindex = function(_, k, v) - M.load()[k] = v - end, -}) diff --git a/lua/precognition/horizontal_motions.lua b/lua/precognition/horizontal_motions.lua index 2e57ab7..40df541 100644 --- a/lua/precognition/horizontal_motions.lua +++ b/lua/precognition/horizontal_motions.lua @@ -69,7 +69,8 @@ function M.end_of_word(str, cursorcol, linelen, big_word) local rev_offset if - (c_class == cc.other and next_char_class ~= cc.other) or (next_char_class == cc.other and c_class ~= cc.other) + (c_class == cc.punctuation and next_char_class ~= cc.punctuation) + or (next_char_class == cc.punctuation and c_class ~= cc.punctuation) then offset = offset + 1 char = vim.fn.strcharpart(str, offset - 1, 1) @@ -132,7 +133,7 @@ function M.prev_word_boundary(str, cursorcol, linelen, big_word) while utils.char_class(char, big_word) == c_class and offset >= 0 do offset = offset - 1 char = vim.fn.strcharpart(str, offset - 1, 1) - --if remaining string is whitespace, return nil_wrap + --if remaining string is whitespace, return 0 local remaining = string.sub(str, offset) if remaining:match("^%s*$") and #remaining > 0 then return 0 diff --git a/lua/precognition/utils.lua b/lua/precognition/utils.lua index c01d5fc..256ee9a 100644 --- a/lua/precognition/utils.lua +++ b/lua/precognition/utils.lua @@ -3,28 +3,32 @@ local M = {} ---@enum cc M.char_classes = { whitespace = 0, - other = 1, + punctuation = 1, word = 2, emoji = 3, + other = "other", + UNKNOWN = -1, } ---@param char string ---@param big_word boolean ----@return integer +---@return cc function M.char_class(char, big_word) assert(type(big_word) == "boolean", "big_word must be a boolean") local cc = M.char_classes - local byte = string.byte(char) - if byte == nil then - return cc.other + + if char == "" then + return cc.UNKNOWN end - if char == " " or char == "\t" or char == "\0" then + + if char == "\0" then return cc.whitespace end - local c_class = require("precognition.ffi").utf_class(byte) + local c_class = vim.fn.charclass(char) + if big_word and c_class ~= 0 then - return cc.other + return cc.punctuation end return c_class diff --git a/tests/precognition/char_spec.lua b/tests/precognition/char_spec.lua index c45a107..2826fe9 100644 --- a/tests/precognition/char_spec.lua +++ b/tests/precognition/char_spec.lua @@ -6,8 +6,11 @@ local eq = assert.are.same describe("static classes", function() it("are set correctly", function() eq(cc.whitespace, 0) - eq(cc.other, 1) + eq(cc.punctuation, 1) eq(cc.word, 2) + eq(cc.emoji, 3) + eq(cc.other, "other") + eq(cc.UNKNOWN, -1) end) end) @@ -30,6 +33,17 @@ describe("char classing", function() eq(utils.char_class("@", false), 1) eq(utils.char_class(".", false), 1) end) + + it("can class emoji characters", function() + eq(utils.char_class("🐱", false), 3) + eq(utils.char_class("😸", false), 3) + eq(utils.char_class("💩", false), 3) + end) + + it("can class nerdfont characters", function() + eq(utils.char_class("", false), 2) + eq(utils.char_class("", false), 2) + end) end) describe("big_word classing", function() @@ -51,17 +65,6 @@ describe("big_word classing", function() eq(utils.char_class("@", true), 1) eq(utils.char_class(".", true), 1) end) - - it("can class emoji characters", function() - eq(utils.char_class("🐱", false), 2) - eq(utils.char_class("😸", false), 2) - eq(utils.char_class("💩", false), 2) - end) - - it("can class nerdfont characters", function() - eq(utils.char_class("", false), 2) - eq(utils.char_class("", false), 2) - end) end) describe("pad arrays", function() diff --git a/tests/precognition/horizontal_motions_spec.lua b/tests/precognition/horizontal_motions_spec.lua index dfc28b9..42877ff 100644 --- a/tests/precognition/horizontal_motions_spec.lua +++ b/tests/precognition/horizontal_motions_spec.lua @@ -109,6 +109,9 @@ describe("boundaries", function() local str = "a big.word string" eq(3, hm.prev_word_boundary(str, 10, #str, true)) eq(3, hm.prev_word_boundary(str, 10, #str, true)) + + str = "big.word" + eq(1, hm.prev_word_boundary(str, 5, #str, true)) end) it("can walk string with b", function()