LuaSnip icon indicating copy to clipboard operation
LuaSnip copied to clipboard

Postfix Snippet with nil capture doesn't expand

Open evesdropper opened this issue 1 year ago • 2 comments

Realized that the smart postfix snippets I made earlier don't work in the dynamic/visual cases anymore.

The code is the same as follows from the wiki:

-- dynamic node
-- generally, postfix comes in the form PRE-CAPTURE-POST, so in this case, arg1 is the "pre" text, arg2 the "post" text
local dynamic_postfix = function(_, parent, _, user_arg1, user_arg2) 
    local capture = parent.snippet.env.POSTFIX_MATCH
    if #capture > 0 then
        return sn(nil, fmta([[
        <><><><>
        ]],
        {t(user_arg1), t(capture), t(user_arg2), i(0)}))
    else
        local visual_placeholder = ""
        if #parent.snippet.env.SELECT_RAW > 0 then
            visual_placeholder = parent.snippet.env.SELECT_RAW
        end
        return sn(nil, fmta([[
        <><><><>
        ]],
        {t(user_arg1), i(1, visual_placeholder), t(user_arg2), i(0)}))
    end
end

postfix({ trig="vec", snippetType = "autosnippet"},
    {d(1, dynamic_postfix, {}, { user_args = {"\\vec{", "}"} })},
    { condition = tex.in_math, show_condition = tex.in_math }
    ),

I went and did some tests with the example postfix snippet, experimenting with different captures:

postfix(".br", {
    f(function(_, parent)
        return "[" .. parent.snippet.env.POSTFIX_MATCH .. "]"
    end, {}),
})

If you try to do .br with no capture before, it'll give an error because the capture is nill, and it can't concatenate nil. So I could do something to catch the nil case first, something like this:

postfix({trig = ".br", snippetType = "snippet"}, {
    f(function(_, parent)
        if parent.snippet.env.POSTFIX_MATCH == nil then
            return "bunger"
        end
        return "[" .. parent.snippet.env.POSTFIX_MATCH .. "]"
    end, {}),
    }),

This only works because of LSP detecting the .br snippet and it expands if I foloow the LSP suggestion; however, when I want to manually tab trigger or if I change it to an autosnippet (thus taking it off of LSP), it does not trigger.

Maybe #990 is a similar issue, or the commit that it references might be relevant. If this is the case, would it be possible to enable nil captures?

evesdropper avatar Mar 25 '24 18:03 evesdropper

Ah, it's possible that this is due to #898, and subsequent changes in #974. If I remove these lines, the snippet behaves as it should (AFAICT)

I think the proper way of fixing this is to accept an option that enables the old behaviour, ie. nil-match still expands (default don't accept nil-match, since that seems more common for postfix)

L3MON4D3 avatar Apr 01 '24 19:04 L3MON4D3

Oh hey, much easier: use a match_pattern that accepts an empty string:

postfix({ trig="vec", match_pattern = [[[%w%.%_%-%"%']*$]] },
	{d(1, dynamic_postfix, {}, { user_args = {"\\vec{", "}"} })},
	{ condition = require("luasnip.util.util").yes }
	),

The only difference to the default is a * instead of a + :)

L3MON4D3 avatar Apr 04 '24 06:04 L3MON4D3