I would like to define one snippet for a cc-mode if statement and a different one for the preprocessors #if statement. I tried just defining those two:

For if:

# -*- mode: snippet -*-
# name : if (...) { ... }
# key: if
# expand-env: ((yas-also-auto-indent-first-line t))
# --
if ( ${1:condition} ) {

For #if:

# -*- mode: snippet -*-
# name: #if
# key: #if
# expand-env: ((yas-wrap-around-region t))
# --
#if ${1:MODULE_NAME}
#endif // $1

but when I try to complete #if, I get the completion for if. Directly calling M-x yas-insert-snippet with #if as parameter works perfectly...

Thanks, Markus

  • 2
    You wrote twice the same snippet in the question – matteol Sep 15 '17 at 15:59

The main issue here is understanding the priorities yasnippet uses to determine what snippet it should expand.

If I understand the documentation correctly, this is controlled by the yas-key-syntaxes variable which by default is set to: ("w" "w_" "w_." "w_.()" yas-try-key-from-whitespace). This might look rather cryptic if you're not familiar with Emacs syntax classes, but it should be rather clear from the following description:

Yasnippet wants to skip an unknown number of characters backwards to find keywords to expand, so it tests each of the elements of yas-key-syntaxes in turn, using each combination of characters to determine what characters to skip:

  • w Skip any piece of text that matches words.
  • _ Skip any piece of text that matches symbols.
  • . Skip any piece of text that matches punctuation.

In this case, you can fix your #if snippet by changing the yas-key-syntax priorities to try "w." before "w" or "w_" since # belong to the punctuation syntax class. I.e.,:

(setq yas-key-syntaxes '("w." "w" "w_" "w_." "w_.()" yas-try-key-from-whitespace))

Personally, I would bind the snippet to a different keyword, such as pif (pp for pre-processor) instead, but feel free to try it out.

It might also be useful to check out M-x describe-syntax, to figure out what characters belong to which syntax class in a particular major mode.

| improve this answer | |
  • Thank you for that explanation :) Since I want to mess with these settings as little as possible, I'll go the way of renaming my #if to something different. – Markus Sep 19 '17 at 8:49
  • Actually I am considering reversing the default of order of yas-key-syntaxes, which should allow #if and if keys to work, see #805. – npostavs Sep 19 '17 at 12:28
  • I thought about it some more, and I actually agree @npostavs. I think it makes sense to try as many characters as possible first and then successively reduce the size rather than the other way around. – Xaldew Sep 19 '17 at 13:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.