Table of Contents

Snippets

Code snippets are templates that make it easier to enter repeating code patterns and introduce benefits for developers to

  1. quickly output pre-written code (save repetitive typing)
  2. use tabstops to navigate your cursor to predetermined locations in your snippet using the tab key
  3. use multiple occurrences of the same tab stop to enter recurring values only once
  4. use placeholder values to provide default values to tabstops
  5. give placeholder choice options (as from a dropdown) to be selected when the snippet is inserted
  6. insert certain variable values into your snippets

Zeugwerk Creator integrates Snippets, as they are known from Visual Studio Code into the TwinCAT IDE. Snippets appear in an IntelliSense-like Popup, as well as in a dedicated snippet panel. There is also support for tab-completion: type a snippet prefix (trigger text), and press Tab to insert a snippet.

All features of the the Visual Studio Code snippet syntax are supported by Zeugwerk Creator. For this reason, this article builds upon and/or uses sections of the Visual Studio Code documentation.

Snippets repositories

The location, where snippets are searched for can be freely configured. Local folders on your computer and/or remote Git Repositories, which are automatically checked out in a desired branch, are supported. If a specific branch of a repository can be specific by adding :<branch name> to the repository name (note the colon :) Snippets can be browsed and selected in a dedicated Snippel Panel and appear automatically for tab completion or can be selected from the panel when writing code in the code editor,

Create snippets

You can create your own snippets by selecting code in your code editor, and selecting "Create Snippet" from the context menu. A new file will open, which holds the extracted definition for ghe snippets. You can then manually extend the snippet with tabstops, placeholders, choices and variables,

Snippets files are written in JSON, and can define an unlimited number of snippets. Snippets support most all of the Visual Studio Code snippet syntax for dynamic behavior, intelligently format whitespace based on the insertion context, and allow easy multiline editing.

Below is an example of a for loop snippet:

"For Loop": {
        "prefix": ["for"],
        "scope": "pou-implementation",
        "body": [
            "FOR ${1:i} := ${2:start} TO ${3:end}",
            "DO",
            "  ${4:// todo: implement me}",
            "END_FOR"
        ],
        "description": "For-loop statement"
    }

In the example above:

  • "For Loop" is the snippet name. It is displayed via the tab completion popup if no description is provided.
  • prefix defines one or more trigger words that display the snippet for tab completion
  • scope controls if the snippet should show up in the implementation (default) of a POU or the declaration (scope="pou-declaration")
  • body is one or more lines of content, which will be joined as multiple lines upon insertion. Newlines and embedded tabs will be formatted according to the context in which the snippet is inserted.
  • description is an optional description of the snippet displayed in the Snippet Panel and tab completion popul.

Additionally, the body of the example above has placeholders (listed in order of traversal): ${1:i}, ${2:start}, ${3:end}, ${4:// todo: implement me}". You can quickly jump to the next placeholder with Tab, at which point you may edit the placeholder or jump to the next one. The string after the colon : (if any) is the default text, for example element in ${2:start}. Placeholder traversal order is ascending by number, starting from one; $0 is an optional special case that always comes last, and exits snippet mode with the cursor at the specified position. If not defined explictly. $0 is automatically inserted at the end of the snippet.

File template snippets

You can add the isFileTemplate attribute to your snippet's definition if the snippet is intended to populate or replace a file's contents. File template snippets are displayed in a seperate section of the snippet panel and, even if a prefix is set, are not be available for tab completion.

Similarily to creating code snippets, there is a context menu available for creating file snippets when right clicking a peoject item in the Solution Explorer of the TwinCAT IDE.

The body of file templates is in plain text, despite TwinCAT using a XML file. For this reason closing statements, which you are usually not used in TwinCAT are used. These include END_FUNCTION_BLOCK, END_METHOD, END_PROPERTY, END_GET, END_SET.

Snippet syntax

The body of a snippet can use special constructs to control cursors and the text being inserted. The following are supported features and their syntaxes:

Tabstops

With tabstops, you can make the editor cursor move inside a snippet. Use $1, $2 to specify cursor locations. The number is the order in which tabstops will be visited, whereas $0 denotes the final cursor position. Multiple occurrences of the same tabstop are linked and updated in sync.

Placeholders

Placeholders are tabstops with values, like ${1:foo}. The placeholder text will be inserted and selected such that it can be easily changed. Placeholders can be nested, like ${1:another ${2:placeholder}}.

Choice

Placeholders can have choices as values. The syntax is a comma-separated enumeration of values, enclosed with the pipe-character, for example ${1|one,two,three|}. When the snippet is inserted and the placeholder selected, choices will prompt the user to pick one of the values.

Variables

With $name or ${name:default}, you can insert the value of a variable. When a variable isn't set, its default or the empty string is inserted. When a variable is unknown (that is, its name isn't defined) the name of the variable is inserted and it is transformed into a placeholder.

