Can a snippet dynamically remove parts of itself?

Asked by Nate Jones

This is primarily for my puppet snippets. There currently is a snippet like this:

snippet user "user resource type" b
group { "${1:username}":
    ensure => ${2:present},
    uid => ${3:uid},
    gid => ${4:gid},
    comment => '${5:gecos}',
    home => '${6:homedirectory}',
    managehome => false,
    require => Group["${7:group}"],
endsnippet

So the problem I'd like to solve is: how can I eliminate fields from this resource that I don't want to specify. I could Ctrl-J past them and then delete them afterward, but it'd be nice to eliminate a line (like the "comment =>" one, for instance), if I Ctrl-J through it without entering any data.

That way, I can make my puppet snippets contain all the keys without needing to do a lot of post editing.

"group<tab>user<ctrl-j>present<ctrl-j>123<ctrl-j>123<ctrl-j><ctrl-j>/home/user<ctrl-j>user" would end up with:

group { "user":
    ensure => present,
    uid => 123,
    gid => 123,
    home => '/home/user',
    managehome => false,
    require => Group["user"],

Is this possible?

BTW, thanks for a fantastic plugin. I'll have some improved puppet snippets to contribute soon.

Question information

Language:
English Edit question
Status:
Answered
For:
UltiSnips Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:
Revision history for this message
SirVer (sirver) said :
#1

Hi and sorry for the late reply; I was travelling and had no sense for doing my email :P

What you want to achieve is possible but not very pretty. I solved it here using a global python block that conditionally checks if a tabstop number has any text in it (len > 0) and returns a default text, otherwise it returns "". I use this to sandwich the first line of your example: if tabstop 2 has len > 0, then "ensure => " will appear on its left and ",<newline><tab>" will appear on its right. You can repeat and chain this monster but the snippet because very hard to read. You can delete the line by hitting backspace over it's default text.

global !p
_c = lambda t, c, text: text if len(t[c]) else ""
endglobal

snippet user "user resource type" b
group { "${1:username}":
    `!p snip.rv = _c(t, 2, "ensure => ")`${2:present}`!p snip.rv = _c(t, 2, ",\n\t")`uid => ${3:uid},
    gid => ${4:gid},
    comment => '${5:gecos}',
    home => '${6:homedirectory}',
    managehome => false,
    require => Group["${7:group}"],
endsnippet

Another even harder to read solution would be to use conditional transformations. I prefer this python based solution. Here is the full (unreadable) solution of your example. I do not speak ruby very well, so it might contain syntax errors in its final result:

global !p
_c = lambda t, c, text: text if len(t[c]) else ""
endglobal

snippet user "user resource type" b
group { "${1:username}":
    `!p snip.rv = _c(t, 2, "ensure => ")`${2:present}`!p snip.rv = _c(t, 2, ",\n\t")``!p snip.rv = _c(t, 3, "uid => ")`${3:123}`!p snip.rv = _c(t, 3, ",\n\t")``!p snip.rv = _c(t, 4, "gid => ")`${4:123}`!p snip.rv = _c(t, 4, ",\n\t")``!p snip.rv = _c(t, 5, "comment => ")`${5:gecos}`!p snip.rv = _c(t, 5, ",\n\t")``!p snip.rv = _c(t, 6, "home => ")`${6:homedirectory}`!p snip.rv = _c(t, 6, ",\n\t")`managehome => false,
    `!p snip.rv = _c(t, 7, "require => Group[\"")`${7:group}`!p snip.rv = _c(t, 7, "\"],\n\t")`
endsnippet

Looking forward to your improved snippets contribution :)

Can you help with this problem?

Provide an answer of your own, or ask Nate Jones for more information if necessary.

To post a message you must log in.