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

如何为Neovim自定义命令Piomon添加带描述的补全功能

为Neovim自定义命令添加带描述的补全功能

问题场景

我正在为Neovim创建Piomon自定义命令,需要为其添加分层补全逻辑:

  • 第1个参数补全波特率(4800/9600等)
  • 第2个参数补全串口设备路径,要求补全列表同时显示设备路径和设备描述,但选中后仅插入设备路径

原命令代码如下:

vim.api.nvim_create_user_command('Piomon', function(opts)
  local args = opts.fargs
  require('platformio.piomon').piomon(args)
end, {
  nargs = '*',
  complete = function(_, cmd_line)
    local parts = vim.split(cmd_line, "%s+")
    local BAUD = { '4800', '9600', '57600', '115200' }
    if #parts == 2 then return BAUD end
    if #parts == 3 then return tty_list end
    return {}
  end
})

当tty_list是普通字符串数组(如{ "/dev/ttyUSB1", "/dev/ttyACM1" })时补全正常,但我需要将其改为带描述的结构:

{
  {description = "USB-Serial Controller", port = "/dev/ttyUSB1"},
  {description = "STM32 STLink - ST-Link VCP Ctrl", port = "/dev/ttyACM1"}
}

尝试了ChatGPT提供的动态生成补全项的方案,但无法正常工作:

run({ "platformio", "device", "list", "--json-output" }, function(lines)
  local json_data = vim.json.decode(table.concat(lines, ""))
  for _, value in ipairs(json_data) do
    if value['description'] ~= "n/a" then
      table.insert(tty_list, {
        word = value['port'],
        abbr = value['description'],
        menu = ""  -- IMPORTANT
      })
    end
  end
  print(vim.inspect(tty_list))
end)

解决方案

Neovim的自定义命令补全函数支持返回结构化的补全项字典,核心是利用word(实际插入的内容)和abbr(补全列表显示的文本)两个字段实现需求。以下是修正后的完整代码:

1. 静态补全项示例(手动定义带描述的设备)

vim.api.nvim_create_user_command('Piomon', function(opts)
  local args = opts.fargs
  require('platformio.piomon').piomon(args)
end, {
  nargs = '*',
  complete = function(_, cmd_line)
    -- 移除分割后的空字符串,避免参数计数错误
    local parts = vim.split(cmd_line, "%s+", {trimempty = true})
    local BAUD = { '4800', '9600', '57600', '115200' }
    
    if #parts == 2 then
      return BAUD
    elseif #parts == 3 then
      -- 将带描述的设备转换为Neovim支持的补全结构
      local tty_list = {
        {description = "USB-Serial Controller", port = "/dev/ttyUSB1"},
        {description = "STM32 STLink - ST-Link VCP Ctrl", port = "/dev/ttyACM1"}
      }
      local completions = {}
      for _, dev in ipairs(tty_list) do
        table.insert(completions, {
          word = dev.port,          -- 选中后插入命令的内容
          abbr = string.format("%s (%s)", dev.port, dev.description) -- 补全列表显示的文本
        })
      end
      return completions
    end
    return {}
  end
})

2. 动态获取PlatformIO设备列表(修正异步问题)

如果需要从platformio device list动态获取设备,需确保补全触发时数据已就绪,可改为同步获取(或提前缓存异步结果):

local function get_platformio_devices()
  -- 同步执行命令并获取输出
  local handle = io.popen("platformio device list --json-output")
  if not handle then return {} end
  local output = handle:read("*a")
  handle:close()
  
  local json_data = vim.json.decode(output) or {}
  local completions = {}
  for _, dev in ipairs(json_data) do
    if dev.description and dev.description ~= "n/a" and dev.port then
      table.insert(completions, {
        word = dev.port,
        abbr = string.format("%s (%s)", dev.port, dev.description)
      })
    end
  end
  return completions
end

vim.api.nvim_create_user_command('Piomon', function(opts)
  local args = opts.fargs
  require('platformio.piomon').piomon(args)
end, {
  nargs = '*',
  complete = function(_, cmd_line)
    local parts = vim.split(cmd_line, "%s+", {trimempty = true})
    local BAUD = { '4800', '9600', '57600', '115200' }
    
    if #parts == 2 then
      return BAUD
    elseif #parts == 3 then
      return get_platformio_devices() -- 动态返回带描述的补全项
    end
    return {}
  end
})

关键说明

  • 补全项结构:word字段是最终插入到命令中的内容,abbr字段控制补全列表的显示文本,通过拼接端口和描述,实现"显示完整信息但仅插入路径"的需求。
  • 命令行分割:使用{trimempty = true}参数避免因连续空格导致的分割错误,确保参数计数准确。
  • 动态数据处理:同步执行platformio device list可保证补全时数据已就绪;若需异步获取,可在插件加载时提前执行并缓存结果,避免补全时的延迟。

内容的提问来源于stack exchange,提问作者Anurag Kumar Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 00:34:51