From 83d58810c1f4c034b460f9e14c388d5c55dc5235 Mon Sep 17 00:00:00 2001 From: webbrain-one <295484252+webbrain-one@users.noreply.github.com> Date: Wed, 5 Aug 2026 03:55:54 +0300 Subject: [PATCH] Support custom DuckyScript commands in syntax highlighting Allow users to configure additional commands via settings.json to extend syntax highlighting. This enables support for custom extensions used by projects like USBArmyKnife and Flipper Zero. --- package.json | 14 +++++++++++- src/extension.ts | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index d98ec59..62a95a5 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,19 @@ "language": "duckyscript", "path": "./snippets/snippets.json" } - ] + ], + "configuration": { + "type": "object", + "title": "DuckyScript", + "properties": { + "duckyscript.customCommands": { + "type": "array", + "items": { "type": "string" }, + "default": [], + "description": "List of custom commands to highlight in DuckyScript files." + } + } + } }, "scripts": { "vscode:prepublish": "npm run compile", diff --git a/src/extension.ts b/src/extension.ts index 0865492..b604d1f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -54,6 +54,54 @@ const updatedCommandGroups = commandGroups.map(group => const ALL_COMMANDS = commandGroups.flat(); +const semanticTokenLegend = new vscode.SemanticTokensLegend( + ['customCommand'], + [] +); + +class CustomCommandSemanticTokensProvider implements vscode.DocumentSemanticTokensProvider { + private customCommands: Set = new Set(); + private _emitter = new vscode.EventEmitter(); + onDidChangeSemanticTokens = this._emitter.event; + + constructor() { + this.updateCustomCommands(); + vscode.workspace.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('duckyscript.customCommands')) { + this.updateCustomCommands(); + this._emitter.fire(); + } + }); + } + + private updateCustomCommands() { + const config = vscode.workspace.getConfiguration('duckyscript'); + const commands = config.get('customCommands', []); + this.customCommands = new Set(commands.map(c => c.toUpperCase())); + } + + provideDocumentSemanticTokens( + document: vscode.TextDocument, + _token: vscode.CancellationToken + ): vscode.ProviderResult { + const builder = new vscode.SemanticTokensBuilder(semanticTokenLegend); + for (let i = 0; i < document.lineCount; i++) { + const line = document.lineAt(i); + const match = line.text.match(/^\s*([A-Z_][A-Z0-9_]*)\b/); + if (match && this.customCommands.has(match[1].toUpperCase())) { + builder.push({ + line: i, + startColumn: match.index ?? 0, + length: match[1].length, + tokenType: 0, + tokenModifiers: 0 + }); + } + } + return builder.build(); + } +} + // We implement a CompletionItemProvider for our language class MyLanguageCompletionItemProvider implements vscode.CompletionItemProvider { // This method is called when the user activates the suggestions (e.g., Ctrl+Space) @@ -98,6 +146,13 @@ export function activate(context: vscode.ExtensionContext) { ); context.subscriptions.push(providerDisposable); + + // Custom commands syntax highlighting + const customTokenProvider = vscode.languages.registerDocumentSemanticTokensProvider( + { language: 'duckyscript' }, + new CustomCommandSemanticTokensProvider() + ); + context.subscriptions.push(customTokenProvider); } function deactivate() { }