local M = {snippets = {}} M.menu_cmd = 'vis-menu' -- check if fzf is available and use fzf instead of vis-menu per default if os.execute('type fzf >/dev/null 2>/dev/null') then M.menu_cmd = 'fzf' end local source_str = debug.getinfo(1, 'S').source:sub(2) local script_path = source_str:match('(.*/)') local snippets_path = script_path .. 'snippets' local function available_snippets() local snippets = {} -- available string snippets for k, _ in ipairs(M.snippets) do snippets[k] = true end -- available file snippets local cmd = 'ls ' .. snippets_path local proc = io.popen(cmd) local out = assert(proc:read("*a")) -- TODO: error handling proc:close() for filename in out:gmatch("(.-)\n") do snippets[filename] = true end local _snippets = {} for k, _ in pairs(snippets) do table.insert(_snippets, k) end return _snippets end -- concatenate all numeric values in choices and pass it on stdin to M.menu_cmd local function lspc_select(choices) local menu_input = '' local i = 0 for _, c in ipairs(choices) do i = i + 1 menu_input = menu_input .. c .. '\n' end -- select the only possible choice if i < 2 then return choices[1] end local status, output local cmd = 'printf "' .. menu_input .. '" | ' .. M.menu_cmd if M.menu_cmd:sub(0, 8) == 'vis-menu' then status, output = vis:pipe(vis.win.file, {start = 0, finish = 0}, cmd) else local menu = io.popen(cmd) output = menu:read('*a') local _, _, _status = menu:close() status = _status end local choice = nil if status == 0 then -- trim newline from selection if output:sub(-1) == '\n' then choice = output:sub(1, -2) else choice = output end end vis:redraw() return choice end local function select_avail_snippet() return lspc_select(available_snippets()) end local function read_file_snippet(name) local snippet_path = snippets_path .. '/' .. name local file = io.open(snippet_path, "rb") -- r read mode and b binary mode if not file then return end local content = file:read("*a") file:close() return content end vis:command_register('snippet', function(argv, _, win, _, _) local snippet = argv[1] or select_avail_snippet() if not snippet then return end local pos = win.selection.pos if not M.snippets[snippet] then local content = read_file_snippet(snippet) M.snippets[snippet] = content win.file:insert(pos, content) else win.file:insert(pos, M.snippets[snippet]) end end, 'Insert a snippet after the primary selection') return M