summary refs log tree commit diff
path: root/.vim/lua/internal/snippets.lua
diff options
context:
space:
mode:
Diffstat (limited to '.vim/lua/internal/snippets.lua')
-rw-r--r--.vim/lua/internal/snippets.lua129
1 files changed, 129 insertions, 0 deletions
diff --git a/.vim/lua/internal/snippets.lua b/.vim/lua/internal/snippets.lua
new file mode 100644
index 0000000..be00884
--- /dev/null
+++ b/.vim/lua/internal/snippets.lua
@@ -0,0 +1,129 @@
+local ls = require('luasnip')
+local types = require('luasnip.util.types')
+
+-- attach to builtin snippet hooks
+
+vim.snippet.expand = ls.lsp_expand
+
+---@diagnostic disable-next-line: duplicate-set-field
+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
+
+---@diagnostic disable-next-line: duplicate-set-field
+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
+
+local 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,
+  },
+}
+
+ls.config.set_config({
+  enable_autosnippets = true,
+  history = true,
+  updateevents = 'TextChanged,TextChangedI',
+  override_builtin = true,
+  snip_env = vim.tbl_deep_extend('error', ls.session.config.snip_env, snip_env),
+  ext_opts = {
+    [types.choiceNode] = {
+      active = {
+        virt_text = { { '◂    󰬊 ', 'NonText' } },
+      },
+    },
+    [types.insertNode] = {
+      active = {
+        virt_text = { { '◂    󰬐 ', 'NonText' } },
+      },
+    },
+  },
+})
+
+require('luasnip.loaders.from_lua').lazy_load({ paths = './snippets' })
+
+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' })
+
+vim.api.nvim_create_user_command('EditSnippets', require('luasnip.loaders').edit_snippet_files, {})
+
+-- 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,
+-- })