Skip to content

Commit a3320ad

Browse files
committed
feat(rust): add tfn snippet
1 parent aeac509 commit a3320ad

File tree

4 files changed

+169
-30
lines changed

4 files changed

+169
-30
lines changed

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,12 @@ ls.setup({
210210

211211
#### Normal Snippets
212212

213-
| Trig | Desc | Context Required |
214-
| :---: | ------------------------------------------------ | :--------------: |
215-
| `fn` | Expands to function definition. | No |
216-
| `wfn` | Expands to function definition returns a widget. | No |
217-
| `afn` | Expands to an async function definition. | No |
213+
| Trig | Desc | Context Required |
214+
| :---: | -------------------------------------------------------------------- | :--------------: |
215+
| `fn` | Expands to function definition. | No |
216+
| `wfn` | Expands to function definition returns a widget. | No |
217+
| `afn` | Expands to an async function definition. | No |
218+
| `tfn` | Expands to a test function. `#[test]` or `#[tokio::test]` supported. | No |
218219

219220
#### Auto-snippets
220221

lua/luasnip-snippets/snippets/rust/init.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ local function setup()
55
"default",
66
"postfix",
77
"lambda_fn",
8+
"test_fn",
89
})
910
end
1011

lua/luasnip-snippets/snippets/rust/lambda_fn.lua

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -59,31 +59,6 @@ return {
5959
},
6060
d(1, function(_, parent)
6161
local env = parent.env
62-
local last_type, last_type_row, last_type_col
63-
local keys = {
64-
"CPP_ARGUMENT_START",
65-
"CPP_FUNCTION_BODY_START",
66-
"CPP_CLASS_BODY_START",
67-
}
68-
for _, key in ipairs(keys) do
69-
if env[key] ~= nil then
70-
if last_type == nil then
71-
last_type = key
72-
last_type_row = env[key][1]
73-
last_type_col = env[key][2]
74-
else
75-
if
76-
last_type_row < env[key][1]
77-
or (last_type_row == env[key][1] and last_type_col < env[key][2])
78-
then
79-
last_type = key
80-
last_type_row = env[key][1]
81-
last_type_col = env[key][2]
82-
end
83-
end
84-
end
85-
end
86-
8762
if
8863
env.FUNCTION_ITEM_START ~= nil or env.CLOSURE_EXPRESSION_START ~= nil
8964
then
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
local UtilsTS = require("luasnip-snippets.utils.treesitter")
2+
local ls = require("luasnip")
3+
local d = ls.dynamic_node
4+
local sn = ls.snippet_node
5+
local t = ls.text_node
6+
local f = ls.function_node
7+
local fmta = require("luasnip.extras.fmt").fmta
8+
local i = require("luasnip-snippets.nodes").insert_node
9+
local c = require("luasnip-snippets.nodes").choice_node
10+
11+
local function inject_expanding_environment(_, _, match, captures)
12+
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
13+
local buf = vim.api.nvim_get_current_buf()
14+
15+
return UtilsTS.invoke_after_reparse_buffer(
16+
buf,
17+
match,
18+
function(parser, source)
19+
local pos = {
20+
row - 1,
21+
col - #match,
22+
}
23+
local node = parser:named_node_for_range {
24+
pos[1],
25+
pos[2],
26+
pos[1],
27+
pos[2],
28+
}
29+
30+
local ret = {
31+
trigger = match,
32+
capture = captures,
33+
env_override = {
34+
IMPL_ITEM_START = UtilsTS.start_pos(
35+
UtilsTS.find_first_parent(node, { "impl_item" })
36+
),
37+
FUNCTION_ITEM_START = UtilsTS.start_pos(
38+
UtilsTS.find_first_parent(node, { "function_item" })
39+
),
40+
CLOSURE_EXPRESSION_START = UtilsTS.start_pos(
41+
UtilsTS.find_first_parent(node, { "closure_expression" })
42+
),
43+
},
44+
}
45+
46+
---@type TSNode?
47+
local mod_item = UtilsTS.find_first_parent(node, { "mod_item" })
48+
if mod_item ~= nil then
49+
ret.env_override["MOD_ITEM_START"] =
50+
UtilsTS.start_pos(UtilsTS.find_first_parent(node, { "mod_item" }))
51+
local name_node = mod_item:field("name")[1]
52+
if name_node ~= nil then
53+
ret.env_override["MOD_ITEM_NAME"] =
54+
vim.treesitter.get_node_text(name_node, source)
55+
end
56+
local prev = mod_item:prev_sibling()
57+
local attributes = {}
58+
-- try to fild
59+
while true do
60+
if prev == nil then
61+
break
62+
end
63+
if
64+
prev:type() == "line_comment" or prev:type() == "block_comment"
65+
then
66+
-- skip this
67+
elseif prev:type() == "attribute_item" then
68+
attributes[#attributes + 1] =
69+
vim.treesitter.get_node_text(prev, source)
70+
else
71+
break
72+
end
73+
prev = prev:prev_sibling()
74+
end
75+
ret.env_override["ATTRIBUTES_ITEMS"] = attributes
76+
end
77+
78+
vim.api.nvim_win_set_cursor(0, { row, col })
79+
return ret
80+
end
81+
)
82+
end
83+
84+
return {
85+
ls.s(
86+
{
87+
trig = "tfn",
88+
wordTrig = true,
89+
name = "(tfn) Test function definition",
90+
resolveExpandParams = inject_expanding_environment,
91+
},
92+
d(1, function(_, parent)
93+
local env = parent.env
94+
local in_test_cfg = false
95+
if env["ATTRIBUTES_ITEMS"] ~= nil then
96+
for _, v in ipairs(env["ATTRIBUTES_ITEMS"]) do
97+
if v == "#[cfg(test)]" then
98+
in_test_cfg = true
99+
break
100+
end
101+
end
102+
end
103+
104+
if in_test_cfg and env.MOD_ITEM_NAME == "tests" then
105+
-- function item
106+
return sn(
107+
nil,
108+
fmta(
109+
[[
110+
<attr>
111+
<modifier>fn test_<name>() {
112+
<body>
113+
}
114+
]],
115+
{
116+
modifier = f(function(args, _)
117+
if vim.tbl_get(args, 1, 1) == "#[tokio::test]" then
118+
return "async "
119+
else
120+
return ""
121+
end
122+
end, { 2 }),
123+
name = i(1, "new_fn", { desc = "function name" }),
124+
attr = c(2, {
125+
t("#[test]"),
126+
t("#[tokio::test]"),
127+
}, { desc = "function attributes" }),
128+
body = i(0),
129+
}
130+
)
131+
)
132+
else
133+
-- function item
134+
return sn(
135+
nil,
136+
fmta(
137+
[[
138+
<modifier><visible>fn <name>(<args>) {
139+
<body>
140+
}
141+
]],
142+
{
143+
modifier = c(1, {
144+
t(""),
145+
t("async "),
146+
}, { desc = "function modifier" }),
147+
visible = c(2, {
148+
t(""),
149+
t("pub "),
150+
t("pub(crate) "),
151+
t("pub(super) "),
152+
}, { desc = "visibility" }),
153+
name = i(3, "new_fn", { desc = "function name" }),
154+
args = i(4, "args", { desc = "function arguments" }),
155+
body = i(0),
156+
}
157+
)
158+
)
159+
end
160+
end, {})
161+
),
162+
}

0 commit comments

Comments
 (0)