diff options
author | Thomas Voss <mail@thomasvoss.com> | 2023-11-13 23:31:57 +0100 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2023-11-13 23:31:57 +0100 |
commit | 10c3013239a96a4279b492d28d7c8679b7450c29 (patch) | |
tree | 4d1d8d7c6c8649f086ec0db38d6ffed1ee46fe1c | |
parent | 446a47fd5975ec492964e5d59572c93719b24501 (diff) |
nvim: Add snippets with luasnip
-rw-r--r-- | .config/nvim/after/plugin/luasnip.lua | 205 |
1 files changed, 202 insertions, 3 deletions
diff --git a/.config/nvim/after/plugin/luasnip.lua b/.config/nvim/after/plugin/luasnip.lua index 8216615..6d9d662 100644 --- a/.config/nvim/after/plugin/luasnip.lua +++ b/.config/nvim/after/plugin/luasnip.lua @@ -1,4 +1,203 @@ -local luasnip = require('luasnip') +local ls = require('luasnip') +local ts_utils = require('nvim-treesitter.ts_utils') +local ts_locals = require('nvim-treesitter.locals') -vim.keymap.set('i', '<C-l>', function() luasnip.jump(1) end) -vim.keymap.set('i', '<C-h>', function() luasnip.jump(-1) end) +local c = ls.choice_node +local d = ls.dynamic_node +local f = ls.function_node +local i = ls.insert_node +local s = ls.s +local sn = ls.snippet_node +local t = ls.text_node +local fmt = require('luasnip.extras.fmt').fmt + +ls.config.set_config { + history = true, + updateevents = 'TextChanged,TextChangedI', +} + +ls.add_snippets('lua', { + s('req', fmt([[local {} = require('{}')]], { + f(function(name) + local xs = vim.split(name[1][1], '.', { plain = true }) + return xs[#xs] or '' + end, { 1 }), + i(1), + })), +}) + +local function is_ptr(str) + return string.find(str, '*', 1, true) ~= nil +end + +local function is_num(str) + return vim.regex( + '\\v^(' + .. 'u?int(8|16|32|64)?' + .. '|byte' + .. '|complex(64|128)' + .. '|float(32|64)' + .. '|rune' + .. '|uintptr' + .. ')$' + ):match_str(str) ~= nil +end + +local transforms = { + bool = 'false', + string = '""', + error = 'err', + [is_num] = '0', + [is_ptr] = 'nil', +} + +local transform = function(text) + local condition_matches = function(condition, ...) + if type(condition) == 'string' then + return condition == text + else + return condition(...) + end + end + + for condition, result in pairs(transforms) do + if condition_matches(condition, text) then + return t(result) + end + end + + return t(text .. '{}') +end + +local handlers = { + parameter_list = function(node) + local result = {} + + local count = node:named_child_count() + for idx = 0, count - 1 do + local matching_node = node:named_child(idx) + local type_node = matching_node:field('type')[1] + table.insert(result, transform( + vim.treesitter.get_node_text(type_node, 0) + )) + if idx ~= count - 1 then + table.insert(result, t({ ', ' })) + end + end + + return result + end, + + type_identifier = function(node) + local text = vim.treesitter.get_node_text(node, 0) + return { transform(text) } + end, +} + +local function_node_types = { + function_declaration = true, + method_declaration = true, + func_literal = true, +} + +local function go_result_type() + local cursor_node = ts_utils.get_node_at_cursor() + if cursor_node == nil then + print('Unable to find position') + return t('') + end + local scope = ts_locals.get_scope_tree(cursor_node, 0) + + local function_node + for _, v in ipairs(scope) do + if function_node_types[v:type()] then + function_node = v + break + end + end + + if not function_node then + print('Not inside of a function') + return t('') + end + + local query = vim.treesitter.query.parse('go', [[ + [ + (method_declaration result: (_) @id) + (function_declaration result: (_) @id) + (func_literal result: (_) @id) + ] + ]]) + for _, node in query:iter_captures(function_node, 0) do + if handlers[node:type()] then + return handlers[node:type()](node) + end + end +end + +ls.add_snippets('go', { + s( + 'f', + fmt( + [[ + func <><>() <>{ + <> + } + ]], + { + c(1, { + t(''), + t('() '), + }), + i(2, 'name'), + c(3, { + t(''), + t('() '), + }), + i(0), + }, + { + delimiters = '<>', + } + ) + ), + s( + 'ife', + fmt( + [[ + if err != nil { + return <> + } + ]], + { + d(1, function() + return sn(nil, go_result_type()) + end), + }, + { + delimiters = '<>', + } + ) + ), +}) + +vim.keymap.set({ 'i', 's' }, '<C-l>', function() + if ls.expand_or_jumpable() then + ls.expand_or_jump() + end +end) +vim.keymap.set('i', '<C-h>', function() + if ls.jumpable(-1) then + ls.jump(-1) + end +end) +vim.keymap.set('i', '<C-k>', function() + if ls.choice_active() then + ls.change_choice(-1) + end +end) +vim.keymap.set('i', '<C-j>', function() + if ls.choice_active() then + ls.change_choice(1) + end +end) |