neovim configuration using rocks.nvim plugin manager
at main 103 lines 3.2 kB view raw
1require("luasnip.session.snippet_collection").clear_snippets("typescriptreact") 2 3local ls = require("luasnip") 4local s = ls.snippet 5local i = ls.insert_node 6local t = ls.text_node 7local c = ls.choice_node 8local fn = ls.function_node 9local dn = ls.dynamic_node 10local sn = ls.snippet_node 11local rep = require("luasnip.extras").rep 12local fmt = require("luasnip.extras.fmt").fmt 13local fmta = require("luasnip.extras.fmt").fmta 14 15-- Get a list of the property names given an `interface_declaration` 16-- treesitter *tsx* node. 17-- Ie, if the treesitter node represents: 18-- interface { 19-- prop1: string; 20-- prop2: number; 21-- } 22-- Then this function would return `{"prop1", "prop2"} 23---@param node TSNode interface declaration node 24---@return string[] 25local function get_prop_names(node) 26 local interface_body = node:field("body")[1] 27 if not interface_body then 28 return {} 29 end 30 31 local prop_names = {} 32 33 for prop_signature in interface_body:iter_children() do 34 if prop_signature:type() == "property_signature" then 35 local prop_iden = prop_signature:child(0) 36 local prop_name = vim.treesitter.get_node_text(prop_iden, 0) 37 prop_names[#prop_names + 1] = prop_name 38 end 39 end 40 41 return prop_names 42end 43 44-- original: https://gist.github.com/davidatsurge/9873d9cb1781f1a37c0f25d24cb1b3ab 45-- https://www.reddit.com/r/neovim/comments/uuhk1t/feedback_on_luasniptreesitter_snippet_that_fills/ 46local componentWithProps = fmta( 47 [[ 48 <>interface <>Props { 49 <><> 50 } 51 52 export function <>({ <> }: <>Props) { 53 <>return <>; 54 }; 55 ]], 56 { 57 c(1, { t "export ", t "" }), 58 -- Initialize component name to file name 59 rep(3), 60 t "\t", 61 i(2, "// Props"), 62 dn(3, function(_, snip) 63 local filename = vim.fn.expand("%:t:r") 64 local comp_name 65 -- TODO: rewrite this with `vim.fs` lua api 66 if filename == "index" then 67 comp_name = vim.fn.expand("%"):match("([^/]+)/[^/]+$") 68 else 69 comp_name = vim.fn.substitute(snip.env.TM_FILENAME, "\\..*$", "", "g") 70 end 71 return sn(nil, { i(1, comp_name) }) 72 end, { 1 }), 73 fn(function(_, snip, _) 74 local pos_begin = snip.nodes[4].mark:pos_begin() 75 local pos_end = snip.nodes[4].mark:pos_end() 76 local parser = vim.treesitter.get_parser(0, "tsx") 77 local tstree = parser:parse() 78 79 local node = tstree[1]:root():named_descendant_for_range(pos_begin[1], pos_begin[2], pos_end[1], pos_end[2]) 80 81 while node ~= nil and node:type() ~= "interface_declaration" do 82 node = node:parent() 83 end 84 85 if node == nil then 86 return "" 87 end 88 89 -- `node` is now surely of type "interface_declaration" 90 local prop_names = get_prop_names(node) 91 92 return vim.fn.join(prop_names, ", ") 93 end, { 2 }), 94 rep(3), 95 t "\t", 96 i(4, "null"), 97 } 98) 99 100-- stylua: ignore 101ls.add_snippets("typescriptreact", { 102 s("cp", componentWithProps), 103})