Skip to content

Commit 126ce33

Browse files
committed
fix(snippets): make read_file() work with function array items
Resolve #2032
1 parent 228a8c3 commit 126ce33

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

doc/mini-snippets.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ General advice:
349349
example from |MiniSnippets-examples|.
350350
- Prefer `*.json` files with dict-like content if you want more cross platfrom
351351
setup. Otherwise use `*.lua` files with array-like content.
352+
- To implement "dynamic snippet" that changes data (usually <body>) depending
353+
on the context, use `*.lua` file with function returning snippet data.
354+
It should be an element in the output table (dict or array like).
352355

353356
Notes:
354357
- There is no built-in support for VSCode-like "package.json" files. Define

lua/mini/snippets.lua

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,9 @@
346346
--- example from |MiniSnippets-examples|.
347347
--- - Prefer `*.json` files with dict-like content if you want more cross platfrom
348348
--- setup. Otherwise use `*.lua` files with array-like content.
349+
--- - To implement "dynamic snippet" that changes data (usually <body>) depending
350+
--- on the context, use `*.lua` file with function returning snippet data.
351+
--- It should be an element in the output table (dict or array like).
349352
---
350353
--- Notes:
351354
--- - There is no built-in support for VSCode-like "package.json" files. Define
@@ -376,7 +379,6 @@
376379
--- - Set up 'mini.snippets' as recommended in |MiniSnippets-examples|.
377380
--- - Open Neovim. Type each snippet prefix and press <C-j> (even if there is
378381
--- still active session). Explore from there.
379-
---
380382
---@tag MiniSnippets-overview
381383

382384
--- # Basic snippet management config ~
@@ -1657,7 +1659,7 @@ H.file_readers.lua = function(path, silent)
16571659
local ok, contents = pcall(dofile, path)
16581660
if not ok then return { problems = { 'Could not execute Lua file' } } end
16591661
if type(contents) ~= 'table' then return { problems = { 'Returned object is not a table' } } end
1660-
return H.read_snippet_dict(contents)
1662+
return H.read_snippet_data(contents)
16611663
end
16621664

16631665
H.file_readers.json = function(path, silent)
@@ -1672,18 +1674,21 @@ H.file_readers.json = function(path, silent)
16721674
return { problems = { 'File does not contain a valid JSON object. Reason: ' .. msg } }
16731675
end
16741676

1675-
return H.read_snippet_dict(contents)
1677+
return H.read_snippet_data(contents)
16761678
end
16771679

16781680
H.file_readers['code-snippets'] = H.file_readers.json
16791681

1680-
H.read_snippet_dict = function(contents)
1682+
H.read_snippet_data = function(contents)
16811683
local res, problems = {}, {}
16821684
for name, t in pairs(contents) do
16831685
if H.is_snippet(t) then
16841686
-- Try inferring description from dict's field (if appropriate)
16851687
if type(name) == 'string' and (t.desc == nil and t.description == nil) then t.desc = name end
16861688
table.insert(res, t)
1689+
elseif vim.is_callable(t) then
1690+
-- Allow entries to be functions (relevant for Lua files)
1691+
table.insert(res, t)
16871692
else
16881693
table.insert(problems, 'The following is not a valid snippet data:\n' .. vim.inspect(t))
16891694
end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
return {
2+
function(context) return { prefix = 'dyn', body = 'Buf: ' .. context.buf_id, desc = 'Dynamic' } end,
3+
-- Should also work with function returning (maybe nested) function
4+
function(_)
5+
return {
6+
function(con) return { prefix = 'dynest', body = 'Buf (from nested): ' .. con.buf_id, desc = 'Dynamic nested' } end,
7+
}
8+
end,
9+
}

tests/test_snippets.lua

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,19 @@ T['gen_loader']['from_file()']['works'] = function()
883883
eq(child.lua_get('_G.loader_tilde()'), out)
884884
end
885885

886+
T['gen_loader']['from_file()']['works with function items'] = function()
887+
child.lua('_G.file_dynamic_path = ' .. vim.inspect(test_dir_absolute .. '/file-dynamic-snippets.lua'))
888+
local dyn_snippets = child.lua([[
889+
MiniSnippets.config.snippets = { MiniSnippets.gen_loader.from_file(_G.file_dynamic_path) }
890+
return MiniSnippets.expand({ match = false, insert = false })
891+
]])
892+
local buf_id = get_buf()
893+
eq(dyn_snippets, {
894+
{ prefix = 'dyn', body = 'Buf: ' .. buf_id, desc = 'Dynamic' },
895+
{ prefix = 'dynest', body = 'Buf (from nested): ' .. buf_id, desc = 'Dynamic nested' },
896+
})
897+
end
898+
886899
T['gen_loader']['from_file()']['does not cache if there were reading problems'] = function()
887900
local temp_file = child.lua([[
888901
local temp_file = vim.fn.tempname() .. '.lua'
@@ -991,6 +1004,21 @@ T['read_file()']['works with array-like content'] = function()
9911004
validate('file-array.code-snippets')
9921005
end
9931006

1007+
T['read_file()']['works with function items'] = function()
1008+
child.lua('_G.file_dynamic_path = ' .. vim.inspect(test_dir_absolute .. '/file-dynamic-snippets.lua'))
1009+
local dyn_snippets = child.lua([[
1010+
MiniSnippets.config.snippets = {
1011+
function() return MiniSnippets.read_file(_G.file_dynamic_path) end
1012+
}
1013+
return MiniSnippets.expand({ match = false, insert = false })
1014+
]])
1015+
local buf_id = get_buf()
1016+
eq(dyn_snippets, {
1017+
{ prefix = 'dyn', body = 'Buf: ' .. buf_id, desc = 'Dynamic' },
1018+
{ prefix = 'dynest', body = 'Buf (from nested): ' .. buf_id, desc = 'Dynamic nested' },
1019+
})
1020+
end
1021+
9941022
T['read_file()']['works with relative paths'] = function()
9951023
child.fn.chdir(test_dir_absolute)
9961024
eq(read_file('snippets/lua.json'), { { prefix = 'a', body = 'A=$1', desc = 'snippets/lua.json' } })

0 commit comments

Comments
 (0)