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_TEXTThe currently selected text or the empty stringTM_CURRENT_LINEThe contents of the current lineTM_CURRENT_WORDThe contents of the word under cursor or the empty stringTM_LINE_INDEXThe zero-index based line numberTM_LINE_NUMBERThe one-index based line numberTM_FILENAMEThe filename of the current documentTM_FILENAME_BASEThe filename of the current document without its extensionsTM_DIRECTORYThe directory of the current documentTM_FILEPATHThe full file path of the current documentRELATIVE_FILEPATHThe relative (to the opened workspace or folder) file path of the current documentCLIPBOARDThe contents of your clipboardWORKSPACE_NAMEThe name of the opened solutionWORKSPACE_FOLDERThe path of the opened solutionCURSOR_INDEXThe zero-index based cursor numberCURSOR_NUMBERThe one-index based cursor number
For inserting the current date and time:
CURRENT_YEARThe current yearCURRENT_YEAR_SHORTThe current year's last two digitsCURRENT_MONTHThe month as two digits (example '02')CURRENT_MONTH_NAMEThe full name of the month (example 'July')CURRENT_MONTH_NAME_SHORTThe short name of the month (example 'Jul')CURRENT_DATEThe day of the month as two digits (example '08')CURRENT_DAY_NAMEThe name of day (example 'Monday')CURRENT_DAY_NAME_SHORTThe short name of the day (example 'Mon')CURRENT_HOURThe current hour in 24-hour clock formatCURRENT_MINUTEThe current minute as two digitsCURRENT_SECONDThe current second as two digitsCURRENT_SECONDS_UNIXThe number of seconds since the Unix epochCURRENT_TIMEZONE_OFFSETThe current UTC time zone offset as +HH:MM or -HH:MM (example -07:00).
For inserting random values:
RANDOM6 random Base-10 digitsRANDOM_HEX6 random Base-16 digitsUUIDA Version 4 UUID
For inserting line or block comments, honoring the current language:
BLOCK_COMMENT_STARTBLOCK_COMMENT_ENDLINE_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.