Skip to content

Commit

Permalink
fix(horizontal_motions): edge cases around end words
Browse files Browse the repository at this point in the history
  • Loading branch information
tris203 committed Jan 14, 2025
1 parent 35a76ac commit 24f2cc5
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 11 deletions.
26 changes: 15 additions & 11 deletions lua/precognition/horizontal_motions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ end
---@param cursorcol integer
---@param linelen integer
---@param big_word boolean
---@param recursive boolean?
---@return Precognition.PlaceLoc
function M.end_of_word(str, cursorcol, linelen, big_word)
function M.end_of_word(str, cursorcol, linelen, big_word, recursive)
if cursorcol >= linelen then
return 0
end
Expand All @@ -83,15 +84,18 @@ function M.end_of_word(str, cursorcol, linelen, big_word)
local c_class = utils.char_class(char, big_word)
local next_char_class = utils.char_class(vim.fn.strcharpart(str, (offset - 1) + 1, 1), big_word)
local rev_offset

if
(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)
c_class = utils.char_class(char, big_word)
next_char_class = utils.char_class(vim.fn.strcharpart(str, (offset - 1) + 1, 1), big_word)
if not recursive then
if
(c_class == cc.punctuation and next_char_class ~= cc.punctuation)
or (next_char_class == cc.punctuation and c_class ~= cc.punctuation)
or (c_class == cc.emoji and next_char_class ~= cc.emoji)
or (next_char_class == cc.emoji and c_class ~= cc.emoji)
then
offset = offset + 1
char = vim.fn.strcharpart(str, offset - 1, 1)
c_class = utils.char_class(char, big_word)
next_char_class = utils.char_class(vim.fn.strcharpart(str, (offset - 1) + 1, 1), big_word)
end
end

if c_class ~= cc.whitespace and next_char_class ~= cc.whitespace then
Expand All @@ -113,7 +117,7 @@ function M.end_of_word(str, cursorcol, linelen, big_word)
--next word starts with punctuation
rev_offset = next_word_start
else
rev_offset = M.end_of_word(str, next_word_start, linelen, big_word)
rev_offset = M.end_of_word(str, next_word_start, linelen, big_word, true)
end
end
end
Expand Down
16 changes: 16 additions & 0 deletions tests/precognition/horizontal_motions_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -317,11 +317,27 @@ describe("edge case", function()
eq(3, hm.prev_word_boundary(str, 5, len, false))
end)

it("multibyte end_of_word", function()
local str = "# 💭👀precognition.nvim"
local len = vim.fn.strcharlen(str)
eq(4, hm.end_of_word(str, 1, len, false))
eq(16, hm.end_of_word(str, 4, len, false))

str = "🌞7😘aa"
len = vim.fn.strcharlen(str)
eq(3, hm.end_of_word(str, 2, len, false))
end)

it("quoted strings", function()
local str = 'this = "that"'
eq(8, hm.end_of_word(str, 6, #str, false))

str = 'b = "^", c = 2 },'
eq(8, hm.end_of_word(str, 3, #str, false))
end)

it("end of words with specials", function()
local str = "b t~a"
eq(3, hm.end_of_word(str, 1, #str, false))
end)
end)

0 comments on commit 24f2cc5

Please sign in to comment.