Inhaltsverzeichnis

Creare Control VSIX

Guida per la creazione di una Extension VSIX per un WvdS Control.

Panoramica

Ogni WvdS Control viene distribuito come Extension VSIX autonoma:

wvds-vscode-ui-{control}-0.1.0.vsix
+-- package.json           # Manifest Extension
+-- dist/
|   +-- extension_main.js  # Codice compilato
+-- images/
|   +-- icon.png           # Icona Extension
+-- pas/
    +-- extension_main.pas # Codice sorgente Pascal

Struttura Directory

sources/extensions/wvds.vscode.ui.controls/
+-- {categoria}/
    +-- wvds.vscode.ui.{control}/
        +-- package.json
        +-- build.cfg
        +-- pas/
        |   +-- extension_main.pas
        +-- dist/              # Output Build
            +-- extension_main.js

Passo 1: Creare Directory

$ControlName = "mycontrol"
$Category = "editors"
$BasePath = "sources/extensions/wvds.vscode.ui.controls"
 
New-Item -ItemType Directory -Path "$BasePath/$Category/wvds.vscode.ui.$ControlName/pas" -Force

Passo 2: package.json

{
  "name": "wvds-vscode-ui-mycontrol",
  "displayName": "WvdS UI: MyControl",
  "description": "MyControl component for WvdS UI Framework",
  "version": "0.1.0",
  "publisher": "ArmandoFilho",
  "icon": "images/icon.png",
  "engines": {
    "vscode": "^1.85.0"
  },
  "categories": [
    "Other"
  ],
  "activationEvents": [
    "onLanguage:pxaml"
  ],
  "main": "./dist/extension_main.js",
  "contributes": {
    "snippets": [
      {
        "language": "pxaml",
        "path": "./snippets/mycontrol.json"
      }
    ]
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/ArmandoFilho/WvdS.FPC"
  },
  "license": "MIT"
}

Passo 3: extension_main.pas

library extension_main;
 
{$mode objfpc}
{$modeswitch externalclass}
 
uses
  JS, Web,
  VSCode.Base, VSCode.Commands, VSCode.Window;
 
type
  TExtension = class
  public
    class procedure Activate(AContext: TVSCodeExtensionContext);
    class procedure Deactivate;
  end;
 
class procedure TExtension.Activate(AContext: TVSCodeExtensionContext);
var
  Disposable: TVSCodeDisposable;
begin
  (* Registra snippet provider *)
  Disposable := TVSCodeCommands.RegisterCommand(
    'wvds.ui.mycontrol.insert',
    @InsertSnippet
  );
  AContext.Subscriptions.Push(Disposable);
end;
 
class procedure TExtension.Deactivate;
begin
  (* Cleanup *)
end;
 
procedure InsertSnippet;
begin
  asm
    const snippet = '<MyControl Name="myControl1" />';
    vscode.window.activeTextEditor?.insertSnippet(
      new vscode.SnippetString(snippet)
    );
  end;
end;
 
exports
  Activate,
  Deactivate;
 
begin
end.

Passo 4: build.cfg

-Mobjfpc
-Tnodejs
-O-
-Jc
-Jirtl.js
-Fu../../../common
-FUpas
-FEdist
-odist/extension_main.js

Passo 5: Compilare

$ExtPath = "sources/extensions/wvds.vscode.ui.controls/editors/wvds.vscode.ui.mycontrol"
 
# Compilare con pas2js
pas2js @"$ExtPath/build.cfg" "$ExtPath/pas/extension_main.pas"

Passo 6: Pacchettizzare VSIX

cd $ExtPath
 
# Copiare icona (se non presente)
if (-not (Test-Path "images")) {
    New-Item -ItemType Directory -Path "images" -Force
    Copy-Item "%MEDIA%/wvds_fpc.png" "images/icon.png"
}
 
# Creare VSIX
vsce package --no-dependencies
 
# Spostare in dist
Move-Item "*.vsix" "%BINARIES%/dist/"

Definizione Snippet

Crea snippets/mycontrol.json:

{
  "WvdS MyControl": {
    "prefix": "wvds-mycontrol",
    "body": [
      "<MyControl",
      "    Name=\"${1:myControl1}\"",
      "    ${2:Property}=\"${3:Value}\"",
      "/>"
    ],
    "description": "Insert WvdS MyControl"
  }
}

Esempio Completo

Extension Button

library extension_main;
 
{$mode objfpc}
{$modeswitch externalclass}
 
uses
  JS, Web,
  VSCode.Base, VSCode.Commands, VSCode.Window,
  VSCode.Languages, VSCode.CompletionItem;
 
const
  CONTROL_NAME = 'Button';
  CONTROL_CATEGORY = 'Basic Controls';
  CONTROL_ICON = 'symbol-event';
 
type
  TButtonExtension = class
  public
    class procedure Activate(AContext: TVSCodeExtensionContext);
    class procedure Deactivate;
  private
    class procedure RegisterSnippet(AContext: TVSCodeExtensionContext);
    class procedure RegisterCompletionProvider(AContext: TVSCodeExtensionContext);
  end;
 
class procedure TButtonExtension.Activate(AContext: TVSCodeExtensionContext);
begin
  RegisterSnippet(AContext);
  RegisterCompletionProvider(AContext);
 
  asm
    console.log('WvdS UI: Button extension activated');
  end;
end;
 
class procedure TButtonExtension.Deactivate;
begin
  (* Cleanup *)
end;
 
class procedure TButtonExtension.RegisterSnippet(AContext: TVSCodeExtensionContext);
var
  Cmd: TVSCodeDisposable;
begin
  Cmd := TVSCodeCommands.RegisterCommand(
    'wvds.ui.button.insert',
    procedure
    begin
      asm
        const editor = vscode.window.activeTextEditor;
        if (editor) {
          const snippet = new vscode.SnippetString(
            '<Button\n' +
            '    Name="${1:button1}"\n' +
            '    Caption="${2:Click Me}"\n' +
            '    OnClick="${3:OnButtonClick}"\n' +
            '/>'
          );
          editor.insertSnippet(snippet);
        }
      end;
    end
  );
  AContext.Subscriptions.Push(Cmd);
end;
 
class procedure TButtonExtension.RegisterCompletionProvider(
  AContext: TVSCodeExtensionContext);
begin
  (* Provider completamento PXAML *)
  asm
    const provider = vscode.languages.registerCompletionItemProvider(
      { language: 'pxaml', scheme: 'file' },
      {
        provideCompletionItems(document, position) {
          const item = new vscode.CompletionItem('Button', vscode.CompletionItemKind.Class);
          item.insertText = new vscode.SnippetString(
            '<Button Name="${1:button1}" Caption="${2:Click Me}" />'
          );
          item.documentation = 'WvdS Button control';
          return [item];
        }
      },
      '<'
    );
    AContext.subscriptions.push(provider);
  end;
end;
 
procedure Activate(AContext: TJSObject);
begin
  TButtonExtension.Activate(TVSCodeExtensionContext(AContext));
end;
 
procedure Deactivate;
begin
  TButtonExtension.Deactivate;
end;
 
exports
  Activate,
  Deactivate;
 
begin
end.

Generazione Batch

Per piu control, vedi Generazione Control.

Troubleshooting

Errori pas2js

Errore Soluzione
class var non supportato Usare variabile a livello Unit
Int64 non supportato Usare Integer