Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat(extras): Insert repeat node when duplicated keys occur #665

Merged
merged 4 commits into from
Dec 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion DOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ only apply to some nodes (`user_args` for both function and dynamicNode).
These `opts` are only mentioned if they accept options that are not common to
all nodes.

## Node-Api:

- `get_jump_index()`: this method returns the jump-index of a node. If a node
doesn't have a jump-index, this method returns `nil` instead.

# SNIPPETS

The most direct way to define snippets is `s`:
Expand Down Expand Up @@ -237,7 +242,7 @@ which is passed to the function.
(in most cases `parent == parent.snippet`, but the `parent` of the dynamicNode
is not always the surrounding snippet, it could be a `snippetNode`).

## Api:
## Snippet-Api:

- `invalidate()`: call this method to effectively remove the snippet. The
snippet will no longer be able to expand via `expand` or `expand_auto`. It
Expand Down Expand Up @@ -1204,6 +1209,13 @@ ls.add_snippets("all", {
}, {
delimiters = "<>"
})),
s("example4", fmt([[
repeat {a} with the same key {a}
]], {
a = i(1, "this will be repeat")
}, {
repeat_duplicates = true
}))
})
```

Expand Down Expand Up @@ -1238,6 +1250,9 @@ any way, correspond to the jump-index of the nodes!
when passing multiline strings via `[[]]` (default true).
* `dedent`: remove indent common to all lines in `format`. Again, makes
passing multiline-strings a bit nicer (default true).
* `repeat_duplicates`: repeat nodes when a key is reused instead of copying
the node if it has a jump-index, refer to [jump-index](#jump-index) to
know which nodes have a jump-index (default false).

There is also `require("luasnip.extras.fmt").fmta`. This only differs from `fmt`
by using angle-brackets (`<>`) as the default-delimiter.
Expand Down
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
NVIM_PATH=deps/nvim
TEST_FILE?=$(realpath tests)
nvim:
git clone --depth 1 https://github.com/neovim/neovim ${NVIM_PATH} || (cd ${NVIM_PATH}; git fetch --depth 1; git checkout origin/master)

Expand Down Expand Up @@ -33,4 +34,4 @@ test: nvim jsregexp
# unset both to prevent env leaking into the neovim-build.
# add helper-functions to lpath.
# ";;" in CPATH appends default.
unset LUA_PATH LUA_CPATH; LUASNIP_SOURCE=$(shell pwd) JSREGEXP_PATH=$(shell pwd)/${JSREGEXP_PATH} TEST_FILE=$(realpath tests) BUSTED_ARGS=--lpath=$(shell pwd)/tests/?.lua make -C ${NVIM_PATH} functionaltest
unset LUA_PATH LUA_CPATH; LUASNIP_SOURCE=$(shell pwd) JSREGEXP_PATH=$(shell pwd)/${JSREGEXP_PATH} TEST_FILE=$(realpath ${TEST_FILE}) BUSTED_ARGS=--lpath=$(shell pwd)/tests/?.lua make -C ${NVIM_PATH} functionaltest
22 changes: 20 additions & 2 deletions doc/luasnip.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ Table of Contents *luasnip-table-of-contents*
- Jump-index |luasnip-jump-index|
- Adding Snippets |luasnip-adding-snippets|
2. NODE |luasnip-node|
- Node-Api: |luasnip-node-api:|
3. SNIPPETS |luasnip-snippets|
- Api: |luasnip-api:|
- Snippet-Api: |luasnip-snippet-api:|
4. TEXTNODE |luasnip-textnode|
5. INSERTNODE |luasnip-insertnode|
6. FUNCTIONNODE |luasnip-functionnode|
Expand Down Expand Up @@ -193,6 +194,13 @@ only apply to some nodes (`user_args` for both function and dynamicNode). These
`opts` are only mentioned if they accept options that are not common to all
nodes.

NODE-API: *luasnip-node-api:*


- `get_jump_index()`: this method returns the jump-index of a node. If a node
doesn’t have a jump-index, this method returns `nil` instead.


==============================================================================
3. SNIPPETS *luasnip-snippets*

Expand Down Expand Up @@ -304,7 +312,7 @@ where the snippet can be accessed through the immediate parent
parent.snippet`, but the `parent` of the dynamicNode is not always the
surrounding snippet, it could be a `snippetNode`).

API: *luasnip-api:*
SNIPPET-API: *luasnip-snippet-api:*


- `invalidate()`: call this method to effectively remove the snippet. The
Expand Down Expand Up @@ -1167,6 +1175,13 @@ Simple example:
}, {
delimiters = "<>"
})),
s("example4", fmt([[
repeat {a} with the same key {a}
]], {
a = i(1, "this will be repeat")
}, {
repeat_duplicates = true
}))
})
<

