perf(snip): consider max trigger length

This commit is contained in:
arne314
2025-01-29 15:36:09 +01:00
parent 00fcd9041f
commit 2481c329f9
3 changed files with 58 additions and 22 deletions

View File

@@ -47,14 +47,14 @@ function M.ri(insert_node_id)
return luasnip.function_node(function(args) return args[1][1] end, insert_node_id)
end
function M.snip(trigger, expand, insert, condition, priority, wordTrig)
function M.snip(trigger, expand, insert, condition, priority, wordTrig, maxTrigLength)
priority = priority or 1000
if wordTrig == nil then wordTrig = true end
return luasnip.snippet(
{
trig = trigger,
trigEngine = M.engine,
trigEngineOpts = { condition = condition, wordTrig = wordTrig },
trigEngineOpts = { condition = condition, wordTrig = wordTrig, maxTrigLength = maxTrigLength },
wordTrig = false,
priority = priority,
snippetType = 'autosnippet',
@@ -70,16 +70,40 @@ function M.start_snip(trigger, expand, insert, condition, priority)
return M.snip('^(\\s*)' .. trigger, '<>' .. expand, { M.cap(1), unpack(insert) }, condition, priority)
end
local alts_regex = '[\\[\\(](.*|.*)[\\)\\]]'
function M.engine(trigger, opts)
local base_engine = lsengines.ecma(trigger, opts)
-- determine possibly fixed length of trigger
local fixed_length
if not trigger:match('[%+%*%?%]%[|]') then
fixed_length = #trigger
-- determine possibly max/fixed length of trigger
local max_length = opts.maxTrigLength
local is_fixed_length = false
if alts_regex ~= '' and not trigger:match('[%+%*]') then
max_length = #trigger
- utils.count_string(trigger, '\\')
- utils.count_string(trigger, '%(')
- utils.count_string(trigger, '%)')
- utils.count_string(trigger, '%?')
is_fixed_length = not trigger:match('[%+%*%?%[%]|]')
local alts_match = alts_regex:match(trigger) -- find longest trigger in [...|...]
if alts_match then
for _, alts in ipairs(alts_match) do
local max_alt_length = 1
for alt in alts:gmatch('([^|]+)') do
local len
if alt:match('%[.*-.*%]') then -- [A-Za-z0-9] and similar
len = 2
else
len = #alt
end
max_alt_length = math.max(max_alt_length, len)
end
max_length = max_length - (#alts - max_alt_length)
end
else -- [^...] and similar
max_length = max_length - utils.count_string(trigger, '%[') - utils.count_string(trigger, '%]')
end
end
-- cache preanalysis results
@@ -94,11 +118,16 @@ function M.engine(trigger, opts)
-- matching
return function(line, trig)
if not M.snippets_toggle or not condition() then return nil end
if fixed_length ~= nil then
local first_idx = #line - fixed_length -- include additional char for wordtrig
if max_length ~= nil then
local first_idx = #line - max_length -- include additional char for wordtrig
if first_idx < 0 then
return nil
elseif first_idx > 0 then
if is_fixed_length then
return nil
else
first_idx = 1
end
end
if first_idx > 0 then
if string.byte(line, first_idx) > 127 then return nil end
end
line = line:sub(first_idx)
@@ -122,6 +151,16 @@ end
function M.setup()
if cfg.enable then
local jsregexp_ok, jsregexp = pcall(require, 'luasnip-jsregexp')
if not jsregexp_ok then
jsregexp_ok, jsregexp = pcall(require, 'jsregexp')
end
if jsregexp_ok then
alts_regex = jsregexp.compile_safe(alts_regex)
else
alts_regex = ''
vim.notify("WARNING: Most snippets won't work as jsregexp is not installed", vim.log.levels.WARN)
end
local autosnippets = {}
for _, file in ipairs(cfg.modules) do
for _, sn in ipairs(require(('typstar.snippets.%s'):format(file))) do
@@ -136,13 +175,6 @@ function M.setup()
end
end
luasnip.add_snippets('typst', autosnippets)
local jsregexp_ok, _ = pcall(require, 'luasnip-jsregexp')
if not jsregexp_ok then
jsregexp_ok, _ = pcall(require, 'jsregexp')
end
if not jsregexp_ok then
vim.notify("WARNING: Most snippets won't work as jsregexp is not installed", vim.log.levels.WARN)
end
end
end

View File

@@ -19,7 +19,7 @@ local greek_letters_map = {
['f'] = 'phi',
['g'] = 'gamma',
['h'] = 'eta',
['i'] = 'iotta',
['i'] = 'iota',
['j'] = 'theta',
['k'] = 'kappa',
['l'] = 'lambda',
@@ -115,19 +115,23 @@ return {
'$<>$<>',
{ d(1, get_index, {}, { user_args = { 1, 2 } }), d(2, prepend_space, {}, { user_args = { 3 } }) },
markup,
500
500,
true,
13
),
snip(
'(' .. trigger_index_pre .. ')' .. '(' .. trigger_index_post .. ')([^\\w])',
'<><>',
{ d(1, get_index, {}, { user_args = { 1, 2 } }), d(2, prepend_space, {}, { user_args = { 3 } }) },
math,
200
200,
true,
10 -- epsilon123
),
-- series of numbered letters
snip('(' .. trigger_index_pre .. ') ot ', '<>_1, <>_2, ... ', { cap(1), cap(1) }, math), -- a_1, a_2, ...
snip('(' .. trigger_index_pre .. ') ot(\\w+) ', '<> ', { d(1, get_series) }, math), -- a_1, a_2, ... a_j or a_1, a_2, a_2, a_3, a_4, a_5
snip('(' .. trigger_index_pre .. ') ot(\\w+) ', '<> ', { d(1, get_series) }, math, 1000, true, 13), -- a_1, a_2, ... a_j or a_1, a_2, a_2, a_3, a_4, a_5
-- misc
snip('(' .. trigger_index_pre .. ')bl', 'B_<> (<>)', { cap(1), i(1, 'x_0') }, math),

View File

@@ -89,5 +89,5 @@ return {
snip('lm', 'lim ', {}, math),
snip('lim', 'lim_(<> ->> <>) ', { i(1, 'n'), i(2, 'oo') }, math),
snip('lim (sup|inf)', 'lim<> ', { cap(1) }, math),
snip('lim(_\\(\\s?\\w+\\s?->\\s?\\w+\\s?\\)) (sup|inf)', 'lim<><> ', { cap(2), cap(1) }, math),
snip('lim(_\\(\\s?\\w+\\s?->\\s?\\w+\\s?\\)) (sup|inf)', 'lim<><> ', { cap(2), cap(1) }, math, 1000, true, 25),
}