You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 06:25:34