Mark's Magical Verse extension
Syntax highlighting and digest-powered hover/autocomplete for the Verse language used in UEFN.
Features
Syntax highlighting for .verse files — comments, strings (with "{Expr}" interpolation), attributes, specifiers, control-flow keywords, declarations, function/method names (a distinct color by default — see below), field/parameter names, and primitive types (void, int, float, string, logic, etc.).
Hover documentation — hover any known symbol name to see its signature and doc comment, sourced from Epic's generated digest files. Hovering your own field/param/local names shows their declared or inferred type (plus the digest doc for that type, if it's a known one); hovering one of your own class/struct/interface/enum names shows its declaration line.
Autocomplete sourced from the same digests, plus your own file's fields/params/locals:
- Anywhere: global completions for known modules, classes, structs, interfaces, enums, and top-level functions, plus visible fields/params/locals/
Self/sibling methods in your current file.
- After a
.: member completions for a known type or module name (e.g. fort_hud_controller., Fortnite.UI.) — and, more usefully, for a variable whose declared type is known (e.g. MyEvent. where MyEvent : event(), or a for (X : ArrayField) loop variable).
Go to definition (F12 / Ctrl+click) — jumps to a field/param/local/method's declaration in the current file, to a class/field/method declared anywhere else in the workspace, or to a digest symbol's declaration line in whichever *.digest.verse file it came from.
Signature help — shows parameter info while typing inside a call's (...), for your own methods (current file or elsewhere in the workspace) and known digest functions, highlighting the active parameter as you type past each comma.
Find all references (Shift+F12) and rename symbol (F2) — for a local (param/local/for-binding), scoped to the current file; for a class/struct/interface/enum name or module-scope function, project-wide by name (these are effectively unique identifiers in Verse); for a class/enum-scoped field/method/enum-value, project-wide but verified per occurrence (a bare reference has to actually resolve to this exact declaration, a Receiver.Name reference has to have a receiver whose type actually has this member) — so a same-named member on an unrelated class is never touched. When that verification can't be done confidently, both features refuse rather than guess: rename would rather do nothing than silently corrupt unrelated code. Renaming a digest (Epic API) symbol is refused outright.
On top of the current file's own fields/params/locals, the extension indexes every other .verse file in the workspace for its classes' fields/methods, enum values, and module-scope functions — so calling into another file's class, referencing its enum's values (your_enum.SomeValue), or referencing a module-scope helper function declared elsewhere, resolves for hover/completion/definition/signature-help too, not just within the file you're editing.
Digest files (*.digest.verse) are Verse-syntax declaration dumps that Epic
generates for the public API, and that UEFN also generates for your own
project's Verse code. This extension doesn't ship any of Epic's own
generated content — those files aren't mine to redistribute — so it reads
them from wherever UEFN already writes them on your machine instead, via
two sources that merge together:
Your UEFN project's own AppData Digests folder — where UEFN itself
regenerates the global Verse/UnrealEngine/Fortnite API digests (and your
project's own digest) on every compile, typically
C:\Users\<you>\AppData\Local\UnrealEditorFortnite\Saved\VerseProject\<ProjectName>\Digests.
The extension tries to auto-detect this (see the uefnDigestsFolder
setting below) but VS Code's extension API has no real way to know which
UEFN project goes with your workspace, so auto-detection only kicks in
when it's unambiguous — otherwise set the path explicitly.
A workspace-relative digest folder (default digests) — for
manually copying or symlinking digest files into your workspace instead,
if you'd rather not point at AppData.
Settings
verse.digests.uefnDigestsFolder (default "", empty) — absolute path to
your UEFN project's generated Digests folder. Searched recursively, so it
doesn't matter whether your UEFN version lays the *.digest.verse files
flat or nests them in subfolders (older versions have been observed doing
the latter) — no need to flatten/copy them yourself either way. Leave
empty to auto-detect from the standard UEFN AppData location — this only
works when there's exactly one UEFN project on your machine, or one whose
name matches your workspace folder's name; otherwise, set this explicitly.
Windows only — UEFN doesn't currently ship elsewhere, and there's no
verified equivalent path to guess at on another platform.
verse.digests.projectFolder (default "digests") — workspace-relative folder to scan for digest files, for the manual-copy approach above.
Function/method names default to a burnt-orange (#CC6633) highlight, via a
configurationDefaults entry for editor.tokenColorCustomizations scoped
to the entity.name.function.verse token. It's a default, not forced —
override it in your own settings.json under
editor.tokenColorCustomizations.textMateRules (note: if you already set
editor.tokenColorCustomizations yourself for anything else, your version
replaces this one entirely rather than merging, since it's a single
setting value — add the rule back in yours if you want to keep it
alongside your own).
Troubleshooting
.verse files open as Plain Text no matter what's installed or enabled.
Check files.associations in your User and Workspace settings
(Command Palette → Preferences: Open Settings (UI), search
files.associations) for an entry like "*.verse": "Verse". That value
has to be the exact, case-sensitive language id — this extension
registers "verse" (lowercase); "Verse" is only a display alias (what
shows in the language picker), not a usable association target. A
mismatched-case entry silently overrides every extension's own
language contribution, which is why it happens regardless of what's
installed. Fix: change the value to lowercase "verse".
Does this work alongside Epic's official Verse extension?
Yes, both can be installed and enabled at the same time.
Pay-what-you-like
- If you find this extension useful, I have a ko-fi page where you can show your appreciation - every little helps :) https://ko-fi.com/markripley
| |