From 8ce1aac477a33ab1fe2a0b590ff278518dc0e473 Mon Sep 17 00:00:00 2001 From: Olivia Kinnear Date: Sun, 23 Aug 2026 06:13:41 -0500 Subject: [PATCH] feat(pos): mutable vim.Pos, vim.Range fields #41318 Allow plugins to set the human-readable fields. --- runtime/lua/vim/pos.lua | 22 ++++++++++++++++ runtime/lua/vim/range.lua | 42 +++++++++++++++++++++++++----- test/functional/lua/pos_spec.lua | 11 ++++++++ test/functional/lua/range_spec.lua | 13 +++++++++ 4 files changed, 81 insertions(+), 7 deletions(-) diff --git a/runtime/lua/vim/pos.lua b/runtime/lua/vim/pos.lua index 80ce0b6f9e..bb2e2a0597 100644 --- a/runtime/lua/vim/pos.lua +++ b/runtime/lua/vim/pos.lua @@ -55,6 +55,28 @@ function M.__index(pos, key) return M[key] end +---@private +---@param pos vim.Pos +---@param key any +---@param value any +function M.__newindex(pos, key, value) + if key == 'row' then + validate('row', value, 'number') + pos[1] = value + elseif key == 'col' then + validate('col', value, 'number') + pos[2] = value + elseif key == 'buf' then + validate('buf', value, 'number') + if value == 0 then + value = api.nvim_get_current_buf() + end + pos[3] = value + else + rawset(pos, key, value) + end +end + ---@package ---@param buf integer ---@param row integer diff --git a/runtime/lua/vim/range.lua b/runtime/lua/vim/range.lua index e8dd7d8bb9..aafc8da65f 100644 --- a/runtime/lua/vim/range.lua +++ b/runtime/lua/vim/range.lua @@ -50,24 +50,52 @@ local util = require('vim.pos._util') local M = {} ---@private ----@param pos vim.Range +---@param range vim.Range ---@param key any -function M.__index(pos, key) +function M.__index(range, key) if key == 'start_row' then - return pos[1] + return range[1] elseif key == 'start_col' then - return pos[2] + return range[2] elseif key == 'end_row' then - return pos[3] + return range[3] elseif key == 'end_col' then - return pos[4] + return range[4] elseif key == 'buf' then - return pos[5] + return range[5] end return M[key] end +---@private +---@param range vim.Range +---@param key any +---@param value any +function M.__newindex(range, key, value) + if key == 'start_row' then + validate('start_row', value, 'number') + range[1] = value + elseif key == 'start_col' then + validate('start_col', value, 'number') + range[2] = value + elseif key == 'end_row' then + validate('end_row', value, 'number') + range[3] = value + elseif key == 'end_col' then + validate('end_col', value, 'number') + range[4] = value + elseif key == 'buf' then + validate('buf', value, 'number') + if value == 0 then + value = api.nvim_get_current_buf() + end + range[5] = value + else + rawset(range, key, value) + end +end + ---@package ---@overload fun(start: vim.Pos, end_: vim.Pos): vim.Range ---@overload fun(buf: integer, start_row: integer, start_col: integer, end_row: integer, end_col: integer): vim.Range diff --git a/test/functional/lua/pos_spec.lua b/test/functional/lua/pos_spec.lua index a252702023..fef9d86a52 100644 --- a/test/functional/lua/pos_spec.lua +++ b/test/functional/lua/pos_spec.lua @@ -41,6 +41,17 @@ describe('vim.pos', function() eq({ 1, 3, buf }, pos_default) end) + it('is modifiable', function() + local pos, buf = exec_lua(function() + local pos = vim.pos(-1, 5, 5) + pos.buf = 0 + pos.row = 4 + pos.col = 2 + return pos, vim.api.nvim_get_current_buf() + end) + eq({ 4, 2, buf }, pos) + end) + it('comparisons by overloaded operators', function() local buf = exec_lua(function() return vim.api.nvim_create_buf(false, true) diff --git a/test/functional/lua/range_spec.lua b/test/functional/lua/range_spec.lua index 5c83702ec3..c1e9f1708c 100644 --- a/test/functional/lua/range_spec.lua +++ b/test/functional/lua/range_spec.lua @@ -56,6 +56,19 @@ describe('vim.range', function() eq(success, false) end) + it('is modifiable', function() + local range, buf = exec_lua(function() + local range = vim.range(-1, 5, 5, 5, 5) + range.buf = 0 + range.start_row = 4 + range.start_col = 2 + range.end_row = 6 + range.end_col = 8 + return range, vim.api.nvim_get_current_buf() + end) + eq({ 4, 2, 6, 8, buf }, range) + end) + it('converts between vim.Range and lsp.Range', function() local buf = exec_lua(function() return vim.api.nvim_get_current_buf()