如何为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
相关产品推荐
相关产品推荐

