mirror of
https://github.com/neovim/neovim.git
synced 2026-05-23 21:30:11 +00:00
feat(pos): pos:to_offset(), pos.offset() #39564
Problem:
For a given position, it is not easy to compare which of several other positions is closest to it.
Solution:
Add support for converting `vim.Pos` to a buffer byte offset.
This allows for sorting, e.g:
```lua
table.sort(positions, function(pos1, pos2)
return pos1:to_offset() < pos2:to_offset()
end
```
Or a binary search, e.g:
```lua
vim.list.bisect(positions, pos, { key = function(pos) return pos:to_offset() end })
```
This commit is contained in:
@@ -225,6 +225,33 @@ function M.extmark(buf, row, col)
|
||||
return M.new(buf, row, col)
|
||||
end
|
||||
|
||||
--- Converts |vim.Pos| to buffer offset.
|
||||
---@param pos vim.Pos
|
||||
---@return integer
|
||||
function M.to_offset(pos)
|
||||
return api.nvim_buf_get_offset(pos.buf, pos[1]) + pos[2]
|
||||
end
|
||||
|
||||
--- Creates a new |vim.Pos| from buffer offset.
|
||||
---@param buf integer
|
||||
---@param offset integer
|
||||
---@return vim.Pos
|
||||
function M.offset(buf, offset)
|
||||
local lnum = vim.list.bisect(
|
||||
setmetatable({}, {
|
||||
__index = function(_, lnum)
|
||||
return api.nvim_buf_get_offset(buf, lnum - 1)
|
||||
end,
|
||||
}),
|
||||
offset,
|
||||
{ lo = 1, hi = api.nvim_buf_line_count(buf) + 2, bound = 'upper' }
|
||||
) - 1
|
||||
|
||||
local row = lnum - 1
|
||||
local col = offset - api.nvim_buf_get_offset(buf, row)
|
||||
return M.new(buf, row, col)
|
||||
end
|
||||
|
||||
-- Overload `Range.new` to allow calling this module as a function.
|
||||
setmetatable(M, {
|
||||
__call = function(_, ...)
|
||||
|
||||
Reference in New Issue
Block a user