diff --git a/lua/data/func.lua b/lua/data/func.lua index 45b10cf..e0625fe 100644 --- a/lua/data/func.lua +++ b/lua/data/func.lua @@ -1777,5 +1777,57 @@ function M.convert_path(path) end end +function M.char_on_pos(pos) + pos = pos or vim.fn.getpos(".") + return tostring(vim.fn.getline(pos[1])):sub(pos[2], pos[2]) +end + +-- From: https://neovim.discourse.group/t/how-do-you-work-with-strings-with-multibyte-characters-in-lua/2437/4 +function M.char_byte_count(s, i) + if not s or s == "" then + return 1 + end + + local char = string.byte(s, i or 1) + + -- Get byte count of unicode character (RFC 3629) + if char > 0 and char <= 127 then + return 1 + elseif char >= 194 and char <= 223 then + return 2 + elseif char >= 224 and char <= 239 then + return 3 + elseif char >= 240 and char <= 244 then + return 4 + end +end + +function M.get_visual_range() + local sr, sc = unpack(vim.fn.getpos("v"), 2, 3) + local er, ec = unpack(vim.fn.getpos("."), 2, 3) + + -- To correct work with non-single byte chars + local byte_c = M.char_byte_count(M.char_on_pos({ er, ec })) + ec = ec + (byte_c - 1) + + local range = {} + + if sr == er then + local cols = sc >= ec and { ec, sc } or { sc, ec } + range = { sr, cols[1] - 1, er, cols[2] } + elseif sr > er then + range = { er, ec - 1, sr, sc } + else + range = { sr, sc - 1, er, ec } + end + + return range +end + +function M.to_api_range(range) + local sr, sc, er, ec = unpack(range) + return sr - 1, sc, er - 1, ec +end + -- Export the module return M