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
|
local ls = require('luasnip')
local types = require('luasnip.util.types')
-- configure luasnip
ls.config.set_config({
enable_autosnippets = true,
history = true,
updateevents = 'TextChanged,TextChangedI',
override_builtin = true,
ext_opts = {
[types.choiceNode] = {
active = {
virt_text = { { '◂ ', 'NonText' } },
},
},
[types.insertNode] = {
active = {
virt_text = { { '◂ ', 'NonText' } },
},
},
},
snip_env = vim.tbl_deep_extend('error', ls.session.config.snip_env, {
-- snippet helpers
nl = function()
return ls.t({ '', '' })
end,
exec = function(command)
return ls.f(function(_, _, ...)
local job = require('plenary.job'):new({
command = vim.env.SHELL,
args = { '-c', ... },
enable_recording = true,
})
local res, exitcode = job:sync()
if not exitcode == 0 or #res == 0 then
error(string.format('exec "%s" failed', ...))
end
return res
end, {}, { user_args = { command } })
end,
-- condition helpers
cond = {
ts = function(capture)
return function()
return vim.tbl_contains(vim.treesitter.get_captures_at_cursor(), capture)
end
end,
},
}),
})
-- snippet loaders
require('luasnip.loaders.from_lua').lazy_load()
require('luasnip.loaders.from_vscode').lazy_load({ include = {} })
-- keymaps
vim.keymap.set({ 'i', 's' }, '<c-j>', function()
return vim.snippet.active({ direction = 1 }) and vim.snippet.jump(1)
end, { silent = true, desc = 'snippet: jump next' })
vim.keymap.set({ 'i', 's' }, '<c-k>', function()
return vim.snippet.active({ direction = -1 }) and vim.snippet.jump(-1)
end, { silent = true, desc = 'snippet: jump prev' })
vim.keymap.set({ 'i', 's' }, '<c-n>', function()
if ls.choice_active() then
ls.change_choice(1)
end
end, { silent = true, desc = 'snippet: next choice' })
vim.keymap.set({ 'i', 's' }, '<c-p>', function()
if ls.choice_active() then
ls.change_choice(-1)
end
end, { silent = true, desc = 'snippet: prev choice' })
-- usercmds
vim.api.nvim_create_user_command('EditSnippets', require('luasnip.loaders').edit_snippet_files, {})
-- autocmds
-- vim.api.nvim_create_autocmd('User', {
-- pattern = 'LuasnipChoiceNodeEnter',
-- callback = function()
-- vim.schedule(function()
-- assert(ls.session.active_choice_nodes[vim.api.nvim_get_current_buf()], 'No active choiceNode')
-- vim.ui.select(
-- ls.get_current_choices(),
-- -- TODO: patch luasnip.extras.select_choice to fix missing prompt
-- { prompt = 'LuaSnip: choice node', kind = 'luasnip' },
-- function(_, idx)
-- if not idx then
-- return
-- end
-- -- feed+immediately execute i to enter INSERT after vim.ui.input closes.
-- vim.api.nvim_feedkeys('i', 'x', false)
-- ls.set_choice(idx)
-- ls.unlink_current()
-- end
-- )
-- end)
-- end,
-- })
-- unlink luasnip session on <esc>
vim.api.nvim_create_autocmd('ModeChanged', {
pattern = '*',
callback = function()
if ((vim.v.event.old_mode == 's' and vim.v.event.new_mode == 'n') or vim.v.event.old_mode == 'i')
and ls.session.current_nodes[vim.api.nvim_get_current_buf()]
and not ls.session.jump_active
and not require("blink.cmp").is_visible()
then
ls.unlink_current()
end
end
})
-- attach to builtin snippet hooks
vim.snippet.expand = ls.lsp_expand
vim.snippet.active = function(filter)
filter = filter or {}
filter.direction = filter.direction or 1
if filter.direction == 1 then
return ls.expand_or_jumpable()
else
return ls.jumpable(filter.direction)
end
end
vim.snippet.jump = function(direction)
if direction == 1 then
if ls.expandable() then
return ls.expand_or_jump()
else
return ls.jumpable(1) and ls.jump(1)
end
else
return ls.jumpable(-1) and ls.jump(-1)
end
end
vim.snippet.stop = ls.unlink_current
|