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. (See Extension Settings.)
:: StoryData
{
"ifid": "<ifid here>",
"format": "<story format here, i.e. 'SugarCube'>",
"format-version": "<story format version here, i.e. '2.34.1'>"
}
-
Syntax highlighting.
-
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. See extension-settings.) Open from the Twee 3 Language Tools tab on the activity bar (the forking paths logo.)
-
A story-map view (Contributed by @Goctionni) that opens in the browser! Still in very 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 (see settings):- 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 array)
optional: If the macro has children, specify their names as an array (currently unused in code.) - 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.
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)
This extension contributes the following settings:
Automatically set by the StoryData
special passage (if it exists):
twee3LanguageTools.storyformat.current
: Identifier of the storyformat in use.
Manual settings:
NOTE: It's recommended to change these settings separately for each workspace instead of globally.
twee3LanguageTools.storyformat.override
: Identifier of the storyformat to override the format set byStoryData
.
⠀twee3LanguageTools.directories.include
: Directories in which to look for twee files. Use glob patterns relative to the root of the workspace folders (e.g.src/unprocessed/twee
,src/static
,external
). (Searches the entire workspace by default.)twee3LanguageTools.directories.exclude
: Directories to exclude from the search of twee files. Use absolute glob patterns (e.g.**/src/processed/**
). (Excludes**/node_modules/**
by default.) If passage listing is active, excluded files will not be scanned for passages. They also will not be scanned for errors until manually opened.
⠀twee3LanguageTools.storyMap.unusedPortClosingDelay
: Duration in milliseconds before the story-map server port is closed after the UI in the browser window has been closed. (5000
by default.) ⠀twee3LanguageTools.passage.list
: Display list of passages with quick 'jump' links? (false
by default.)twee3LanguageTools.passage.group
: Group passages by? (None
by default. Can be grouped by file of origin, folder of origin, or passage tags.)
⠀twee3LanguageTools.twee-3.warning.spaceAfterStartToken
: Warn about missing space after the start token (::
) in passage headers? (true
by default.)twee3LanguageTools.twee-3.error.storyData.format
: Throw an error when missing the story format field (format
) inStoryData
special passage? (true
by default.)twee3LanguageTools.twee-3.error.storyData.formatVersion
: Throw an error when missing the story format version field (format-version
) inStoryData
special passage? (true
by default.)
⠀twee3LanguageTools.sugarcube-2.warning.undefinedMacro
: Warn about macros/widgets which were not found in definitions (*.twee-config.yaml
or*.twee-config.json
files) or the core SugarCube macro library? (true
by default.)twee3LanguageTools.sugarcube-2.warning.deprecatedMacro
: Warn about deprecated macros/widgets? (true
by default.)twee3LanguageTools.sugarcube-2.warning.endMacro
: Warn about the deprecated<<end...>>
closing tag syntax? (true
by default.)twee3LanguageTools.sugarcube-2.warning.barewordLinkPassageChecking
: Provides warnings for links like[[passage]]
whenpassage
is not a valid passage name. This could cause false positives in cases where you are using a global variable. (true
by default.)
⠀twee3LanguageTools.sugarcube-2.error.argumentParsing
: Provide errors about invalid argument syntax being passed into macros? (true
by default.)twee3LanguageTools.sugarcube-2.error.parameterValidation
: Provide errors about invalid argument types being passed into macros? (true
by default.)
⠀twee3LanguageTools.sugarcube-2.features.macroTagMatching
: Highlight opening and closing tags of container macros? (true
by default.)
⠀twee3LanguageTools.experimental.sugarcube-2.selfClosingMacros.enable
: Enable self-closing syntax for container macros? Read here for more information. (false
by default.)twee3LanguageTools.experimental.sugarcube-2.selfClosingMacros.warning.irrationalSelfClose
: Warn about self-closed instances of content focused macros (e.g.<<script />>
)? (true
by default.)
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).
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.