Merge pull request #1 from arne314/dev

Big performance improvements and snippets for common indices
This commit is contained in:
arne314
2024-12-08 22:17:09 +01:00
committed by GitHub
6 changed files with 126 additions and 31 deletions

View File

@@ -1,16 +1,30 @@
local M = {} local M = {}
local cfg = require('typstar.config').config.snippets local cfg = require('typstar.config').config.snippets
local utils = require('typstar.utils')
local luasnip = require('luasnip') local luasnip = require('luasnip')
local fmta = require('luasnip.extras.fmt').fmta local fmta = require('luasnip.extras.fmt').fmta
local lsengines = require('luasnip.nodes.util.trig_engines')
local ts = vim.treesitter
M.in_math = function() return vim.api.nvim_eval('typst#in_math()') == 1 end local last_keystroke_time = nil
M.in_markup = function() return vim.api.nvim_eval('typst#in_markup()') == 1 end vim.api.nvim_create_autocmd('TextChangedI', {
M.in_code = function() return vim.api.nvim_eval('typst#in_code()') == 1 end callback = function()
M.in_comment = function() return vim.api.nvim_eval('typst#in_comment()') == 1 end last_keystroke_time = vim.loop.now()
end,
})
local lexical_result_cache = {}
local ts_markup_query = ts.query.parse('typst', '(text) @markup')
local ts_math_query = ts.query.parse('typst', '(math) @math')
local ts_string_query = ts.query.parse('typst', '(string) @string')
M.in_math = function()
local cursor = utils.get_cursor_pos()
return utils.cursor_within_treesitter_query(ts_math_query, 0, cursor)
and not utils.cursor_within_treesitter_query(ts_string_query, 0, cursor)
end
M.in_markup = function() return utils.cursor_within_treesitter_query(ts_markup_query, 2) end
M.not_in_math = function() return not M.in_math() end M.not_in_math = function() return not M.in_math() end
M.not_in_markup = function() return not M.in_markup() end M.not_in_markup = function() return not M.in_markup() end
M.not_in_code = function() return not M.in_code() end
M.not_in_comment = function() return not M.in_comment() end
M.snippets_toggle = true M.snippets_toggle = true
function M.cap(i) function M.cap(i)
@@ -32,25 +46,46 @@ end
function M.snip(trigger, expand, insert, condition, priority) function M.snip(trigger, expand, insert, condition, priority)
priority = priority or 1000 priority = priority or 1000
return luasnip.snippet( return luasnip.snippet(
{ trig = trigger, regTrig = true, wordtrig = false, priority = priority, snippetType = 'autosnippet' }, {
trig = trigger,
trigEngine = M.engine,
trigEngineOpts = { condition = condition },
priority = priority,
snippetType = 'autosnippet'
},
fmta(expand, { unpack(insert) }), fmta(expand, { unpack(insert) }),
{ {
condition = function() condition = function() return M.snippets_toggle end
if not M.snippets_toggle then
return false
end
return condition()
end
} }
) )
end end
function M.start_snip(trigger, expand, insert, condition, priority) function M.start_snip(trigger, expand, insert, condition, priority)
return M.snip('^%s*' .. trigger, expand, insert, condition, priority) return M.snip('^\\s*' .. trigger, expand, insert, condition, priority)
end
function M.engine(trigger, opts)
local base_engine = lsengines.ecma(trigger, opts)
local condition = function()
local cached = lexical_result_cache[opts.condition]
if cached ~= nil and cached[1] == last_keystroke_time then
return cached[2]
end
local result = opts.condition()
lexical_result_cache[opts.condition] = { last_keystroke_time, result }
return result
end
return function(line, trig)
if not M.snippets_toggle or not condition() then
return nil
end
return base_engine(line, trig)
end
end end
function M.toggle_autosnippets() function M.toggle_autosnippets()
M.snippets_toggle = not M.snippets_toggle M.snippets_toggle = not M.snippets_toggle
print(string.format('%sabled typstar autosnippets', M.snippets_toggle and 'En' or 'Dis'))
end end
function M.setup() function M.setup()

View File

