Skip to content

Is there a way to retain the "jumpability" of nested snippets after a luasnip-next-choice call? #1339

@anthony-S93

Description

@anthony-S93

As a simple example, consider the following snippets,

s(
        {
            trig = "eq"
        },
        {
            c(1, {
               sn(nil, {
                    t({"\\begin{equation}", "\t"}),
                    r(1, "body"),
                    t{"", "\\end{equation}"},
                }),
                sn(nil, {
                    t({"\\begin{equation*}", "\t"}),
                    r(1, "body"),
                    t({"", "\\end{equation*}"}),
                })
            })
        },
        {
            stored = {
                ["body"] = i(1, "body")
            }
        }
    ),
    s(
        {
            trig = "test"
        },
        {
            t({"This is a test node!", "Input 1: "}),
            i(1, "val"),
            t({"", "Input 2: "}),
            i(2, "val"),
        }
    ),

What I found is that after a next-choice call, the inner snippet can no longer be jumped into as shown in the following screen recording.

2025-05-05-19-07-34.mp4

Is there a way to override this default behavior? The thing is, I'm using Luasnip to create a bunch of "smart snippets" that make it easier to write LaTeX documents. I've written these snippets to include virtual text hints that can act as a sort of "on-the-fly" documentation to make LaTeX writing more efficient. Here are some examples:

2025-05-05-19-18-36.mp4
2025-05-05-19-25-44.mp4

The problem is that almost all of these snippets involve the nesting of other snippets within a choiceNode. The various configurations and forms of a LaTeX environment (e.g: the align environment) are essentially different choices within a choiceNode. But in LaTeX, an environment can contain many other environments, so it becomes impossible to use the snippet without also invoking another snippet when typing into an insertNode.

One other approach can circumvent this issue. Instead of having a large parent choiceNode containing all the selections, I could split the entire snippet into parts and adding multiple choiceNodes where a choice is needed. For example, instead of doing this:

s(
    {
        trig = "eq",
     }, 
    {
        -- one parent choiceNode containing all selectable variations
        c(1, {
              sn(nil, {
                   -- variant 1
              }),
              sn(nil, {
                  -- variant 2
              })
          })
     }
        
)

I could do this:

s(
    {
        trig = "eq",
     }, 
    {
        -- split the snippet into chunks, keeping the static components as simple nodes while 
        -- adding choiceNodes wherever a selectable component is encountered
        t("some static component"),
        c(1, {
                -- selectable component
                sn(nil, {
                        -- choice 1
                    }),
                sn(nil, {
                       -- choice 2
                })
          }) 
        t("some other static component"),
        c(2, {
                -- another selectable component
               sn(nil, {
                       -- choice 1
               }),
               sn(nil, {
                       -- choice 2
               })
         })
    }
        
)

The latter is in fact my previous approach to writing these snippets before your timely fix of #1334 (thanks, btw). But this approach is less than ideal because it makes it difficult to switch choices. Since the choiceNodes are scattered throughout the snippet, I have to actually jump to those choiceNodes before I can switch choices; in the first approach, I can switch choices anywhere as long as the parent choiceNode is active. This is why the first approach (having a single parent choiceNode) is preferable. But as mentioned above, by having a large parent choiceNode at the top level, the inner snippets can no longer be jumped into after a choice switch has been made.

As a final example, here is a simpler LaTeX snippet I created:

2025-05-05-20-28-42.mp4

The snippet makes the size of the delimiters of the set-builder notation selectable and automatically adjusts the size of the vertical bar based on the selected delimiter size. For example, let's say I'm in the middle of typing something in the "expression" insertNode when I suddenly realize that I need to switch choice to use a larger delimiter. Currently, after I make the choice switch, I can no longer jump into the "expression" insertNode, which may contain other snippets. It would be nice if there's a way to achieve this.

My apologies for all the questions. As you can undoubtedly tell, I'm incredibly new to Luasnip. But even at my current level of usage, I can appreciate how powerful and versatile Luasnip is. Thanks for all your hard work and dedication.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions