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) return luasnip.function_node(function(args) return args[1][1] end, insert_node_id)
end end
function M.snip(trigger, expand, insert, condition, priority, wordTrig) function M.snip(trigger, expand, insert, condition, priority, wordTrig, maxTrigLength)
priority = priority or 1000 priority = priority or 1000
if wordTrig == nil then wordTrig = true end if wordTrig == nil then wordTrig = true end
return luasnip.snippet( return luasnip.snippet(
{ {
trig = trigger, trig = trigger,
trigEngine = M.engine, trigEngine = M.engine,
trigEngineOpts = { condition = condition, wordTrig = wordTrig }, trigEngineOpts = { condition = condition, wordTrig = wordTrig, maxTrigLength = maxTrigLength },
wordTrig = false, wordTrig = false,
priority = priority, priority = priority,
snippetType = 'autosnippet', 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) return M.snip('^(\\s*)' .. trigger, '<>' .. expand, { M.cap(1), unpack(insert) }, condition, priority)
end end
local alts_regex = '[\\[\\(](.*|.*)[\\)\\]]'
function M.engine(trigger, opts) function M.engine(trigger, opts)
local base_engine = lsengines.ecma(trigger, opts) local base_engine = lsengines.ecma(trigger, opts)
-- determine possibly fixed length of trigger -- determine possibly max/fixed length of trigger
local fixed_length local max_length = opts.maxTrigLength
if not trigger:match('[%+%*%?%]%[|]') then local is_fixed_length = false
fixed_length = #trigger 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, '%(')
- 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 end
-- cache preanalysis results -- cache preanalysis results
@@ -94,11 +118,16 @@ function M.engine(trigger, opts)
-- matching -- matching
return function(line, trig) return function(line, trig)
if not M.snippets_toggle or not condition() then return nil end if not M.snippets_toggle or not condition() then return nil end
if fixed_length ~= nil then if max_length ~= nil then
local first_idx = #line - fixed_length -- include additional char for wordtrig local first_idx = #line - max_length -- include additional char for wordtrig
if first_idx < 0 then if first_idx < 0 then
return nil if is_fixed_length then
elseif first_idx > 0 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 if string.byte(line, first_idx) > 127 then return nil end
end end
line = line:sub(first_idx) line = line:sub(first_idx)
@@ -122,6 +151,16 @@ end
function M.setup() function M.setup()
if cfg.enable then 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 = {} local autosnippets = {}
for _, file in ipairs(cfg.modules) do for _, file in ipairs(cfg.modules) do
for _, sn in ipairs(require(('typstar.snippets.%s'):format(file))) do for _, sn in ipairs(require(('typstar.snippets.%s'):format(file))) do
@@ -136,13 +175,6 @@ function M.setup()
end end
end end
luasnip.add_snippets('typst', autosnippets) 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
end end

View File

@@ -19,7 +19,7 @@ local greek_letters_map = {
['f'] = 'phi', ['f'] = 'phi',
['g'] = 'gamma', ['g'] = 'gamma',
['h'] = 'eta', ['h'] = 'eta',
['i'] = 'iotta', ['i'] = 'iota',
['j'] = 'theta', ['j'] = 'theta',
['k'] = 'kappa', ['k'] = 'kappa',
['l'] = 'lambda', ['l'] = 'lambda',
@@ -115,19 +115,23 @@ return {
'$<>$<>', '$<>$<>',
{ d(1, get_index, {}, { user_args = { 1, 2 } }), d(2, prepend_space, {}, { user_args = { 3 } }) }, { d(1, get_index, {}, { user_args = { 1, 2 } }), d(2, prepend_space, {}, { user_args = { 3 } }) },
markup, markup,
500 500,
true,
13
), ),
snip( snip(
'(' .. trigger_index_pre .. ')' .. '(' .. trigger_index_post .. ')([^\\w])', '(' .. trigger_index_pre .. ')' .. '(' .. trigger_index_post .. ')([^\\w])',
'<><>', '<><>',
{ d(1, get_index, {}, { user_args = { 1, 2 } }), d(2, prepend_space, {}, { user_args = { 3 } }) }, { d(1, get_index, {}, { user_args = { 1, 2 } }), d(2, prepend_space, {}, { user_args = { 3 } }) },
math, math,
200 200,
true,
10 -- epsilon123
), ),
-- series of numbered letters -- 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 ', '<>_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 -- misc
snip('(' .. trigger_index_pre .. ')bl', 'B_<> (<>)', { cap(1), i(1, 'x_0') }, math), 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('lm', 'lim ', {}, math),
snip('lim', 'lim_(<> ->> <>) ', { i(1, 'n'), i(2, 'oo') }, math), snip('lim', 'lim_(<> ->> <>) ', { i(1, 'n'), i(2, 'oo') }, math),
snip('lim (sup|inf)', 'lim<> ', { cap(1) }, 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),
} }