Search code examples
emacscobolyasnippet

Conditionally skip a field in yasnippet


I'm trying to create a yasnippet for a MOVE statement i COBOL. Writing MOVE statements is something we do ALOT of and I want to be as fast and efficient as possible with it.

Usual it is something like this:

MOVE variable-1 TO variable-2

but sometimes you use functions as well:

MOVE FUNCTION LENGTH(variable-1) TO variable-2

So what I'm after is a snippet which skips field-2 if field-1 = "FUNCTION".

What I have right now is:

MOVE $1 ${2:$$(unless (or yas-modified-p yas-moving-away-p (equal (upcase (yas-field-value 1)) "FUNCTION")) (yas-skip-and-clear-field))} TO $0

This works great for the "MOVE FUNCTION ..." case but otherwise it don´t. Here when I hit after entered varaible-1 in field-1 i get (cursor is |):

MOVE variable-1 #<marker at 2998 in text.cbl>| TO

So it seems that the return value from yas-skip-and-clear-field get printed instead of doing the jump to $0.

How could I solve this? Or are there any better way of doing this?


Solution

  • I wrote similar snippet for systemverilog 'logic', whose syntax is:

    logic MySignal;
    

    or

    logic [31:0] mybus;
    

    So ideally, if 'logic' followed by is typed, the snippet would expand the first field unconditionally. If that field contains [number:number], it expands the other field with name. If [] is not found, the field is considered to be a signal name.

    It is not perfect, but here is what I have came with:

    # -*- mode: snippet -*-
    # name: logic
    # key: logic
    # --
    logic ${1:range_or_signal}${2: $(if (string-match "\\[[0-9\s]+:[0-9\s]+\\]" (yas-field-value 1)) (concat " " (string-trim yas-text)) (yas-auto-next ""))};
    $0
    

    Basically the first field is always entered, and the other one is skipped if first one is not vector definition. The skipping is performed by yas-auto-next