Skip to content

Commit

Permalink
Merge branch 'main' into percent_motion
Browse files Browse the repository at this point in the history
  • Loading branch information
tris203 authored May 17, 2024
2 parents bd3bc8b + d895349 commit 3ca9e71
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 12 deletions.
19 changes: 11 additions & 8 deletions lua/precognition/horizontal_motions.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local utils = require("precognition.utils")
local cc = utils.char_classes

local M = {}

Expand Down Expand Up @@ -34,14 +35,14 @@ function M.next_word_boundary(str, cursorcol, _linelen)
local char = vim.fn.strcharpart(str, offset - 1, 1)
local c_class = utils.char_class(char)

if c_class ~= 0 then
if c_class ~= cc.whitespace then
while utils.char_class(char) == c_class and offset <= len do
offset = offset + 1
char = vim.fn.strcharpart(str, offset - 1, 1)
end
end

while utils.char_class(char) == 0 and offset <= len do
while utils.char_class(char) == cc.whitespace and offset <= len do
offset = offset + 1
char = vim.fn.strcharpart(str, offset - 1, 1)
end
Expand All @@ -66,26 +67,28 @@ function M.end_of_word(str, cursorcol, linelen)
local next_char_class = utils.char_class(vim.fn.strcharpart(str, (offset - 1) + 1, 1))
local rev_offset

if (c_class == 1 and next_char_class ~= 1) or (next_char_class == 1 and c_class ~= 1) then
if
(c_class == cc.other and next_char_class ~= cc.other) or (next_char_class == cc.other and c_class ~= cc.other)
then
offset = offset + 1
char = vim.fn.strcharpart(str, offset - 1, 1)
c_class = utils.char_class(char)
next_char_class = utils.char_class(vim.fn.strcharpart(str, (offset - 1) + 1, 1))
end

if c_class ~= 0 and next_char_class ~= 0 then
if c_class ~= cc.whitespace and next_char_class ~= cc.whitespace then
while utils.char_class(char) == c_class and offset <= linelen do
offset = offset + 1
char = vim.fn.strcharpart(str, offset - 1, 1)
end
end

if c_class == 0 or next_char_class == 0 then
if c_class == cc.whitespace or next_char_class == cc.whitespace then
local next_word_start = M.next_word_boundary(str, cursorcol, linelen)
if next_word_start then
next_char_class = utils.char_class(vim.fn.strcharpart(str, (next_word_start - 1) + 1, 1))
--next word is single char
if next_char_class == 0 then
if next_char_class == cc.whitespace then
rev_offset = next_word_start
else
rev_offset = M.end_of_word(str, next_word_start, linelen)
Expand Down Expand Up @@ -117,8 +120,8 @@ function M.prev_word_boundary(str, cursorcol, _linelen)
local char = vim.fn.strcharpart(str, offset - 1, 1)
local c_class = utils.char_class(char)

if c_class == 0 then
while utils.char_class(char) == 0 and offset >= 0 do
if c_class == cc.whitespace then
while utils.char_class(char) == cc.whitespace and offset >= 0 do
offset = offset - 1
char = vim.fn.strcharpart(str, offset - 1, 1)
end
Expand Down
16 changes: 12 additions & 4 deletions lua/precognition/utils.lua
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
local M = {}

---@enum cc
M.char_classes = {
whitespace = 0,
other = 1,
word = 2,
}

---@param char string
---@return integer
function M.char_class(char)
local cc = M.char_classes
local byte = string.byte(char)

if byte and byte < 0x100 then
if char == " " or char == "\t" or char == "\0" then
return 0 -- whitespace
return cc.whitespace
end
if char == "_" or char:match("%w") then
return 2 -- word character
return cc.word
end
return 1 -- other
return cc.other
end

return 1 -- scary unicode edge cases go here
return cc.other -- scary unicode edge cases go here
end

---@param bufnr? integer
Expand Down
9 changes: 9 additions & 0 deletions tests/precognition/char_spec.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
local utils = require("precognition.utils")
local cc = utils.char_classes
---@diagnostic disable-next-line: undefined-field
local eq = assert.are.same

describe("static classes", function()
it("are set correctly", function()
eq(cc.whitespace, 0)
eq(cc.other, 1)
eq(cc.word, 2)
end)
end)

describe("char classing", function()
it("white space is classeed", function()
eq(utils.char_class(" "), 0)
Expand Down

0 comments on commit 3ca9e71

Please sign in to comment.