L3MON4D3 / LuaSnip

Snippet Engine for Neovim written in Lua.
Apache License 2.0
3.31k stars 234 forks source link

Expose generic conditions for use in snippets #1030

Open bew opened 11 months ago

bew commented 11 months ago

Hello,

I'd like to make a snippet with an insert node that defaults to env.LS_SELECT_RAW when luasnip has a selection 'in store', or something else if not.

Grepping the docs shows there is a require"luasnip.extras.conditions.show".has_selected_text 'function' I could use to check if there is a selection available, but it feels weird to use something from a module mentioning show (as if it was specific to show conditions). I would prefer importing something from luasnip.extras.conditions (generic condition objects), or have a handy simple function (not a condition object) for use in snippets. Could also be used in statusline segment to put an indicator when there is a luasnip text selection available

atticus-sullivan commented 11 months ago

When implementing these condition 'functions'/objects, we started out with luasnip.extras.conditions. The issue is that currently we have two different places where it makes sense to use these conditions, show_condition and condition (relevant for if the snippet can be expanded), which do not share the same API. Therefore we split up the module in conditions.expand and conditions.show to reflect that difference (... .expand contains everything from ... .show as the API is a superset of the show_condition API).

So the naming most probably won't change for this.

Tbh I'm still not sure what exactly your issue is (is it just the naming/organization in modules?). In effect the condition objects from luasnip.extras.conditions.{show,expand} are just simple tables {func = function(...) ... end} (with a special metatable attached). So if you really need to, you could try accessing the underlying function via require"luasnip.extras.conditions.show".has_selected_text.func. But be aware that the contents of that table is kinda an internal representation and might change in the future (although currently I see no reason why it should).

L3MON4D3 commented 11 months ago

I'd like to make a snippet with an insert node that defaults to env.LS_SELECT_RAW when luasnip has a selection 'in store', or something else if not.

Sorry, completely forgot to answer here, with all the other stuff going on :sweat_smile: You can use a dynamicNode and check if the select-variables contain text. For example:

d(1, function(_, parent)
    if #parent.snippet.env.LS_SELECT_DEDENT ~= 0 then
        return sn(nil, {
            t(parent.snippet.env.LS_SELECT_DEDENT)
        })
    else
        return sn(nil, { i(1) })
    end
end
L3MON4D3 commented 11 months ago

Tbh I'm still not sure what exactly your issue is

I think @bew just thought that the condition-function is the only way to check whether there is a selection

bew commented 11 months ago

note: I actually noticed that using has_selected_text from the extra show conditions module always returns false when inside a snippet for some reason. If I instead check that snip.env.LS_SELECT_RAW isn't empty before using it that works correctly.

I think having a nice function would be better though, so my snippet code don't need to depend on what the default / empty value of LS_SELECT_RAW is when there are no selection.

L3MON4D3 commented 11 months ago

note: I actually noticed that using has_selected_text from the extra show conditions module always returns false when inside a snippet for some reason.

Oh, I'll check that out

I think having a nice function would be better though, so my snippet code don't need to depend on what the default / empty value of LS_SELECT_RAW is when there are no selection.

True, hmm.. I think we should add that, but I'm not sure where :D We don't yet have a module with functions for use inside of dynamic/functionNode, and I'm not sure where to put it/what to call it. extras/helpers, maybe

LnLcFlx commented 6 months ago
d(1, function(_, parent)
  if #parent.snippet.env.LS_SELECT_DEDENT ~= 0 then
      return sn(nil, {
          t(parent.snippet.env.LS_SELECT_DEDENT)
      })
  else
      return sn(nil, { i(1) })
  end
end

This workaround has the flaw that the inserted LS_SELECT_DEDENT won't be selected at the end. I am looking for something in the sense of "i(1, LS_SELECT_DEDENT)" but the above solution is basically

which is something different.

I'm migrating from UltiSnips and basically half my snippets use ${1:$VISUAL}}, which is a problem for me.