1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
-- Copyright (c) 2023-2024 Florian Fischer. All rights reserved.
--
-- vis-snippets is free software: you can redistribute it and/or modify it under
-- the terms of the GNU General Public License as published by the Free Software
-- Foundation, either version 3 of the License, or (at your option) any later
-- version.
--
-- vis-snippets is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License along with
-- vis-snippets found in the LICENSE file.
-- If not, see <https://www.gnu.org/licenses/>.
--
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
-- select implementation copied from vis-lspc.
-- 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
|