@@ -1,7 +1,11 @@
local helper = require('typstar.autosnippets') local helper = require('typstar.autosnippets')
local snip = helper.snip local snip = helper.snip
local cap = helper.cap
local math = helper.in_math
local markup = helper.in_markup
local letters = { local letter_snippets = {}
local greek_letters = {
{ 'a', 'alpha' }, { 'A', 'Alpha' }, { 'a', 'alpha' }, { 'A', 'Alpha' },
{ 'b', 'beta' }, { 'B', 'Beta' }, { 'b', 'beta' }, { 'B', 'Beta' },
{ 'c', 'chi' }, { 'C', 'Chi' }, { 'c', 'chi' }, { 'C', 'Chi' },
@@ -24,13 +28,32 @@ local letters = {
{ 'x', 'xi' }, { 'X', 'xi' }, { 'x', 'xi' }, { 'X', 'xi' },
{ 'z', 'zeta' }, { 'Z', 'Zeta' }, { 'z', 'zeta' }, { 'Z', 'Zeta' },
} }
local latin_letters = { 'f', 'u', 'v', 'w', 'y' } -- remaining ones are added dynamically
local common_indices = { '\\d+', 'i', 'j', 'k', 'n' }
local letter_snippets = {} for _, letter in ipairs({ unpack(latin_letters) }) do
table.insert(latin_letters, letter:upper())
end
for _, val in pairs(letters) do local generate_index_snippets = function(letter)
table.insert(letter_snippets, snip(';' .. val[1], val[2], {}, helper.in_math)) for _, index in pairs(common_indices) do
table.insert(letter_snippets, snip(';' .. val[1], '$' .. val[2] .. '$ ', {}, helper.in_markup)) table.insert(letter_snippets,
table.insert(letter_snippets, snip(':' .. val[1], '$' .. val[1] .. '$ ', {}, helper.in_markup)) snip(letter .. '(' .. index .. ') ', letter .. '_(<>) ', { cap(1) }, math, 200))
table.insert(letter_snippets,
snip('\\$' .. letter .. '\\$(' .. index .. ') ', '$' .. letter .. '_(<>)$ ', { cap(1) }, markup, 200))
end
end
for _, val in pairs(greek_letters) do
table.insert(letter_snippets, snip(';' .. val[1], val[2], {}, math))
table.insert(letter_snippets, snip(';' .. val[1], '$' .. val[2] .. '$ ', {}, markup))
generate_index_snippets(val[2])
table.insert(latin_letters, val[1])
end
for _, letter in pairs(latin_letters) do
generate_index_snippets(letter)
table.insert(letter_snippets, snip(':' .. letter, '$' .. letter .. '$ ', {}, markup))
end end
return { return {

View File

@@ -62,6 +62,8 @@ return {
snip('iso', 'tilde.equiv ', {}, math), snip('iso', 'tilde.equiv ', {}, math),
snip('rrn', 'RR^n ', {}, math), snip('rrn', 'RR^n ', {}, math),
snip('cc', 'cases(\n\t<>\n)\\', { i(1, '1') }, math), snip('cc', 'cases(\n\t<>\n)\\', { i(1, '1') }, math),
snip('pi', 'pi ', {}, math),
snip('in', 'in ', {}, math),
snip('(.*)iv', '<>^(-1)', { cap(1) }, math), snip('(.*)iv', '<>^(-1)', { cap(1) }, math),
snip('(.*)sr', '<>^(2)', { cap(1) }, math), snip('(.*)sr', '<>^(2)', { cap(1) }, math),
snip('(.*)rd', '<>^(<>)', { cap(1), i(1, 'n') }, math), snip('(.*)rd', '<>^(<>)', { cap(1), i(1, 'n') }, math),
@@ -74,8 +76,6 @@ return {
snip('lm', 'lim <>', { i(1, 'a_n') }, math), snip('lm', 'lim <>', { i(1, 'a_n') }, math),
snip('lim', 'lim_(<> ->> <>) <>', { i(1, 'n'), i(2, 'oo'), i(3, 'a_n') }, math), snip('lim', 'lim_(<> ->> <>) <>', { i(1, 'n'), i(2, 'oo'), i(3, 'a_n') }, math),
snip('lim sup', 'limsup <>', { i(1, 'a_n') }, math), snip('lim (sup|inf)', 'lim<> <>', { cap(1), i(1, 'a_n') }, math),
snip('lim(_.*%-.*) sup', 'limsup<> <>', { cap(1), i(1, 'a_n') }, math), snip('lim(_.*-.*) (sup|inf)', 'lim<><> <>', { cap(2), cap(1), i(1, 'a_n') }, math),
snip('lim inf', 'liminf <>', { i(1, 'a_n') }, math),
snip('lim(_.*%-.*) inf', 'liminf<> <>', { cap(1), i(1, 'a_n') }, math),
} }

View File

@@ -78,6 +78,6 @@ local lmat = function(_, sp)
end end
return { return {
snip('(%d)(%d)ma', 'mat(\n\t<>\n)', { d(1, mat) }, math), snip('(\\d)(\\d)ma', 'mat(\n\t<>\n)', { d(1, mat) }, math),
snip('(%d)(%d)lma', 'mat(\n\t<>\n)', { d(1, lmat) }, math), snip('(\\d)(\\d)lma', 'mat(\n\t<>\n)', { d(1, lmat) }, math),
} }

View File

@@ -14,7 +14,7 @@ local operations = { -- boolean denotes whether an additional layer of () bracke
{ 'vi', '1/(', ')', true }, { 'vi', '1/(', ')', true },
{ 'bb', '(', ')', false }, { 'bb', '(', ')', false },
{ 'sq', '[', ']', true }, { 'sq', '[', ']', true },
{ 'abs', '|', '|', false }, { 'abs', 'abs(', ')', false },
{ 'ul', 'underline(', ')', false }, { 'ul', 'underline(', ')', false },
{ 'ol', 'overline(', ')', false }, { 'ol', 'overline(', ')', false },
{ 'ub', 'underbrace(', ')', false }, { 'ub', 'underbrace(', ')', false },
@@ -61,12 +61,12 @@ end
for _, val in pairs(operations) do for _, val in pairs(operations) do
table.insert(snippets, snip(val[1], val[2] .. '<>' .. val[3], { d(1, get_visual) }, math)) table.insert(snippets, snip(val[1], val[2] .. '<>' .. val[3], { d(1, get_visual) }, math))
table.insert(snippets, snip('[%s$]' .. val[1], val[2] .. '<>' .. val[3], { i(1, '1') }, math)) table.insert(snippets, snip('[\\s$]' .. val[1], val[2] .. '<>' .. val[3], { i(1, '1') }, math))
table.insert(snippets, table.insert(snippets,
snip('([%w]+)' snip('([\\w]+)'
.. val[1], val[2] .. '<>' .. val[3], { cap(1) }, math, 900)) .. val[1], val[2] .. '<>' .. val[3], { cap(1) }, math, 900))
table.insert(snippets, table.insert(snippets,
snip('(.*[%)|%]|%}])' .. val[1], '<>', { f(wrap_brackets, {}, { user_args = { val } }), nil }, math, 1100)) snip('(.*[\\)|\\]|\\}])' .. val[1], '<>', { f(wrap_brackets, {}, { user_args = { val } }), nil }, math, 1100))
end end
return { return {

View File

@@ -1,7 +1,14 @@
local M = {} local M = {}
local ts = vim.treesitter
function M.get_cursor_pos()
local cursor_row, cursor_col = unpack(vim.api.nvim_win_get_cursor(0))
cursor_row = cursor_row - 1
return { cursor_row, cursor_col }
end
function M.insert_snippet(snip) function M.insert_snippet(snip)
local line_num = vim.fn.getcurpos()[2] local line_num = M.get_cursor_pos()[1] + 1
local lines = {} local lines = {}
for line in snip:gmatch '[^\r\n]+' do for line in snip:gmatch '[^\r\n]+' do
table.insert(lines, line) table.insert(lines, line)
@@ -13,4 +20,34 @@ function M.run_shell_command(cmd)
vim.fn.jobstart(cmd) vim.fn.jobstart(cmd)
end end
function M.cursor_within_treesitter_query(query, match_tolerance, cursor)
cursor = cursor or M.get_cursor_pos()
local bufnr = vim.api.nvim_get_current_buf()
local root = ts.get_parser(bufnr):parse()[1]:root()
for _, match, _ in query:iter_matches(root, bufnr, cursor[1], cursor[1] + 1) do
if match then
local start_row, start_col, _, _ = match[1]:range()
local _, _, end_row, end_col = match[#match]:range()
local matched = M.cursor_within_coords(cursor, start_row, end_row, start_col, end_col,
match_tolerance)
if matched then
return true
end
end
end
return false
end
function M.cursor_within_coords(cursor, start_row, end_row, start_col, end_col, match_tolerance)
if start_row <= cursor[1] and end_row >= cursor[1] then
if start_row == cursor[1] and start_col - match_tolerance >= cursor[2] then
return false
elseif end_row == cursor[1] and end_col + match_tolerance <= cursor[2] then
return false
end
return true
end
return false
end
return M return M