5

I'm writing a snippet (for Go) and would like to have a field conditionally transformed when I move to the next field. Specifically, I want the field empty if I leave it unedited, and enclosed in parentheses if I leave it edited.

My unsuccessful snippet, expressing what I want but failing to transform an edited field:

func ${1:$$(when (and yas-modified-p yas-moving-away-p) 
             (concat "(" yas-text ")"))} FuncName

What I want is, that when typing t Type in the field, the snippet would expand as such:

func (t Type) FuncName

and when skipping over the field unedited it would expand like this:

func FuncName

I know that the condition executes as one would expect, because if I change (concat ...) to (message "XXX"), I see the trace printed in the mini buffer, but I can't figure out why my transformation doesn't work.

ivarg
  • 755
  • 1
  • 8
  • 11

3 Answers3

3

In your example it seems to me that the result of your concatenated string is discarded. I think you need to actually insert the new string into the buffer.

I'm not really very familiar with yasnippet syntax, so this may not be the cleanest solution, but the following seems to work for me:

func ${1:$$(when (and yas-modified-p 
                      yas-moving-away-p) 
              (insert ")" )
              (backward-char (+ 1 (length yas-text)))
              (insert "("))} ${2:funcName} {
    $0
}
Carl Groner
  • 4,149
  • 1
  • 19
  • 20
  • This almost worked, but since `backward-word` only takes one word, the input `t Type` becomes `t (Type)` after snippet expansion. – ivarg Oct 25 '13 at 05:52
  • Good point, I did miss that. Luckily, you can simply use the length of `yas-text` instead of a single word. I have updated my example to demonstrate this. – Carl Groner Oct 25 '13 at 17:03
1

The documentation suggests you need to wrap elisp forms in `backticks` to incorporate the return value into the snippet (much like command substitution in shell scripts).

Source

BinaryButterfly
  • 18,137
  • 13
  • 50
  • 91
phils
  • 71,335
  • 11
  • 153
  • 198
1

Wouldn't it be easier to have the snippet start as

func () FuncName

and remove the parenthese if they are left empty?

Stefan
  • 27,908
  • 4
  • 53
  • 82
  • 1
    Indeed, this seems like the preferred solution. You can use two mirrors around the first field that conditionally return the "(" and ")" strings, respectively, if the field's value is not the empty string. This is the preferred way to do it. – joao Oct 26 '13 at 23:49
  • Being not entirely comfortable with emacs lisp, I had to do some trial and error before reaching this: `func ${1:$(when (> (length yas-text) 0) "(")}$1${1:$(when (> (length yas-text) 0) ")")} FuncName`. Is there some more compact way to achieve this? – ivarg Oct 27 '13 at 20:29