summaryrefslogtreecommitdiff
path: root/init.lua
blob: 3025386c2bd33ae64a525a1c606adec2947e8aa1 (plain)
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
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