Merge pull request #18 from arne314/dev

V1.3.4
This commit is contained in:
Arne
2025-07-12 20:13:13 +02:00
committed by GitHub
12 changed files with 88 additions and 26 deletions

View File

@@ -10,6 +10,8 @@ Neovim plugin for efficient note taking in Typst
### Snippets
Use `:TypstarToggleSnippets` to toggle all snippets at any time.
To efficiently navigate insert nodes and avoid overlapping ones,
use `:TypstarSmartJump` and `:TypstarSmartJumpBack`.
Available snippets can mostly be intuitively derived from [here](././lua/typstar/snippets), they include:
Markup snippets:
@@ -86,7 +88,8 @@ require('typstar').setup({ -- depending on your neovim plugin system
1. Install [LuaSnip](https://github.com/L3MON4D3/LuaSnip/), set `enable_autosnippets = true` and set a visual mode selection key (e.g. `store_selection_keys = '<Tab>'`) in the configuration
2. Install [jsregexp](https://github.com/kmarius/jsregexp) as described [here](https://github.com/L3MON4D3/LuaSnip/blob/master/DOC.md#transformations) (You will see a warning on startup if jsregexp isn't installed properly)
3. Install [nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter) and run `:TSInstall typst`
4. Optional: Setup [ctheorems](https://typst.app/universe/package/ctheorems/) with names like [here](./lua/typstar/snippets/markup.lua)
4. Make sure you haven't remapped `<C-g>`. Otherwise set `add_undo_breakpoints = false` in the [config](#configuration)
5. Optional: Setup [ctheorems](https://typst.app/universe/package/ctheorems/) with names like [here](./lua/typstar/snippets/markup.lua)
### Excalidraw
1. Install [Obsidian](https://obsidian.md/) and create a vault in your typst note taking directory
@@ -136,6 +139,10 @@ The [config](#configuration) allows you to
- disable all snippets via `snippets.enable = false`
- only include specific modules from the snippets folder via e.g. `snippets.modules = { 'letters' }`
- exclude specific triggers via e.g. `snippets.exclude = { 'dx', 'ddx' }`
- disable different behaviors of snippets from the `visual` module
- visual selection via e.g. `snippets.visual_disable = { 'br' }`
- normal snippets (`abs` &#8594; `abs(1+1)`) via e.g. `snippets.visual_disable_normal = { 'abs' }`
- postfix snippets (`xabs` &#8594; `abs(x)`) via e.g. `snippets.visual_disable_postfix = { 'abs' }`
For further customization you can make use of the provided wrappers from within your [LuaSnip](https://github.com/L3MON4D3/LuaSnip/) config.
Let's say you prefer the short `=>` arrow over the long `==>` one and would like to change the `ip` trigger to `imp`.

View File

@@ -52,11 +52,12 @@
store_selection_keys = "<Tab>",
})
require('typstar').setup()
local typstar = require('typstar')
typstar.setup({})
vim.keymap.set({'n', 'i'}, '<M-t>', '<Cmd>TypstarToggleSnippets<CR>', { silent = true, noremap = true })
vim.keymap.set({'n', 'i'}, '<M-j>', function() ls.jump( 1) end, { silent = true, noremap = true })
vim.keymap.set({'n', 'i'}, '<M-k>', function() ls.jump(-1) end, { silent = true, noremap = true })
vim.keymap.set({'n', 'i'}, '<M-j>', '<Cmd>TypstarSmartJump<CR>', { silent = true, noremap = true })
vim.keymap.set({'n', 'i'}, '<M-k>', '<Cmd>TypstarSmartJumpBack<CR>', { silent = true, noremap = true })
EOF
'';
plugins = [

View File

@@ -27,6 +27,9 @@ local default_config = {
'visual',
},
exclude = {}, -- list of triggers to exclude
visual_disable = {}, -- visual.lua: list of triggers to exclude from visual selection mode
visual_disable_normal = {}, -- visual.lua: list of triggers to exclude from normal snippet mode
visual_disable_postfix = {}, -- visual.lua: list of triggers to exclude from postfix snippet mode
},
}

View File

@@ -20,10 +20,10 @@ vim.api.nvim_create_autocmd('TextChangedI', {
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)
return utils.cursor_within_treesitter_query(ts_math_query, 0, 0, cursor)
and not utils.cursor_within_treesitter_query(ts_string_query, 0, 0, cursor)
end
M.in_markup = function() return utils.cursor_within_treesitter_query(ts_markup_query, 2) end
M.in_markup = function() return utils.cursor_within_treesitter_query(ts_markup_query, 1, 2) end
M.not_in_math = function() return not M.in_math() end
M.not_in_markup = function() return not M.in_markup() end
M.snippets_toggle = true

View File

@@ -1,6 +1,7 @@
local M = {}
local config = require('typstar.config')
local luasnip = nil
M.setup = function(args)
config.merge_config(args)
@@ -9,6 +10,8 @@ M.setup = function(args)
local anki = require('typstar.anki')
vim.api.nvim_create_user_command('TypstarToggleSnippets', autosnippets.toggle_autosnippets, {})
vim.api.nvim_create_user_command('TypstarSmartJump', function() M.smart_jump(1) end, {})
vim.api.nvim_create_user_command('TypstarSmartJumpBack', function() M.smart_jump(-1) end, {})
vim.api.nvim_create_user_command('TypstarInsertExcalidraw', excalidraw.insert_drawing, {})
vim.api.nvim_create_user_command('TypstarOpenExcalidraw', excalidraw.open_drawing, {})
@@ -19,8 +22,23 @@ M.setup = function(args)
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
-- source: https://github.com/lentilus/fastex.nvim
M.smart_jump = function(length, x, y, tries)
if luasnip == nil then luasnip = require('luasnip') end
local x2, y2 = unpack(vim.api.nvim_win_get_cursor(0))
local tries = tries or 0
if tries > 10 then return end
if x == nil or y == nil then
x, y = x2, y2
end
if x == x2 and y == y2 then
luasnip.jump(length)
vim.schedule(function() M.smart_jump(length, x, y, tries + 1) end)
end
end
return M

View File

@@ -41,7 +41,7 @@ local greek_keys = {}
local greek_letters_set = {}
local common_indices = { '\\d+', '[i-n]' }
-- buitins and caligraphic letters from github.com/lentilus/readable-typst
local index_conflicts = { 'Im', 'in', 'ln', 'pi', 'xi', 'Ii', 'Jj', 'Kk', 'Ll', 'Mm', 'Nn' }
local index_conflicts = { 'Im', 'in', 'ln', 'Pi', 'pi', 'Xi', 'xi', 'Ii', 'Jj', 'Kk', 'Ll', 'Mm', 'Nn' }
local index_conflicts_set = {}
local punctuation_prepend_space = { ',', ';' }
local punctuation_prepend_space_set = {}

View File

@@ -75,14 +75,14 @@ return {
snip('cc', 'cases(\n\t<>\n)\\', { i(1, '1') }, math),
snip('([A-Za-z])o([A-Za-z0-9])', '<>(<>) ', { cap(1), cap(2) }, math, 100, {
maxTrigLength = 3,
blacklist = { 'bot', 'cos', 'col', 'com', 'con', 'dol', 'dot', 'log', 'loz', 'mod', 'top', 'won', 'xor' },
blacklist = { 'bot', 'col', 'com', 'con', 'cos', 'cot', 'dol', 'dot', 'log', 'loz', 'mod', 'roo', 'top', 'won', 'xor' },
}),
snip('(K|M|N|Q|R|S|Z)([\\dn]) ', '<><>^<> ', { cap(1), cap(1), cap(2) }, math),
snip('dx', 'dif / (dif <>) ', { i(1, 'x') }, math, 900),
snip('ddx', '(dif <>) / (dif <>) ', { i(1, 'f'), i(2, 'x') }, math),
snip('DX', 'partial / (partial <>) ', { i(1, 'x') }, math, 900),
snip('DDX', '(partial <>) / (partial <>) ', { i(1, 'f'), i(2, 'x') }, math),
snip('DX', 'diff / (diff <>) ', { i(1, 'x') }, math, 900),
snip('DDX', '(diff <>) / (diff <>) ', { i(1, 'f'), i(2, 'x') }, math),
snip('part', 'partial ', {}, math, 1600),
snip('it', 'integral ', {}, math, 900),
snip('int', 'integral_(<>)^(<>) ', { i(1, 'a'), i(2, 'b') }, math),

View File

@@ -47,6 +47,8 @@ local lmat = function(_, sp)
for k = 1, cols + 1 do
if k == cols then
table.insert(nodes, t('dots.down, '))
elseif k == cols + 1 then
table.insert(nodes, t('dots.v'))
else
table.insert(nodes, t('dots.v, '))
end

View File

@@ -7,10 +7,17 @@ local t = ls.text_node
local helper = require('typstar.autosnippets')
local utils = require('typstar.utils')
local cfg = require('typstar.config').config.snippets
local math = helper.in_math
local snip = helper.snip
local snippets = {}
local visual_disable = {}
local visual_disable_normal = {}
local visual_disable_postfix = {}
utils.generate_bool_set(cfg.visual_disable, visual_disable)
utils.generate_bool_set(cfg.visual_disable_normal, visual_disable_normal)
utils.generate_bool_set(cfg.visual_disable_postfix, visual_disable_postfix)
local operations = { -- first boolean: existing brackets should be kept; second boolean: brackets should be added
{ 'vi', '1/', '', true, false },
@@ -68,17 +75,31 @@ local smart_wrap = function(args, parent, old_state, expand)
local cursor = utils.get_cursor_pos()
local root = utils.get_treesitter_root(bufnr)
if process_ts_query(bufnr, cursor, ts_wrapnobrackets_query, root, expand[2], expand[3], expand[4] and 0 or 1) then
return s(nil, t())
end
local trigger = expand[1]
local expand1 = expand[5] and expand[2] .. '(' or expand[2]
local expand2 = expand[5] and expand[3] .. ')' or expand[3]
if process_ts_query(bufnr, cursor, ts_wrap_query, root, expand1, expand2) then return s(nil, t()) end
if #parent.env.LS_SELECT_RAW > 0 then
-- visual selection
if not visual_disable[trigger] and #parent.env.LS_SELECT_RAW > 0 then
return s(nil, t(expand1 .. table.concat(parent.env.LS_SELECT_RAW) .. expand2))
end
-- postfix
if not visual_disable_postfix[trigger] then
if
process_ts_query(bufnr, cursor, ts_wrapnobrackets_query, root, expand[2], expand[3], expand[4] and 0 or 1)
or process_ts_query(bufnr, cursor, ts_wrap_query, root, expand1, expand2)
then
return s(nil, t())
end
end
-- normal snippet
if not visual_disable_normal[trigger] then
return s(nil, { t(expand1), i(1, '1+1'), t(expand2) })
else
return s(nil, t(trigger))
end
end
for _, val in pairs(operations) do

View File

@@ -92,25 +92,35 @@ function M.treesitter_match_start_end(match)
return start_row, start_col, end_row, end_col
end
function M.cursor_within_treesitter_query(query, match_tolerance, cursor)
function M.cursor_within_treesitter_query(query, match_tolerance_l, match_tolerance_r, cursor)
cursor = cursor or M.get_cursor_pos()
match_tolerance_l = match_tolerance_l or 0
match_tolerance_r = match_tolerance_r or 0
local bufnr = vim.api.nvim_get_current_buf()
local root = M.get_treesitter_root(bufnr)
for _, match in ipairs(M.treesitter_iter_matches(root, query, bufnr, cursor[1], cursor[1] + 1)) do
for _, nodes in pairs(match) do
local start_row, start_col, end_row, end_col = M.treesitter_match_start_end(nodes)
local matched = M.cursor_within_coords(cursor, start_row, end_row, start_col, end_col, match_tolerance)
local matched = M.cursor_within_coords(
cursor,
start_row,
end_row,
start_col,
end_col,
match_tolerance_l,
match_tolerance_r
)
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)
function M.cursor_within_coords(cursor, start_row, end_row, start_col, end_col, match_tolerance_l, match_tolerance_r)
if start_row <= cursor[1] and end_row >= cursor[1] then
if start_row == cursor[1] and start_col - match_tolerance >= cursor[2] then
if start_row == cursor[1] and start_col - match_tolerance_l >= cursor[2] then
return false
elseif end_row == cursor[1] and end_col + match_tolerance <= cursor[2] then
elseif end_row == cursor[1] and end_col + match_tolerance_r <= cursor[2] then
return false
end
return true

View File

@@ -4,7 +4,7 @@ build-backend = "pdm.backend"
[project]
name = "typstar"
version = "1.3.3"
version = "1.3.4"
description = "Neovim plugin for efficient note taking in Typst"
authors = [
{ name = "arne314" }

2
uv.lock generated
View File

@@ -438,7 +438,7 @@ wheels = [
[[package]]
name = "typstar"
version = "1.3.3"
version = "1.3.4"
source = { editable = "." }
dependencies = [
{ name = "aiohttp" },