IDE Extension
IDE features, like syntax highlighting, error checking, auto-completion and interactive documentation could significantly increase productivity when writing naninovel scripts. We've made an extension for a free and open-source Visual Studio Code (available for Windows, MacOS and Linux) IDE, which provides the essential IDE support for NaniScript syntax.
Setup
Unity
- Install Newtonsoft Json via Unity's package manager
- Make sure
Enable Bridging
option is enabled in engine configuration
NOTE
Newtonsoft Json package is only used in editor for serializing bridging communication messages and is not referenced by Naninovel's runtime assembly; the package won't be included to the builds and won't affect compatibility or build size.
VS Code
- Open extensions window in VS Code via
View -> Extensions
menu - Search for "Naninovel" and click "Install" button
- When a .nani file is opened, the extension will activate automatically
NOTE
Extension in the VS Code registry is compatible with the current stable Naninovel release. When using legacy (unsupported) Naninovel version, disable auto-update in VS Code and install associated legacy version of the extension. When using preview release of the engine, download associated preview extension via #download
channel on our Discord server.
Spell Check
To enable spell checking in the naninovel scripts, install a spell checker extension, eg. Code Spell Check and turn on the checking for naniscript
language; see the settings section below for an example on how to enable naniscript language for the Code Spell Check extension.
VS Code Settings
Below is the recommended settings for VS Code to ignore Unity's autogenerated meta files, enable semantic syntax highlighting, word wrap and spell checking (given spell check extension is installed) and disable word-based suggestions (so that they don't constantly popup when you type generic text lines):
{
"files.exclude": {
"**/*.meta": true
},
"editor.wordWrap": "on",
"editor.wordBasedSuggestions": "off",
"editor.occurrencesHighlight": "off",
"editor.suggest.showWords": false,
"editor.bracketPairColorization.enabled": false,
"editor.semanticTokenColorCustomizations": {
"enabled": true,
"rules": {
"CommentLine": { "foreground": "#5d6470", "italic": true },
"CommentText": { "foreground": "#5d6470", "italic": true },
"LabelLine": "#9bc37c",
"LabelText": "#9bc37c",
"CommandLine": "#6cb2ed",
"InlinedCommand": "#6cb2ed",
"Command": "#6cb2ed",
"CommandIdentifier": "#6cb2ed",
"Parameter": "#cd9769",
"ParameterIdentifier": "#cd9769",
"ParameterValue": "#e2be7f",
"GenericTextLine": "#acb2be",
"GenericTextPrefix": "#e2be7f",
"GenericTextAuthor": "#e2be7f",
"GenericTextAuthorAppearance": "#e2be7f",
"Expression": "#62b8c1",
"TextIdentifier": "#5d6470",
"Error": "#d14e4e"
}
},
"cSpell.enableFiletypes": [
"naniscript"
]
}
You can access the settings JSON file via File -> Preference -> Settings
menu and clicking "Open Settings (JSON)" button in the upper-right corner of the window. Select "User" tab to edit settings for all projects or "Workspace" to affect only the current project with the naninovel scripts.
Feel free to customize the settings as you see fit.
IDE Metadata
The project metadata (actors, scripts, custom commands, etc) is stored as NaninovelData/Metadata.json
file. It's automatically generated when Unity editor is started. To update the metadata while the project is opened, either use Naninovel -> Update Metadata
editor menu or Ctrl + Shift + U
hotkey.
The metadata is automatically synced with the IDE each time it's updated. To disable automatic metadata sync in the IDE and other related features, use extension settings under "Naninovel" category. Restart the IDE after changing the settings (or press Ctrl+Shift+P and select "Developer: Reload Window") for changes to take effect.
NOTE
When typing generic text lines, author ID auto-completion won't trigger automatically, as it's impossible to guess whether you want to specify author ID or just typing text to print. Use the hotkey (Ctrl+Space
by default) to trigger auto-complete manually.
Video Tutorial
Below is a video tutorial on how to install, configure and use the VS Code extension.
Metadata Providers
To fill generated metadata with additional custom values, implement IMetadataProvider
interface. The implementations are expected to have a parameterless constructor and will be instantiated and used each time project metadata is generated (eg, when syncing with an IDE extension). The results of each implementation will be merged with each other; this way you can have multiple providers that generate specific metadata.
Below is an example of a built-in metadata provider, that generates script label constants to be used in autocompletion.
public class LabelMetadataProvider : IMetadataProvider
{
public Project GetMetadata (MetadataOptions options)
{
var scripts = LoadScripts();
var constants = scripts.Select(CreateLabelConstant);
return new Project { Constants = constants.ToArray() };
}
private Script[] LoadScripts ()
{
return EditorResources.LoadOrDefault()
.GetAllRecords(ScriptsConfiguration.DefaultPathPrefix)
.Select(kv => AssetDatabase.GUIDToAssetPath(kv.Value))
.Where(path => !string.IsNullOrEmpty(path))
.Select(AssetDatabase.LoadAssetAtPath<Script>)
.ToArray();
}
private Constant CreateLabelConstant (Script script)
{
var name = $"Labels/{script.Name}";
var values = script.Lines
.OfType<LabelScriptLine>()
.Where(l => !string.IsNullOrWhiteSpace(l.LabelText))
.Select(l => l.LabelText.Trim());
return new Constant { Name = name, Values = values.ToArray() };
}
}
IDE Attributes
Naninovel has a number of C# attributes to provide various IDE-related functionality to custom commands. For example, to add on-hover documentation to the custom commands and/or parameters, apply Documentation
attribute to command type and parameter fields respectively:
[Documentation("Summary of the custom command.")]
public class CustomCommand : Command
{
[Documentation("Summary of the custom parameter.")]
public StringParameter CustomParameter;
}
To make a parameter auto-complete with both built-in and custom expression functions and pre-defined custom variables use ExpressionContext
attribute.
[ExpressionContext]
public StringParameter Expression;
To auto-complete with values from an arbitrary enumeration type use ConstantContext
attribute.
[ConstantContext(typeof(PlatformID))]
public StringParameter Platform;
To auto-complete and analyze usage and correctness of navigation endpoints (script name and label) use EndpointContext
attribute.
[EndpointContext]
public NamedStringParameter Goto;
To auto-complete with a resource use ResourceContext
and provide path prefix of the resources. Below example will complete with audio resources:
[ResourceContext(AudioConfiguration.DefaultAudioPathPrefix)]
public StringParameter Audio;
To auto-complete with an actor ID (of any type) use ActorContext
attribute.
[ActorContext]
public StringParameter ActorId;
To auto-complete with an actor ID of specific type use ActorContext
attribute with first argument specifying path prefix of the actor resources. Below will complete with printer IDs:
[ActorContext(TextPrintersConfiguration.DefaultPathPrefix)]
public StringParameter PrinterId;
To auto-complete appearances of an actor with ID specified in the same named or another parameter in the current command, use AppearanceContext
attribute. Be aware, that this requires ActorContext
attribute specified in the same command.
[ActorContext(CharactersConfiguration.DefaultPathPrefix)]
public StringParameter CharacterId;
[AppearanceContext]
public StringParameter CharacterAppearance;
Notice, that each of the above attributes allows providing an optional namedIndex
argument. Use it with named parameters to specify for which part of the parameter value the attribute belongs. Below example will allow auto-completing name part of the named parameter with character IDs and value part with appearances for the currently typed character (similar to nameless parameter of @char
command).
[ActorContext(CharactersConfiguration.DefaultPathPrefix, 0), AppearanceContext(1)]
public NamedStringParameter IdAndAppearance;
The parameter context attributes can be applied to class instead of fields to allow specifying (or overriding) the contexts for the fields declared in parent classes. For example, while Id
parameter is declared in the abstract ModifyActor
command, the context is applied to ModifyBackground
inherited class:
[ActorContext(BackgroundsConfiguration.DefaultPathPrefix, paramId: "Id")]
public class ModifyBackground : ModifyActor { }
You can repurpose the same tactic when inheriting custom commands from the built-in ones. Don't forget to provide the optional paramId
argument when applying parameter context attribute to a class instead of field.
Constant Expressions
When using ConstantContext
IDE Attribute, instead of enum it's possible to specify an expression to be evaluated by the IDE to produce a constant name based on command parameter values or other variables, such as currently inspected script.
Expression syntax:
- Evaluated parts should be wrapped in curly braces (
{}
) - To reference currently inspected script name, use
$Script
- To reference parameter value, use
:
followed by the parameter ID (field name as specified in C#, not alias) - Use
[0]
or[1]
after parameter reference to specify named value (0 for name and 1 for index) - Use null coalescing (
??
) after parameter reference for fallback in case the value is not specified - Use concatenation operator (
+
) to merge values from multiple constants
For example, check the expression assigned to Path
parameter of the built-in [@goto]
command:
[ConstantContext("Labels/{:Path[0]??$Script}", 1)]
public NamedStringParameter Path;
— when name component of the parameter is assigned with foo
, it will evaluate to Labels/foo
, otherwise, given inspected script name is bar
it will evaluate to Labels/bar
.
Another example for character poses applied to @char
command:
[ConstantContext("Poses/Characters/{:Id??:IdAndAppearance[0]}+Poses/Characters/*", paramId: nameof(Pose))]
public class ModifyCharacter { ... }
— will merge shared character poses with poses for characters with ID assigned to "ID" parameter or (when not assigned) name component of "IdAndAppearance" parameter.
Constant expressions combined with custom metadata providers allow creating arbitrary autocompletion scenarios for the IDE extension.
Other IDEs and Editors
While we don't maintain extensions for other editors, we have an open-sourced language server for Naninovel: github.com/naninovel/language. It's written in C#, but has JavaScript bindings and can be used in most modern IDEs. The implementation covers syntax highlighting, autocompletion, errors checking, etc. VS Code extension (which is built upon the language server) is open-sourced as well: github.com/naninovel/vscode.
Alternatively, in case you're using an editor with TextMate grammar support (eg, Sublime or Visual Studio), we have one ready: textmate.json.