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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
--------------------------------------------------------------------------------
-- Modules
local M = {}
local cwd = ...
local SnipMate = require(cwd .. '.snipmate-parser')
local UltiSnips = require(cwd .. '.ultisnips-parser')
--------------------------------------------------------------------------------
-- Config
M.snipmate = ''
M.ultisnips = ''
--------------------------------------------------------------------------------
-- Helper functions
-- Takes list of snippets and concatenates them into the string suitable
-- for passing to dmenu (or, very probably, vis-menu)
local function snippetslist(snippets)
local list = ''
for k,v in pairs(snippets) do
if not v.description then
list = list .. k .. '\n'
else
list = list .. k .. ' - ' .. v.description .. '\n'
end
end
return list
end
local function load_ultisnips()
local snippetfile = M.ultisnips .. vis.win.syntax .. '.snippets'
local snippets, success = UltiSnips.load_snippets(snippetfile)
if not success then
vis:info('Failed to load a correct UltiSnip: ' .. snippetfile)
end
return snippets, success
end
local function load_snipmate()
local snippetfile = M.snipmate .. vis.win.syntax .. '.snippets'
local snippets, success = SnipMate.load_snippets(snippetfile)
if not success then
vis:info('Failed to load a correct SnipMate: ' .. snippetfile)
end
return snippets, success
end
-- Second will append to first using suffix for distinguishing
local function merge_and_override(snips1, snips2, suffix)
for k,v in pairs(snips2) do
snips1[k .. suffix] = v
end
return snips1
end
--------------------------------------------------------------------------------
-- Plugging it all in
vis:map(vis.modes.INSERT, "<C-x><C-j>", function()
local snippets = merge_and_override(load_snipmate(), load_ultisnips(), '_us')
local win = vis.win
local file = win.file
local pos = win.selection.pos
if not pos then
return
end
-- TODO do something clever here
-- Use prefix W if exists
local initial = ' '
local range = file:text_object_longword(pos > 0 and pos - 1 or pos)
if range then
initial = initial .. file:content(range)
end
-- Note, for one reason or another, using vis-menu corrupts my terminal
-- (urxvt) for exact amount of lines that vis-menu takes
-- dmenu has no such problems, but can't take initial input :-\
--local stdout = io.popen("echo '" .. snippetslist(snippets) .. "' | dmenu -l 5", "r")
local stdout = io.popen("echo '" .. snippetslist(snippets) .. "' | vis-menu " .. initial, "r")
local chosen = stdout:lines()()
local _, msg, status = stdout:close()
if status ~= 0 or not chosen then
vis:message(msg)
return
end
local trigger = chosen:gmatch('[^ ]+')()
local snipcontent = snippets[trigger].content
if range then
file:delete(range)
-- Update position after deleting the range
pos = pos - (range.finish - range.start)
vis:redraw()
end
vis:insert(snipcontent.str)
if #snipcontent.tags > 0 then
vis:info("Use 'g>' and 'g<' to navigate between anchors.")
-- Create selections iteratively using `:#n,#n2 p` command and `gs` to
-- save it in the jumplist
for _,v in ipairs(snipcontent.tags) do
-- Can't use 'x' command because it'd select stuff across
-- whole file
vis:command('#' .. pos + v.selstart ..',#' .. pos + v.selend .. ' p')
--vis:feedkeys('gs') -- Tested, works without this too, but just in case
--vis:message('Command: ' .. cmd)
end
-- Backtrack through all selections we've made first
-- (so that we can use g> to move us forward)...
for _ in ipairs(snipcontent.tags) do
vis:feedkeys('g<')
end
-- ... then set us on the first selection
vis:feedkeys('g>')
else
win.selection.pos = pos + #snipcontent.str
end
end, "Insert a snippet")
--------------------------------------------------------------------------------
-- End module
return M
|