aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/range.lua
diff options
context:
space:
mode:
authorYi Ming <ofseed@foxmail.com>2026-05-18 17:08:19 +0800
committerYi Ming <ofseed@foxmail.com>2026-05-18 22:19:00 +0800
commitf2b031136ff607866a9ab7933408aa86eb8b99a7 (patch)
treeae9ffff11560da8119057376c41ff4352e544f66 /runtime/lua/vim/range.lua
parentd7164eced6d6dc363eaee0c47538c5ff6552e3ba (diff)
downloadrneovim-f2b031136ff607866a9ab7933408aa86eb8b99a7.tar.gz
rneovim-f2b031136ff607866a9ab7933408aa86eb8b99a7.tar.bz2
rneovim-f2b031136ff607866a9ab7933408aa86eb8b99a7.zip
feat(pos,range): pos:to_mark(), pos.mark(), range:to_mark(), range.mark()
Problem: Ranges represented by marks are usually end-inclusive, but the range utilities we provided are end-exclusive. Solution: Add pos:to_mark(), pos.mark(), range:to_mark(), and range.mark().
Diffstat (limited to 'runtime/lua/vim/range.lua')
-rw-r--r--runtime/lua/vim/range.lua76
1 files changed, 76 insertions, 0 deletions
diff --git a/runtime/lua/vim/range.lua b/runtime/lua/vim/range.lua
index f50aff60b4..dd22d1151e 100644
--- a/runtime/lua/vim/range.lua
+++ b/runtime/lua/vim/range.lua
@@ -160,6 +160,21 @@ local function to_inclusive_pos(buf, row, col)
return row, col
end
+---@param row integer
+---@param col integer
+---@param buf integer
+---@return integer, integer
+local function to_exclusive_pos(buf, row, col)
+ if col >= #get_line(buf, row) then
+ row = row + 1
+ col = 0
+ else
+ col = col + 1
+ end
+
+ return row, col
+end
+
---@private
---@param r1 vim.Range
---@param r2 vim.Range
@@ -320,6 +335,67 @@ end
--- ```lua
--- local range = vim.range(0, 3, 5, 4, 0)
---
+--- -- Convert to mark range, you can call it in a method style.
+--- local start_row, start_col, end_row, end_col = range:to_mark()
+--- ```
+---@param range vim.Range
+---@return integer, integer, integer, integer
+function M.to_mark(range)
+ validate('range', range, 'table')
+
+ local buf = range.buf
+ local start_row, start_col, end_row, end_col = range[1], range[2], range[3], range[4]
+ if vim.o.selection ~= 'exclusive' then
+ end_row, end_col = to_inclusive_pos(buf, end_row, end_col)
+ end
+
+ start_row, start_col = vim.pos(buf, start_row, start_col):to_mark()
+ end_row, end_col = vim.pos(buf, end_row, end_col):to_mark()
+ return start_row, start_col, end_row, end_col
+end
+
+--- Creates a new |vim.Range| from "mark-indexed" range (see |api-indexing|).
+---
+--- Example:
+--- ```lua
+--- -- A range represented by marks may be end-inclusive (decided by 'selection' option).
+--- local start_row, start_col = unpack(api.nvim_buf_get_mark(bufnr, '<'))
+--- local end_row, end_col = unpack(api.nvim_buf_get_mark(bufnr, '>'))
+---
+--- -- Create an end-exclusive range.
+--- local range = vim.range.mark(0, start_row, start_col, end_row, end_col)
+--- ```
+---@param buf integer
+---@param start_row integer
+---@param start_col integer
+---@param end_row integer
+---@param end_col integer
+function M.mark(buf, start_row, start_col, end_row, end_col)
+ validate('buf', buf, 'number')
+ validate('start_row', start_row, 'number')
+ validate('start_col', start_col, 'number')
+ validate('end_row', end_row, 'number')
+ validate('end_col', end_col, 'number')
+
+ if buf == 0 then
+ buf = api.nvim_get_current_buf()
+ end
+
+ local start = vim.pos.mark(buf, start_row, start_col)
+ local end_ = vim.pos.mark(buf, end_row, end_col)
+
+ if vim.o.selection ~= 'exclusive' then
+ end_[1], end_[2] = to_exclusive_pos(buf, end_[1], end_[2])
+ end
+ return M.new(start, end_)
+end
+
+--- Converts |vim.Range| to extmark range (see |api-indexing|).
+---
+--- Example:
+--- ```lua
+--- local range = vim.range(0, 3, 5, 4, 0)
+---
--- -- Convert to extmark range, you can call it in a method style.
--- local extmark_range = range:to_extmark()
--- ```