Vim数字文本对象函数转Lua后异常,求正确实现方案
正确的Lua实现自定义数字文本对象
问题原因
你之前的实现出错,大概率是因为Lua调用Vimscript时,光标位置的上下文传递异常,或是正则匹配的范围计算没有适配跨环境的坐标规则(比如Vimscript的1-based索引在Lua中处理不当),导致只选中了数字的部分片段。
实现方案
直接用Lua API处理行内容与正则匹配,避免跨环境调用的问题,以下是可靠的实现:
1. 核心函数:定位数字边界
这个函数会找到当前光标所在的完整数字的起始和结束位置:
local function get_number_boundaries() -- 转换为Lua的0-based行/列索引 local row = vim.fn.line('.') - 1 local col = vim.fn.col('.') - 1 -- 获取当前行内容 local line = vim.api.nvim_buf_get_lines(0, row, row + 1, false)[1] if not line then return end -- 正则匹配完整数字:支持负数、小数 local number_pattern = [[\v(-?\d+(\.\d+)?)]] -- 收集当前行所有数字的位置信息 local matches = {} local start_idx = 0 while true do local s, e = vim.fn.matchstrpos(line, number_pattern, start_idx) if s == -1 then break end table.insert(matches, { start = s, end_ = e }) start_idx = e end -- 找到包含当前光标所在列的数字,返回Vim的1-based位置 for _, match in ipairs(matches) do if col >= match.start and col < match.end_ then return row + 1, match.start + 1, row + 1, match.end_ end end end
2. 映射文本对象键位
将in(内部数字)和an(环绕数字,这里和内部逻辑一致,若需包含周围空白可自行调整)映射到文本对象:
-- 映射inner number文本对象,支持`cin`/`vin`等操作 vim.keymap.set({ 'o', 'x' }, 'in', function() local r1, c1, r2, c2 = get_number_boundaries() if r1 then vim.fn.cursor(r1, c1) vim.cmd('normal! v') vim.fn.cursor(r2, c2) end end, { desc = "Inner number text object" }) -- 映射around number文本对象 vim.keymap.set({ 'o', 'x' }, 'an', function() local r1, c1, r2, c2 = get_number_boundaries() if r1 then vim.fn.cursor(r1, c1) vim.cmd('normal! v') vim.fn.cursor(r2, c2) end end, { desc = "Around number text object" })
使用说明
- 在数字上执行
cin:删除当前完整数字并进入插入模式 - 在数字上执行
vin:选中当前完整数字 - 支持负数(如
-42)和小数(如3.14)的匹配
内容的提问来源于stack exchange,提问作者mr_scrpt
相关产品推荐
相关产品推荐

