mirror of
https://github.com/Ascyii/typstar.git
synced 2026-01-01 05:24:24 -05:00
107 lines
3.6 KiB
Lua
107 lines
3.6 KiB
Lua
local M = require('typstar.engine') -- inherit all functions
|
|
local luasnip = require('luasnip')
|
|
|
|
function M.cap(i)
|
|
return luasnip.function_node(function(_, snip) return snip.captures[i] end)
|
|
end
|
|
|
|
local compute_leading_white_spaces = function(snip, i)
|
|
local capture = snip.captures[i] or ''
|
|
return capture:match('^%s*') or ''
|
|
end
|
|
|
|
function M.leading_white_spaces(i)
|
|
return luasnip.function_node(function(_, snip) return compute_leading_white_spaces(snip, i) end)
|
|
end
|
|
|
|
function M.visual(idx, default, line_prefix, indent_capture_idx)
|
|
default = default or ''
|
|
line_prefix = line_prefix or ''
|
|
return luasnip.dynamic_node(idx, function(_, snip)
|
|
local select_raw = snip.snippet.env.LS_SELECT_RAW
|
|
if #select_raw > 0 then
|
|
if line_prefix ~= '' then -- e.g. indentation
|
|
for i, s in ipairs(select_raw) do
|
|
select_raw[i] = line_prefix .. s
|
|
end
|
|
end
|
|
return luasnip.snippet_node(nil, luasnip.text_node(select_raw))
|
|
else -- If LS_SELECT_RAW is empty, return an insert node
|
|
local leading = ''
|
|
if indent_capture_idx ~= nil then leading = compute_leading_white_spaces(snip, indent_capture_idx) end
|
|
return luasnip.snippet_node(nil, {
|
|
luasnip.text_node(leading .. line_prefix),
|
|
luasnip.insert_node(1, default),
|
|
})
|
|
end
|
|
end)
|
|
end
|
|
|
|
function M.ri(insert_node_id)
|
|
return luasnip.function_node(function(args) return args[1][1] end, insert_node_id)
|
|
end
|
|
|
|
function M.start_snip(trigger, expand, insert, condition, priority, options)
|
|
return M.snip('^(\\s*)' .. trigger, '<>' .. expand, { M.cap(1), unpack(insert) }, condition, priority, options)
|
|
end
|
|
|
|
-- transform the snippet expand by inserting indentation and/or a prefix after each newline
|
|
function M.blocktransform(expand, insert, prepend, indent_capture_idx)
|
|
local indent = indent_capture_idx ~= nil
|
|
if not indent and not prepend then return expand, insert end
|
|
prepend = prepend or ''
|
|
|
|
local modified_expand = expand
|
|
local modified_insert = {}
|
|
for i, v in pairs(insert) do
|
|
modified_insert[i] = v
|
|
end
|
|
local offset = 0
|
|
local last_pos = 0
|
|
|
|
while true do
|
|
local newline_pos = string.find(expand, '\n', last_pos + 1)
|
|
if not newline_pos then break end
|
|
|
|
-- prepend string
|
|
local insert_pos = newline_pos + offset + 1
|
|
local prefix = (indent and '<>' or '') .. prepend
|
|
modified_expand = string.sub(modified_expand, 1, insert_pos - 1)
|
|
.. prefix
|
|
.. string.sub(modified_expand, insert_pos)
|
|
offset = offset + #prefix
|
|
|
|
-- indent node
|
|
if indent then
|
|
local expand_before = string.sub(modified_expand, 1, insert_pos + 1)
|
|
local indent_pos = select(2, string.gsub(expand_before, '<>', ''))
|
|
table.insert(modified_insert, indent_pos, M.leading_white_spaces(indent_capture_idx))
|
|
end
|
|
last_pos = newline_pos
|
|
end
|
|
return modified_expand, modified_insert
|
|
end
|
|
|
|
function M.start_snip_in_newl(trigger, expand, insert, condition, priority, options)
|
|
return M.snip(
|
|
'([^\\s]\\s+)' .. trigger,
|
|
'<>\n' .. expand,
|
|
{ M.cap(1), unpack(insert) },
|
|
condition,
|
|
priority,
|
|
options
|
|
)
|
|
end
|
|
|
|
function M.list_snip(trigger, expand, insert, condition, priority, options)
|
|
return M.snip(
|
|
'(^\\s*(-|\\+|\\d+\\.)\\s+.*\\s+)' .. trigger,
|
|
'<>' .. expand,
|
|
{ M.cap(1), unpack(insert) },
|
|
condition,
|
|
priority,
|
|
vim.tbl_deep_extend('keep', { indentCaptureIdx = 1 }, options or {})
|
|
)
|
|
end
|
|
return M
|