summaryrefslogtreecommitdiff
path: root/init.lua
blob: 4f6947db3be93ea54491548d54bb88d56889d1ea (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
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