Snippet expansion fails intermittently
victoriastuart opened this issue · 2 comments
Apologies if this is a FAQ. Examples:
-
when I expand
pp
to<p></p>
after a word or at the end of a line, it works:<p><cursor></p>
-
when I expand
<li> pp
(<li>
triggered byli <tab>
) it fails to complete to<li> <p><cursor</p>
- i.e., I type
li <tab> pp <tab>
expecting to get<li> <p><cursor</p>
, but instead get<li> pp
, with the [block] cursor positioned over the firstp
inpp
- i.e., I type
-
similarly fails when trying to expand the
i
, inside<b>i</b>
, in a 2-step process:b <tab>
giving<b></b>
with cursor auto-positioned between those tags, so I can typei <tab>
- i.e., if I type
b <tab> i <tab>
I get<b>i</b><cursor>
, not the expected<b><i><cursor></i></b>
- i.e., if I type
So, I constantly have to reposition the cursor and press <tab>
to complete the expansion.
It appears to be an issue with completion of the second of two concurrent snippet expansions, perhaps exacerbated by the cursor repositioning (${1}
)?
For reference, here are the snippets mentioned:
snippet pp
<p>${1:}</p>
snippet li
<li> ${1:}
snippet b
<b>${1:}</b>
snippet i
<i>${1:}</i>
This is actually working as intended, though your confusion is totally understandable.
For each of your snippets, SnipMate adds a $0
to the end of it, which indicates where the cursor should be when the snippet is done with. By default SnipMate maps <tab>
to a function that first tries to jump to the next tabstop. If none exists, only then does it trigger the snippet before the cursor. So when you're hitting tab, SnipMate jumps to that zero tabstop instead of triggering your snippet like you expect.
There are two possible solutions here: you can change your snippets so that the zero tabstop is inside the HTML tag, something like <p>$0</p>
, or you can create another insert mode mapping that always triggers a snippet, whether you're in one already or not. That would look like :imap <C-J> <Plug>snipMateTrigger
where ` is the key you want to map to. The map probably makes more sense for you.
The relevant sections in the help are :h SnipMate-zero-tabstop
and :h SnipMate-mappings
.
Hi Adnan: thank you for your reply. I played around a bit, finding a solution. In the second example above,
I type
li <tab> pp <tab>
expecting to get<li> <p><cursor</p>
, but instead get<li> pp
, with the [block] cursor positioned over the firstp
inpp
... I solved this by removing the ${1:}
in my li
snippet:
snippet li
<li>
not
snippet li
<li> ${1:}
Likewise I solved the other examples shown by editing my snippets (replacing ${1:}
with ${0}
:
snippet b
<b>${0:}</b>
snippet i
<i>${0:}</i>
not
snippet b
<b>${1:}</b>
snippet i
<i>${1:}</i>
Now, I can get <b><i><cursor></i></b>
(or the reciprocal, <i><b><cursor></b></i>
) through a b <tab> i <tab>
(etc.) keypress sequence. :-)
While I could have simply defined a "two-in-one snippet," e.g.
snippet bi
<b><i>${1:}</i></b> ${0:}
... I needed to understand this behavior, as it affects some other tandem snippet combinations.
Thank you for your kind response and your work; much appreciated! :-)