The following variables can be used:

  • TM_SELECTED_TEXT The currently selected text or the empty string
  • TM_CURRENT_LINE The contents of the current line
  • TM_CURRENT_WORD The contents of the word under cursor or the empty string
  • TM_LINE_INDEX The zero-index based line number
  • TM_LINE_NUMBER The one-index based line number
  • TM_FILENAME The filename of the current document
  • TM_FILENAME_BASE The filename of the current document without its extensions
  • TM_DIRECTORY The directory of the current document
  • TM_FILEPATH The full file path of the current document
  • RELATIVE_FILEPATH The relative (to the opened workspace or folder) file path of the current document
  • CLIPBOARD The contents of your clipboard
  • WORKSPACE_NAME The name of the opened solution
  • WORKSPACE_FOLDER The path of the opened solution
  • CURSOR_INDEX The zero-index based cursor number
  • CURSOR_NUMBER The one-index based cursor number

For inserting the current date and time:

  • CURRENT_YEAR The current year
  • CURRENT_YEAR_SHORT The current year's last two digits
  • CURRENT_MONTH The month as two digits (example '02')
  • CURRENT_MONTH_NAME The full name of the month (example 'July')
  • CURRENT_MONTH_NAME_SHORT The short name of the month (example 'Jul')
  • CURRENT_DATE The day of the month as two digits (example '08')
  • CURRENT_DAY_NAME The name of day (example 'Monday')
  • CURRENT_DAY_NAME_SHORT The short name of the day (example 'Mon')
  • CURRENT_HOUR The current hour in 24-hour clock format
  • CURRENT_MINUTE The current minute as two digits
  • CURRENT_SECOND The current second as two digits
  • CURRENT_SECONDS_UNIX The number of seconds since the Unix epoch
  • CURRENT_TIMEZONE_OFFSET The current UTC time zone offset as +HH:MM or -HH:MM (example -07:00).

For inserting random values:

  • RANDOM 6 random Base-10 digits
  • RANDOM_HEX 6 random Base-16 digits
  • UUID A Version 4 UUID

For inserting line or block comments, honoring the current language:

  • BLOCK_COMMENT_START
  • BLOCK_COMMENT_END
  • LINE_COMMENT

The snippet below inserts (* Hello World *)

{
  "hello": {
    "prefix": "hello",
    "body": "$BLOCK_COMMENT_START Hello World $BLOCK_COMMENT_END"
  }
}

Variable transforms

Transformations allow you to modify the value of a variable before it is inserted. The definition of a transformation consists of three parts:

A regular expression that is matched against the value of a variable, or the empty string when the variable cannot be resolved. A "format string" that allows to reference matching groups from the regular expression. The format string allows for conditional inserts and simple modifications. Options that are passed to the regular expression. The following example inserts the name of the current file without its ending, so from foo.txt it makes foo.

${TM_FILENAME/(.*)\\..+$/$1/}
  |           |         |  |
  |           |         |  |-> no options
  |           |         |
  |           |         |-> references the contents of the first
  |           |             capture group
  |           |
  |           |-> regex to capture everything before
  |               the final `.suffix`
  |
  |-> resolves to the filename

Placeholder-Transform

Like a Variable-Transform, a transformation of a placeholder allows changing the inserted text for the placeholder when moving to the next tab stop. The inserted text is matched with the regular expression and the match or matches - depending on the options - are replaced with the specified replacement format text. Every occurrence of a placeholder can define its own transformation independently using the value of the first placeholder. The format for Placeholder-Transforms is the same as for Variable-Transforms.