You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi, I've copied the DynamicNode with user input example, and it looks like the find_dynamic_node cannot find the dynamicNode generated by the tab snippet (The loop in find_dynamic_node returns without dynamic node).
I'm pretty sure I'm doing something wrong here, but I'm not sure what it could be.
A minimal reproducible config is attached below:
Minimal Reproducible Config
localls=require("luasnip")
localutil=require("luasnip.util.util")
localnode_util=require("luasnip.nodes.util")
ls.setup_snip_env()
localfunctionfind_dynamic_node(node)
-- the dynamicNode-key is set on snippets generated by a dynamicNode only (its'-- actual use is to refer to the dynamicNode that generated the snippet).whilenotnode.dynamicNodedonode=node.parentifnotnodethenreturnendendreturnnode.dynamicNodeendlocalexternal_update_id=0-- func_indx to update the dynamicNode with different functions._G.dynamic_node_external_update=function(func_indx)
-- most of this function is about restoring the cursor to the correct-- position+mode, the important part are the few lines from-- `dynamic_node.snip:store()`.-- find current node and the innermost dynamicNode it is inside.localcurrent_node=ls.session.current_nodes[vim.api.nvim_get_current_buf()]
localdynamic_node=find_dynamic_node(current_node)
ifnotdynamic_nodethenreturnend-- to identify current node in new snippet, if it is available.external_update_id=external_update_id+1current_node.external_update_id=external_update_idlocalcurrent_node_key=current_node.key-- store which mode we're in to restore later.localinsert_pre_call=vim.fn.mode() =="i"-- is byte-indexed! Doesn't matter here, but important to be aware of.localcursor_pos_end_relative=util.pos_sub(util.get_cursor_0ind(),
current_node.mark:get_endpoint(
1))
-- leave current generated snippet.node_util.leave_nodes_between(dynamic_node.snip, current_node)
-- call update-function.localfunc=dynamic_node.user_args[func_indx]
iffuncthen-- the same snippet passed to the dynamicNode-function. Any output from func-- should be stored in it under some unused key.func(dynamic_node.parent.snippet)
end-- last_args is used to store the last args that were used to generate the-- snippet. If this function is called, these will most probably not have-- changed, so they are set to nil, which will force an update.dynamic_node.last_args=nildynamic_node:update()
-- everything below here isn't strictly necessary, but it's pretty nice to have.-- try to find the node we marked earlier, or a node with the same key.-- Both are getting equal priority here, it might make sense to give "exact-- same node" higher priority by doing two searches (but that would require-- two searches :( )localtarget_node=dynamic_node:find_node(function(test_node)
return (test_node.external_update_id==external_update_id) or
(current_node_key~=nilandtest_node.key==current_node_key)
end)
iftarget_nodethen-- the node that the cursor was in when changeChoice was called exists-- in the active choice! Enter it and all nodes between it and this choiceNode,-- then set the cursor.node_util.enter_nodes_between(dynamic_node, target_node)
ifinsert_pre_callthen-- restore cursor-position if the node, or a corresponding node,-- could be found.-- It is restored relative to the end of the node (as opposed to the-- beginning). This does not matter if the text in the node is-- unchanged, but if the length changed, we may move the cursor-- relative to its immediate neighboring characters.-- I assume that it is more likely that the text before the cursor-- got longer (since it is very likely that the cursor is just at-- the end of the node), and thus restoring relative to the-- beginning would shift the cursor back.---- However, restoring to any fixed endpoint is likely to not be-- perfect, an interesting enhancement would be to compare the new-- and old text/[neighborhood of the cursor], and find its new position-- based on that.util.set_cursor_0ind(util.pos_add(target_node.mark:get_endpoint(1),
cursor_pos_end_relative))
elsenode_util.select_node(target_node)
end-- set the new current node correctly.ls.session.current_nodes[vim.api.nvim_get_current_buf()] =target_nodeelse-- the marked node wasn't found, just jump into the new snippet noremally.ls.session.current_nodes[vim.api.nvim_get_current_buf()] =dynamic_node.snip:jump_into(1)
endendvim.api.nvim_set_keymap('i', "<C-t>",
'<cmd>lua _G.dynamic_node_external_update(1)<Cr>',
{noremap=true})
vim.api.nvim_set_keymap('s', "<C-t>",
'<cmd>lua _G.dynamic_node_external_update(1)<Cr>',
{noremap=true})
vim.api.nvim_set_keymap('i', "<C-g>",
'<cmd>lua _G.dynamic_node_external_update(2)<Cr>',
{noremap=true})
vim.api.nvim_set_keymap('s', "<C-g>",
'<cmd>lua _G.dynamic_node_external_update(2)<Cr>',
{noremap=true})
localfunctioncolumn_count_from_string(descr)
-- this won't work for all cases, but it's simple to improve-- (feel free to do so! :D )return#(descr:gsub("[^clm]", ""))
end-- function for the dynamicNode.localtab=function(args, snip)
localcols=column_count_from_string(args[1][1])
-- snip.rows will not be set by default, so handle that case.-- it's also the value set by the functions called from dynamic_node_external_update().ifnotsnip.rowsthensnip.rows=1endlocalnodes= {}
-- keep track of which insert-index we're at.localins_indx=1forj=1, snip.rowsdo-- use restoreNode to not lose content when updating.table.insert(nodes, r(ins_indx, tostring(j) .."x1", i(1)))
ins_indx=ins_indx+1fork=2, colsdotable.insert(nodes, t" & ")
table.insert(nodes,
r(ins_indx, tostring(j) .."x" ..tostring(k), i(1)))
ins_indx=ins_indx+1endtable.insert(nodes, t {"\\\\", ""})
end-- fix last node.nodes[#nodes] =t""returnsn(nil, nodes)
endls.config.set_config({enable_autosnippets=true})
ls.add_snippets("tex", {
s({trig="tab", snippetType="autosnippet"}, fmt([[\begin{{tabular}}{{{}}}{}\end{{tabular}}]], {
i(1, "c"), d(2, tab, {1}, {
user_args= {
-- Pass the functions used to manually update the dynamicNode as user args.-- The n-th of these functions will be called by dynamic_node_external_update(n).-- These functions are pretty simple, there's probably some cool stuff one could do-- with `ui.input`function(snip) snip.rows=snip.rows+1end,
-- don't drop below one.function(snip)
snip.rows=math.max(snip.rows-1, 1)
end
}
})
}))
})
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Hi, I've copied the
DynamicNode with user inputexample, and it looks like thefind_dynamic_nodecannot find the dynamicNode generated by thetabsnippet (The loop infind_dynamic_nodereturns without dynamic node).I'm pretty sure I'm doing something wrong here, but I'm not sure what it could be.
A minimal reproducible config is attached below:
Minimal Reproducible Config
Beta Was this translation helpful? Give feedback.
All reactions