Snippets
Code snippets are templates that make it easier to enter repeating code patterns and introduce benefits for developers to
- quickly output pre-written code (save repetitive typing)
- use tabstops to navigate your cursor to predetermined locations in your snippet using the tab key
- use multiple occurrences of the same tab stop to enter recurring values only once
- use placeholder values to provide default values to tabstops
- give placeholder choice options (as from a dropdown) to be selected when the snippet is inserted
- 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 stringTM_CURRENT_LINE
The contents of the current lineTM_CURRENT_WORD
The contents of the word under cursor or the empty stringTM_LINE_INDEX
The zero-index based line numberTM_LINE_NUMBER
The one-index based line numberTM_FILENAME
The filename of the current documentTM_FILENAME_BASE
The filename of the current document without its extensionsTM_DIRECTORY
The directory of the current documentTM_FILEPATH
The full file path of the current documentRELATIVE_FILEPATH
The relative (to the opened workspace or folder) file path of the current documentCLIPBOARD
The contents of your clipboardWORKSPACE_NAME
The name of the opened solutionWORKSPACE_FOLDER
The path of the opened solutionCURSOR_INDEX
The zero-index based cursor numberCURSOR_NUMBER
The one-index based cursor number
For inserting the current date and time:
CURRENT_YEAR
The current yearCURRENT_YEAR_SHORT
The current year's last two digitsCURRENT_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 formatCURRENT_MINUTE
The current minute as two digitsCURRENT_SECOND
The current second as two digitsCURRENT_SECONDS_UNIX
The number of seconds since the Unix epochCURRENT_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 digitsRANDOM_HEX
6 random Base-16 digitsUUID
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.