Expand Down Expand Up @@ -1197,6 +1212,9 @@ any way, correspond to the jump-index of the nodes!
when passing multiline strings via `[[]]` (default true).
- `dedent`: remove indent common to all lines in `format`. Again, makes
passing multiline-strings a bit nicer (default true).
- `repeat_duplicates`: repeat nodes when a key is reused instead of copying
the node if it has a jump-index, refer to |luasnip-jump-index| to
know which nodes have a jump-index (default false).


There is also `require("luasnip.extras.fmt").fmta`. This only differs from
Expand Down
11 changes: 10 additions & 1 deletion lua/luasnip/extras/fmt.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ local text_node = require("luasnip.nodes.textNode").T
local wrap_nodes = require("luasnip.util.util").wrap_nodes
local extend_decorator = require("luasnip.util.extend_decorator")
local Str = require("luasnip.util.str")
local rp = require("luasnip.extras").rep

-- https://gist.github.com/tylerneylon/81333721109155b2d244
local function copy3(obj, seen)
Expand Down Expand Up @@ -39,11 +40,13 @@ end
-- opts:
-- delimiters: string, 2 distinct characters (left, right), default "{}"
-- strict: boolean, set to false to allow for unused `args`, default true
-- repeat_duplicates: boolean, repeat nodes which have jump_index instead of copying them, default false
-- Returns: a list of strings and elements of `args` inserted into placeholders
local function interpolate(fmt, args, opts)
local defaults = {
delimiters = "{}",
strict = true,
repeat_duplicates = false,
}
opts = vim.tbl_extend("force", defaults, opts or {})

Expand Down Expand Up @@ -97,7 +100,12 @@ local function interpolate(fmt, args, opts)
-- The nodes are modified in-place as part of constructing the snippet,
-- modifying one node twice will lead to UB.
if used_keys[key] then
table.insert(elements, copy3(args[key]))
local jump_index = args[key]:get_jump_index() -- For nodes that don't have a jump index, copy it instead
if not opts.repeat_duplicates or jump_index == nil then
table.insert(elements, copy3(args[key]))
else
table.insert(elements, rp(jump_index))
end
else
table.insert(elements, args[key])
used_keys[key] = true
Expand Down Expand Up @@ -211,6 +219,7 @@ local function format_nodes(str, nodes, opts)
end
end, parts)
end

extend_decorator.register(format_nodes, { arg_indx = 3 })

return {
Expand Down
5 changes: 5 additions & 0 deletions lua/luasnip/nodes/node.lua
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ Node.update_dependents_static = Node._update_dependents_static
Node.update_all_dependents_static = Node._update_dependents_static

function Node:update() end

function Node:update_static() end

function Node:expand_tabs(tabwidth, indentstr)
Expand Down Expand Up @@ -298,6 +299,10 @@ function Node:get_static_args()
return get_args(self, "get_static_text")
end

function Node:get_jump_index()
return self.pos
end

function Node:set_ext_opts(name)
-- differentiate, either visited or unvisited needs to be set.
if name == "passive" then
Expand Down
58 changes: 58 additions & 0 deletions tests/integration/fmt_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
local helpers = require("test.functional.helpers")(after_each)
local exec_lua, feed = helpers.exec_lua, helpers.feed
local ls_helpers = require("helpers")
local Screen = require("test.functional.ui.screen")

describe("Fmt", function()
local screen

before_each(function()
helpers.clear()
ls_helpers.session_setup_luasnip()
screen = Screen.new(50, 3)
screen:attach()
screen:set_default_attr_ids({
[0] = { bold = true, foreground = Screen.colors.Blue },
[1] = { bold = true, foreground = Screen.colors.Brown },
[2] = { bold = true },
[3] = { background = Screen.colors.LightGray },
})
end)
after_each(function()
screen:detach()
end)

it("Repeat duplicate node with same key", function()
exec_lua([=[
ls.add_snippets("all", {
ls.s(
"repeat",
require("luasnip.extras.fmt").fmt([[
{a} repeat {a}
]],
{ a = ls.i(1) },
{ repeat_duplicates = true }
)
)
})
]=])
feed("irepeat")
exec_lua("ls.expand()")
screen:expect({
grid = [[
^ repeat |
{0:~ }|
{2:-- INSERT --} |
]],
})
feed("asdf")
exec_lua("ls.jump()")
screen:expect({
grid = [[
^asdf repeat asdf |
{0:~ }|
{2:-- INSERT --} |
]],
})
end)
end)
Loading