mirror of
https://github.com/Ascyii/typstar.git
synced 2026-01-01 05:24:24 -05:00
Merge branch 'dev' into index-confilicts-readable-typst
This commit is contained in:
@@ -22,8 +22,14 @@ end
|
||||
|
||||
function M.scan() run_typstar_anki('') end
|
||||
|
||||
function M.scan_reimport() run_typstar_anki('--reimport') end
|
||||
|
||||
function M.scan_force() run_typstar_anki('--force-scan ' .. vim.fn.getcwd()) end
|
||||
|
||||
function M.scan_force_reimport() run_typstar_anki('--reimport --force-scan ' .. vim.fn.getcwd()) end
|
||||
|
||||
function M.scan_force_current() run_typstar_anki('--force-scan ' .. vim.fn.expand('%:p')) end
|
||||
|
||||
function M.scan_force_current_reimport() run_typstar_anki('--reimport --force-scan ' .. vim.fn.expand('%:p')) end
|
||||
|
||||
return M
|
||||
|
||||
@@ -46,12 +46,13 @@ end
|
||||
|
||||
function M.snip(trigger, expand, insert, condition, priority, wordTrig)
|
||||
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 },
|
||||
wordTrig = false,
|
||||
priority = priority,
|
||||
snippetType = 'autosnippet',
|
||||
},
|
||||
@@ -68,6 +69,17 @@ end
|
||||
|
||||
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
|
||||
- utils.count_string(trigger, '\\')
|
||||
- utils.count_string(trigger, '%(')
|
||||
- utils.count_string(trigger, '%)')
|
||||
end
|
||||
|
||||
-- cache preanalysis results
|
||||
local condition = function()
|
||||
local cached = lexical_result_cache[opts.condition]
|
||||
if cached ~= nil and cached[1] == last_keystroke_time then return cached[2] end
|
||||
@@ -75,9 +87,28 @@ function M.engine(trigger, opts)
|
||||
lexical_result_cache[opts.condition] = { last_keystroke_time, result }
|
||||
return result
|
||||
end
|
||||
|
||||
-- matching
|
||||
return function(line, trig)
|
||||
if not M.snippets_toggle or not condition() then return nil end
|
||||
return base_engine(line, trig)
|
||||
if fixed_length ~= nil then
|
||||
local first_idx = #line - fixed_length -- include additional char for wordtrig
|
||||
if first_idx < 0 then
|
||||
return nil
|
||||
elseif first_idx > 0 then
|
||||
if string.byte(line, first_idx) > 127 then return nil end
|
||||
end
|
||||
line = line:sub(first_idx)
|
||||
end
|
||||
local whole, captures = base_engine(line, trig)
|
||||
if whole == nil then return nil end
|
||||
|
||||
-- custom word trig
|
||||
local from = #line - #whole + 1
|
||||
if opts.wordTrig and from ~= 1 and string.match(string.sub(line, from - 1, from - 1), '[%w.]') ~= nil then
|
||||
return nil
|
||||
end
|
||||
return whole, captures
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
local M = {}
|
||||
|
||||
local default_config = {
|
||||
typstarRoot = '~/typstar',
|
||||
typstarRoot = nil,
|
||||
anki = {
|
||||
typstarAnkiCmd = 'typstar-anki',
|
||||
typstCmd = 'typst',
|
||||
@@ -30,6 +30,9 @@ local default_config = {
|
||||
|
||||
function M.merge_config(args)
|
||||
M.config = vim.tbl_deep_extend('force', default_config, args or {})
|
||||
M.config.typstarRoot = M.config.typstarRoot
|
||||
or debug.getinfo(1).source:match('^@(.*)/lua/typstar/config%.lua$')
|
||||
or '~/typstar'
|
||||
M.config.excalidraw.templatePath = M.config.excalidraw.templatePath
|
||||
or {
|
||||
['%.excalidraw%.md$'] = M.config.typstarRoot .. '/res/excalidraw_template.excalidraw.md',
|
||||
|
||||
@@ -14,8 +14,11 @@ M.setup = function(args)
|
||||
vim.api.nvim_create_user_command('TypstarOpenExcalidraw', excalidraw.open_drawing, {})
|
||||
|
||||
vim.api.nvim_create_user_command('TypstarAnkiScan', anki.scan, {})
|
||||
vim.api.nvim_create_user_command('TypstarAnkiReimport', anki.scan_reimport, {})
|
||||
vim.api.nvim_create_user_command('TypstarAnkiForce', anki.scan_force, {})
|
||||
vim.api.nvim_create_user_command('TypstarAnkiForceReimport', anki.scan_force_reimport, {})
|
||||
vim.api.nvim_create_user_command('TypstarAnkiForceCurrent', anki.scan_force_current, {})
|
||||
vim.api.nvim_create_user_command('TypstarAnkiForceCurrentReimport', anki.scan_force_current_reimport, {})
|
||||
|
||||
autosnippets.setup()
|
||||
end
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
local ls = require('luasnip')
|
||||
local d = ls.dynamic_node
|
||||
local i = ls.insert_node
|
||||
local s = ls.snippet_node
|
||||
local t = ls.text_node
|
||||
local helper = require('typstar.autosnippets')
|
||||
@@ -8,15 +9,15 @@ local cap = helper.cap
|
||||
local math = helper.in_math
|
||||
local markup = helper.in_markup
|
||||
|
||||
local letter_snippets = {}
|
||||
local greek_letters_map = {
|
||||
['a'] = 'alpha',
|
||||
['b'] = 'beta',
|
||||
['c'] = 'chi',
|
||||
['d'] = 'delta',
|
||||
['e'] = 'epsilon',
|
||||
['f'] = 'phi',
|
||||
['g'] = 'gamma',
|
||||
['h'] = 'phi',
|
||||
['h'] = 'eta',
|
||||
['i'] = 'iotta',
|
||||
['j'] = 'theta',
|
||||
['k'] = 'kappa',
|
||||
@@ -41,6 +42,8 @@ local common_indices = { '\\d+', '[i-n]' }
|
||||
-- buitins and caligraphic letters from github.com/lentilus/readable-typst
|
||||
local index_conflicts = { 'in', 'ln', 'pi', 'xi', 'Ii', 'Jj', 'Kk', 'Ll', 'Mm', 'Nn' }
|
||||
local index_conflicts_set = {}
|
||||
local punctuation_prepend_space = { ',', ';' }
|
||||
local punctuation_prepend_space_set = {}
|
||||
local trigger_greek = ''
|
||||
local trigger_index_pre = ''
|
||||
local trigger_index_post = ''
|
||||
@@ -59,10 +62,15 @@ for latin, greek in pairs(greek_letters_map) do
|
||||
table.insert(greek_keys, latin:upper())
|
||||
end
|
||||
|
||||
for _, conflict in ipairs(index_conflicts) do
|
||||
index_conflicts_set[conflict] = true
|
||||
local generate_bool_set = function(arr, target)
|
||||
for _, val in ipairs(arr) do
|
||||
target[val] = true
|
||||
end
|
||||
end
|
||||
|
||||
generate_bool_set(index_conflicts, index_conflicts_set)
|
||||
generate_bool_set(punctuation_prepend_space, punctuation_prepend_space_set)
|
||||
|
||||
greek_letters_map = greek_full
|
||||
trigger_greek = table.concat(greek_keys, '|')
|
||||
trigger_index_pre = '[A-Za-z]' .. '|' .. table.concat(greek_letters_set, '|')
|
||||
@@ -70,31 +78,62 @@ trigger_index_post = table.concat(common_indices, '|')
|
||||
|
||||
local get_greek = function(_, snippet) return s(nil, t(greek_letters_map[snippet.captures[1]])) end
|
||||
|
||||
local get_index = function(_, snippet)
|
||||
local letter, index = snippet.captures[1], snippet.captures[2]
|
||||
local get_index = function(_, snippet, _, idx1, idx2)
|
||||
local letter, index = snippet.captures[idx1], snippet.captures[idx2]
|
||||
local trigger = letter .. index
|
||||
if index_conflicts_set[trigger] then return s(nil, t(trigger)) end
|
||||
return s(nil, t(letter .. '_' .. index))
|
||||
end
|
||||
|
||||
table.insert(letter_snippets, snip(':([A-Za-z0-9])', '$<>$ ', { cap(1) }, markup))
|
||||
table.insert(letter_snippets, snip(';(' .. trigger_greek .. ')', '$<>$ ', { d(1, get_greek) }, markup))
|
||||
table.insert(letter_snippets, snip(';(' .. trigger_greek .. ')', '<>', { d(1, get_greek) }, math))
|
||||
table.insert(
|
||||
letter_snippets,
|
||||
snip(
|
||||
'\\$(' .. trigger_index_pre .. ')\\$' .. '(' .. trigger_index_post .. ') ',
|
||||
'$<>$ ',
|
||||
{ d(1, get_index) },
|
||||
markup,
|
||||
500
|
||||
)
|
||||
)
|
||||
table.insert(
|
||||
letter_snippets,
|
||||
snip('(' .. trigger_index_pre .. ')' .. '(' .. trigger_index_post .. ') ', '<> ', { d(1, get_index) }, math, 200)
|
||||
)
|
||||
local get_series = function(_, snippet)
|
||||
local letter, target = snippet.captures[1], snippet.captures[2]
|
||||
local target_num = tonumber(target)
|
||||
local result
|
||||
if target_num then
|
||||
local res = {}
|
||||
for n = 1, target_num do
|
||||
table.insert(res, string.format('%s_%d', letter, n))
|
||||
if n ~= target_num then table.insert(res, ', ') end
|
||||
end
|
||||
result = table.concat(res, '')
|
||||
else
|
||||
result = string.format('%s_1, %s_2, ..., %s_%s', letter, letter, letter, target)
|
||||
end
|
||||
return s(nil, t(result))
|
||||
end
|
||||
|
||||
local prepend_space = function(_, snippet, _, idx)
|
||||
local punc = snippet.captures[idx]
|
||||
if punctuation_prepend_space_set[punc] then punc = punc .. ' ' end
|
||||
return s(nil, t(punc))
|
||||
end
|
||||
|
||||
return {
|
||||
unpack(letter_snippets),
|
||||
-- latin/greek
|
||||
snip(':([A-Za-z0-9])', '$<>$ ', { cap(1) }, markup),
|
||||
snip(';(' .. trigger_greek .. ')', '$<>$ ', { d(1, get_greek) }, markup),
|
||||
snip(';(' .. trigger_greek .. ')', '<>', { d(1, get_greek) }, math),
|
||||
|
||||
-- indices
|
||||
snip(
|
||||
'\\$(' .. trigger_index_pre .. ')\\$' .. '(' .. trigger_index_post .. ')([^\\w])',
|
||||
'$<>$<>',
|
||||
{ d(1, get_index, {}, { user_args = { 1, 2 } }), d(2, prepend_space, {}, { user_args = { 3 } }) },
|
||||
markup,
|
||||
500
|
||||
),
|
||||
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
|
||||
),
|
||||
|
||||
-- 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
|
||||
|
||||
-- misc
|
||||
snip('(' .. trigger_index_pre .. ')bl', 'B_<> (<>)', { cap(1), i(1, 'x_0') }, math),
|
||||
}
|
||||
|
||||
@@ -36,26 +36,35 @@ return {
|
||||
-- operators
|
||||
snip('ak([^k ])', '+ <>', { cap(1) }, math, 100, false),
|
||||
snip('sk([^k ])', '- <>', { cap(1) }, math, 100, false),
|
||||
snip('oak', 'plus.circle ', {}, math, 1100),
|
||||
snip('bak', 'plus.square ', {}, math, 1100),
|
||||
snip('mak', 'plus.minus ', {}, math, 1100),
|
||||
snip('xx', 'times ', {}, math),
|
||||
snip('oak', 'plus.circle ', {}, math),
|
||||
snip('bak', 'plus.square ', {}, math),
|
||||
snip('mak', 'plus.minus ', {}, math),
|
||||
snip('xx', 'times ', {}, math, 900),
|
||||
snip('oxx', 'times.circle ', {}, math),
|
||||
snip('bxx', 'times.square ', {}, math),
|
||||
snip('ff', '(<>) / (<>) <>', { i(1, 'a'), i(2, 'b'), i(3) }, math),
|
||||
|
||||
-- exponents
|
||||
snip('iv', '^(-1) ', {}, math, 500, false),
|
||||
snip('sr', '^2 ', {}, math, 500, false),
|
||||
snip('cb', '^3 ', {}, math, 500, false),
|
||||
snip('jj', '_(<>) ', { i(1, 'n') }, math, 500, false),
|
||||
snip('kk', '^(<>) ', { i(1, 'n') }, math, 500, false),
|
||||
snip('ep', 'exp(<>) ', { i(1, '1') }, math),
|
||||
|
||||
-- sets
|
||||
-- 'st' to '{<>} in ./visual.lua
|
||||
snip('set', '{<> | <>}', { i(1), i(2) }, math),
|
||||
snip('es', 'emptyset ', {}, math),
|
||||
snip('es', 'emptyset ', {}, math, 900),
|
||||
snip('ses', '{emptyset} ', {}, math),
|
||||
snip('sp', 'supset ', {}, math),
|
||||
snip('sb', 'subset ', {}, math),
|
||||
snip('sep', 'supset.eq ', {}, math),
|
||||
snip('seb', 'subset.eq ', {}, math),
|
||||
snip('nn', 'sect ', {}, math),
|
||||
snip('uu', 'union ', {}, math),
|
||||
snip('bnn', 'sect.big ', {}, math, 1100),
|
||||
snip('buu', 'union.big ', {}, math, 1100),
|
||||
snip('nn', 'sect ', {}, math, 900),
|
||||
snip('uu', 'union ', {}, math, 900),
|
||||
snip('bnn', 'sect.big ', {}, math),
|
||||
snip('buu', 'union.big ', {}, math),
|
||||
snip('swo', 'without ', {}, math),
|
||||
|
||||
-- misc
|
||||
@@ -63,28 +72,22 @@ return {
|
||||
snip('mt', '|->> ', {}, math),
|
||||
snip('Oo', 'compose ', {}, math),
|
||||
snip('iso', 'tilde.equiv ', {}, math),
|
||||
snip('ep', 'exp(<>) ', { i(1, '1') }, math),
|
||||
snip('cc', 'cases(\n\t<>\n)\\', { i(1, '1') }, math),
|
||||
snip('(K|M|N|Q|R|S|Z)([\\dn]) ', '<><>^<> ', { cap(1), cap(1), cap(2) }, math),
|
||||
snip('(.*)iv', '<>^(-1)', { cap(1) }, math),
|
||||
snip('(.*)sr', '<>^2', { cap(1) }, math),
|
||||
snip('(.*)cb', '<>^3', { cap(1) }, math),
|
||||
snip('(.*)jj', '<>_(<>)', { cap(1), i(1, 'n') }, math),
|
||||
snip('(.*)kk', '<>^(<>)', { cap(1), i(1, 'n') }, math),
|
||||
|
||||
snip('ddx', '(d <>)(d <>)', { i(1, 'f'), i(2, 'x') }, math),
|
||||
snip('it', 'integral', {}, math),
|
||||
snip('int', 'integral_(<>)^(<>)', { i(1, 'a'), i(2, 'b') }, math),
|
||||
snip('oit', 'integral_Omega', {}, math),
|
||||
snip('dit', 'integral_(<>)', { i(1, 'Omega') }, math),
|
||||
snip('ddx', '(d <>)(d <>) ', { i(1, 'f'), i(2, 'x') }, math),
|
||||
snip('it', 'integral ', {}, math, 900),
|
||||
snip('int', 'integral_(<>)^(<>) ', { i(1, 'a'), i(2, 'b') }, math),
|
||||
snip('oit', 'integral_Omega ', {}, math),
|
||||
snip('dit', 'integral_(<>) ', { i(1, 'Omega') }, math),
|
||||
|
||||
snip('sm', 'sum ', {}, math),
|
||||
snip('sum', 'sum_(<>)^(<>)', { i(1, 'i=0'), i(2, 'oo') }, math),
|
||||
snip('osm', 'sum_Omega', {}, math),
|
||||
snip('dsm', 'sum_(<>)', { i(1, 'I') }, math),
|
||||
snip('sm', 'sum ', {}, math, 900),
|
||||
snip('sum', 'sum_(<>)^(<>) ', { i(1, 'i=0'), i(2, 'oo') }, math),
|
||||
snip('osm', 'sum_Omega ', {}, math),
|
||||
snip('dsm', 'sum_(<>) ', { i(1, 'I') }, 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 (sup|inf)', 'lim<> <>', { cap(1), i(1, 'a_n') }, math),
|
||||
snip('lim(_.*-.*) (sup|inf)', 'lim<><> <>', { cap(2), cap(1), i(1, 'a_n') }, math),
|
||||
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),
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ local smart_wrap = function(args, parent, old_state, expand)
|
||||
end
|
||||
|
||||
for _, val in pairs(operations) do
|
||||
table.insert(snippets, snip(val[1], '<>', { d(1, smart_wrap, {}, { user_args = { val } }) }, math, 1000, false))
|
||||
table.insert(snippets, snip(val[1], '<>', { d(1, smart_wrap, {}, { user_args = { val } }) }, math, 1500, false))
|
||||
end
|
||||
|
||||
return {
|
||||
|
||||
@@ -46,6 +46,11 @@ function M.run_shell_command(cmd, show_output)
|
||||
end
|
||||
end
|
||||
|
||||
function M.count_string(str, tocount)
|
||||
local _, count = str:gsub(tocount, '')
|
||||
return count
|
||||
end
|
||||
|
||||
function M.char_to_hex(c) return string.format('%%%02X', string.byte(c)) end
|
||||
|
||||
function M.urlencode(url)
|
||||
|
||||
Reference in New Issue
Block a user