Syntax highlighting for HTML and select storyformats (see Features) on top of Twee 3 code.
Made possible through contributions from:
And feedback from the folks over at the Twine Games Discord Server.
The extension relies on a workspace (or a folder) being open. If single files are to be edited, the storyformat must be configured manually.
Supported file extensions:
.tw
.twee
To set the correct storyformat for the files, a StoryData
passage with the storyformat (and version) (see example below) mentioned in it is preferred. If not, the extension provides the option to set the format explictly.)
:: StoryData
{
"ifid": "<ifid here>",
"format": "<story format here, i.e. 'SugarCube'>",
"format-version": "<story format version here, i.e. '2.35.0'>"
}
-
Syntax highlighting.
-
Snippet to generate the
StoryData
special passage: start typingStoryData
in a Twee document and press Tab when prompted with the snippet. This populates the IFID field with a newly generated one. -
Command palette tool to generate IFID: open the command palette (Ctrl/Cmd + Shift + P or F1 by default) and search for "IFID".
-
A list of passages for quick jumps (can be grouped by files, folders, or passage tags.) Open from the Twee 3 Language Tools tab on the activity bar (the forking paths logo.)
-
Workspace statistics Status bar item (WIP) (Contributed by @rambdev).
- Total passage count (includes Story passages, Special passages, and Script/Stylesheet-tagged passages)
- Story passage count
-
A story-map view (Contributed by @Goctionni) that opens inside VSCode (and optionally, in the browser)! Still in early stages. Also accessible from the Twee 3 Language Tools tab on the activity bar.
-
Currently implemented features:
- Snap to grid (button on top-left.)
- Arrows to linked passages.
- Passage position, size, and tags can be edited via a sidebar. Changes are not currently autosaved, and a manual save button is present.
- Multi-select, and thereby mass editing of position, size, and tags.
- Ability to move passages across files.
-
Usage:
- Use the middle-mouse button, or hold down Shift while dragging the mouse to pan the map grid.
- Scroll the mousewheel or stretch/pinch on trackpad to zoom in/out.
- Hold Ctrl/Cmd while selecting to add new passages to selection, or remove already added passages from it.
-
(id: sugarcube-2
)
- Syntax highlighting:
- Macro documentation on hover. (Contributed by @MinusGix) (Custom definitions can be added via
*.twee-config.yml
. See: Custom macro definitions for SC): - Container macro pair highlights:
- Snippets. (Contributed by @rambdev) Type macro names to get code snippet inserts with placeholder values:
- Diagnostics:
- Macros with opening tags but no closes (and vice-versa):
- Deprecated macros:
- Deprecated
<<end...>>
closing macros: - Unrecognized macros. New/custom macros can be defined manually (see: Custom macro definitions for SC), but anything else will throw a warning. This can be turned off by the
twee3LanguageTools.sugarcube-2.undefinedMacroWarnings
setting:- Screenshot - diagnostic
- Screenshot - quick fix (Writes definitions to
t3lt.twee-config.yml
in the root of the first workspace folder.)
- Invalid argument syntax in macros (Contributed by @MinusGix):
- Argument validation (Contributed by @MinusGix): Read here for more information.
(id: chapbook-1
)
(id: harlowe-3
)
The extension adds diagnostics for erroneous usage of macros in TwineScript for the sugarcube-2
storyformat. By default, only the definitions for the core SugarCube library are present, but custom definitions can be added. The process is as follows:
- Add a
*.twee-config.yaml
(or.yml
) OR*.twee-config.json
(*
represents any valid file name) file to your project folder (or anywhere in the workspace.) - Define custom macros as follows:
- If using
*.twee-config.yaml
(indentation is important for YAML files):sugarcube-2: macros: customMacroName: container: true anotherOne: {}
- If using
*.twee-config.json
:{ "sugarcube-2": { "macros": { "customMacroName": { "container": true }, "anotherOne": {} } } }
- If using
The following properties are currently programmed, even though not all of them are used as of now:
- name
(string)
optional: Name of the macro (currently unused in code; the name of the object suffices for now.) - description
(string)
optional: Description of macro. Shown on hover. Supports markdown. - container
(boolean)
optional: If the macro is a container (i.e. requires a closing tag) or not.false
by default. - selfClose
(boolean)
optional: If the macro is a self-closable. Requires macro to be a container first.false
by default. - children
(string|child-definition array)
optional: If the macro has children, specify them as an array of strings or child-definition (WIP) objects. - parents
(string array)
optional: If the macro is a child macro, specify the names of its parents as an array (currently unused in code.) - deprecated
(boolean)
optional: If the macro is deprecated or not.false
by default. - deprecatedSuggestions
(string array)
optional: If the macro is deprecated, specify any alternatives to the macro as an array. - parameters
(object)
optional: Allows for macro argument validation. Read here for more information. - decoration
(object)
optional: Allows for declaring decorations to be displayed on that macro. Uses DecorationRenderOptions' fields. RequiresdefinedMacroDecorations
setting to be enabled.
NOTE: Multiple twee-config
files can be present in a workspace. They will stack and add to the macro definitions for the workspace. The recommended strategy is to make separate files for separate macro sets/libraries, e.g. (the following file can also be used as an example):
click-to-proceed.twee-config.yaml
(Link)
Uses a simple packing algorithm to space out passages into clusters based on the file they originate from.
To use, search for Pack passages to clusters
from the command palette (Ctrl/Cmd + Shift + P or F1 by default).
Adds every unrecognized macro to the definition file, instead of doing it one by one.
To use, search for Unrecognized Macros
from the command palette (Ctrl/Cmd + Shift + P or F1 by default).
However, it is still recommended to add definitions one at a time.
NOTE: SugarCube 2 does NOT have a self-closing syntax for container macros, this feature is just to support custom passage processing functions.
Example of such a function which replaces self-closed instances with the actual closing macro tag (i.e. <<macro />>
with <<macro>><</macro>>
):
Config.passages.onProcess = function(p) {
const macroNamePattern = `[A-Za-z][\\w-]*|[=-]`;
const selfCloseMacroRegex = new RegExp(`<<(${macroNamePattern})((?:\\s*)(?:(?:/\\*[^*]*\\*+(?:[^/*][^*]*\\*+)*/)|(?://.*\\n)|(?:\`(?:\\\\.|[^\`\\\\])*\`)|(?:"(?:\\\\.|[^"\\\\])*")|(?:'(?:\\\\.|[^'\\\\])*')|(?:\\[(?:[<>]?[Ii][Mm][Gg])?\\[[^\\r\\n]*?\\]\\]+)|[^>]|(?:>(?!>)))*?)\\/>>`, 'gm');
return p.text.replace(selfCloseMacroRegex, "<<$1$2>><</$1>>");
};
The twee3LanguageTools.experimental.sugarcube-2.selfClosingMacros.enable
setting enables detection of self-closed macros.
Argument validation is still a work in progress. Passage name validation, especially. Shouldn't hinder workflow, however.
Changelog here.