diff options
| author | Yi Ming <ofseed@foxmail.com> | 2026-05-18 17:08:19 +0800 |
|---|---|---|
| committer | Yi Ming <ofseed@foxmail.com> | 2026-05-18 22:19:00 +0800 |
| commit | f2b031136ff607866a9ab7933408aa86eb8b99a7 (patch) | |
| tree | ae9ffff11560da8119057376c41ff4352e544f66 /runtime/lua/vim/range.lua | |
| parent | d7164eced6d6dc363eaee0c47538c5ff6552e3ba (diff) | |
| download | rneovim-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.lua | 76 |
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() --- ``` |