diff --git a/.gitattributes b/.gitattributes
index 14f819f4d0..7b5fe69d2b 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -4008,7 +4008,7 @@ components/pas2js/Makefile svneol=native#text/plain
components/pas2js/Makefile.compiled svneol=native#text/plain
components/pas2js/Makefile.fpc svneol=native#text/plain
components/pas2js/Pas2JSDsgn.compiled svneol=native#text/plain
-components/pas2js/defaults.inc svneol=native#text/plain
+components/pas2js/atomdefaults.inc svneol=native#text/plain
components/pas2js/fpmake.pp svneol=native#text/plain
components/pas2js/frmpas2jsatompackagesettings.lfm svneol=native#text/plain
components/pas2js/frmpas2jsatompackagesettings.pas svneol=native#text/plain
@@ -4016,8 +4016,11 @@ components/pas2js/frmpas2jsbrowserprojectoptions.lfm svneol=native#text/plain
components/pas2js/frmpas2jsbrowserprojectoptions.pp svneol=native#text/plain
components/pas2js/frmpas2jsnodejsprojectoptions.lfm svneol=native#text/plain
components/pas2js/frmpas2jsnodejsprojectoptions.pp svneol=native#text/plain
+components/pas2js/frmpas2jsvscodeextensionsettings.lfm svneol=native#text/plain
+components/pas2js/frmpas2jsvscodeextensionsettings.pas svneol=native#text/plain
components/pas2js/frmpas2jswebservers.lfm svneol=native#text/plain
components/pas2js/frmpas2jswebservers.pp svneol=native#text/plain
+components/pas2js/languages/regpas2jsvscode.pot svneol=native#text/plain
components/pas2js/languages/strpas2jsdesign.fr.po svneol=native#text/plain
components/pas2js/languages/strpas2jsdesign.hu.po svneol=native#text/plain
components/pas2js/languages/strpas2jsdesign.pot svneol=native#text/plain
@@ -4036,7 +4039,9 @@ components/pas2js/pjsdsgnregister.pas svneol=native#text/plain
components/pas2js/pjsprojectoptions.lfm svneol=native#text/plain
components/pas2js/pjsprojectoptions.pp svneol=native#text/plain
components/pas2js/regpas2jsatom.pas svneol=native#text/plain
+components/pas2js/regpas2jsvscode.pas svneol=native#text/plain
components/pas2js/strpas2jsdesign.pp svneol=native#text/plain
+components/pas2js/vscodedefaults.inc svneol=native#text/plain
components/plotfunction/demo/event/frmmain.lfm svneol=native#text/plain
components/plotfunction/demo/event/frmmain.pp svneol=native#text/plain
components/plotfunction/demo/event/ploteventdemo.ico -text svneol=unset#image/ico
diff --git a/components/pas2js/defaults.inc b/components/pas2js/atomdefaults.inc
similarity index 100%
rename from components/pas2js/defaults.inc
rename to components/pas2js/atomdefaults.inc
diff --git a/components/pas2js/frmpas2jsvscodeextensionsettings.lfm b/components/pas2js/frmpas2jsvscodeextensionsettings.lfm
new file mode 100644
index 0000000000..565141dccb
--- /dev/null
+++ b/components/pas2js/frmpas2jsvscodeextensionsettings.lfm
@@ -0,0 +1,292 @@
+object VSCodeExtensionSettingsForm: TVSCodeExtensionSettingsForm
+ Left = 357
+ Height = 546
+ Top = 159
+ Width = 588
+ Caption = 'New Atom Package'
+ ClientHeight = 546
+ ClientWidth = 588
+ OnShow = FormShow
+ LCLVersion = '2.1.0.0'
+ object edtDescription: TEdit
+ AnchorSideLeft.Control = dePackage
+ AnchorSideTop.Control = dePackage
+ AnchorSideTop.Side = asrBottom
+ Left = 120
+ Height = 27
+ Top = 43
+ Width = 446
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Top = 8
+ TabOrder = 0
+ end
+ object lblDescription: TLabel
+ AnchorSideTop.Control = edtDescription
+ AnchorSideTop.Side = asrCenter
+ AnchorSideRight.Control = edtDescription
+ Left = 24
+ Height = 16
+ Top = 48
+ Width = 88
+ Alignment = taRightJustify
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Right = 8
+ Caption = '&Description'
+ FocusControl = edtDescription
+ ParentColor = False
+ end
+ object edtName: TEdit
+ AnchorSideLeft.Control = edtDescription
+ AnchorSideTop.Control = edtDescription
+ AnchorSideTop.Side = asrBottom
+ Left = 120
+ Height = 27
+ Top = 78
+ Width = 184
+ BorderSpacing.Top = 8
+ OnEditingDone = edtNameEditingDone
+ OnKeyPress = edtNameKeyPress
+ TabOrder = 1
+ end
+ object lblName: TLabel
+ AnchorSideTop.Control = edtName
+ AnchorSideTop.Side = asrCenter
+ AnchorSideRight.Control = edtName
+ Left = 16
+ Height = 16
+ Top = 83
+ Width = 96
+ Alignment = taRightJustify
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Right = 8
+ Caption = 'Package &Name'
+ FocusControl = edtName
+ ParentColor = False
+ end
+ object edtPublisher: TEdit
+ AnchorSideLeft.Control = edtClassName
+ AnchorSideTop.Control = edtClassName
+ AnchorSideTop.Side = asrBottom
+ Left = 120
+ Height = 27
+ Top = 149
+ Width = 173
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Top = 8
+ OnKeyPress = edtPublisherKeyPress
+ TabOrder = 2
+ end
+ object vleCommands: TValueListEditor
+ AnchorSideTop.Side = asrBottom
+ Left = 120
+ Height = 112
+ Top = 180
+ Width = 446
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Top = 8
+ DefaultColWidth = 192
+ FixedCols = 0
+ RowCount = 2
+ TabOrder = 3
+ KeyOptions = [keyEdit, keyAdd, keyDelete]
+ Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goColSizing, goEditing, goAutoAddRows, goAlwaysShowEditor, goThumbTracking]
+ TitleCaptions.Strings = (
+ 'Command Name'
+ 'Implement in Function'
+ )
+ ColWidths = (
+ 192
+ 252
+ )
+ end
+ object ButtonPanel1: TButtonPanel
+ Left = 6
+ Height = 38
+ Top = 502
+ Width = 576
+ OKButton.Name = 'OKButton'
+ OKButton.DefaultCaption = True
+ HelpButton.Name = 'HelpButton'
+ HelpButton.DefaultCaption = True
+ CloseButton.Name = 'CloseButton'
+ CloseButton.DefaultCaption = True
+ CancelButton.Name = 'CancelButton'
+ CancelButton.DefaultCaption = True
+ TabOrder = 4
+ ShowButtons = [pbOK, pbCancel]
+ end
+ object lblLicense: TLabel
+ AnchorSideTop.Control = edtLicense
+ AnchorSideTop.Side = asrCenter
+ AnchorSideRight.Control = edtLicense
+ Left = 56
+ Height = 16
+ Top = 305
+ Width = 56
+ Alignment = taRightJustify
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Right = 8
+ Caption = '&License'
+ FocusControl = edtLicense
+ ParentColor = False
+ end
+ object edtLicense: TEdit
+ AnchorSideLeft.Control = vleCommands
+ AnchorSideTop.Control = vleCommands
+ AnchorSideTop.Side = asrBottom
+ Left = 120
+ Height = 27
+ Top = 300
+ Width = 184
+ BorderSpacing.Top = 8
+ TabOrder = 5
+ end
+ object lblCommands: TLabel
+ AnchorSideTop.Control = vleCommands
+ AnchorSideRight.Control = vleCommands
+ Left = 32
+ Height = 16
+ Top = 180
+ Width = 80
+ Alignment = taRightJustify
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Right = 8
+ Caption = '&Commands'
+ FocusControl = vleCommands
+ ParentColor = False
+ end
+ object lblLicense1: TLabel
+ AnchorSideTop.Control = edtKeywords
+ AnchorSideTop.Side = asrCenter
+ AnchorSideRight.Control = edtKeywords
+ Left = 44
+ Height = 16
+ Top = 341
+ Width = 68
+ Alignment = taRightJustify
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Right = 8
+ Caption = '&Keywords'
+ FocusControl = edtKeywords
+ ParentColor = False
+ end
+ object edtKeywords: TEdit
+ AnchorSideLeft.Control = edtLicense
+ AnchorSideTop.Control = edtLicense
+ AnchorSideTop.Side = asrBottom
+ Left = 120
+ Height = 27
+ Top = 336
+ Width = 445
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Top = 9
+ TabOrder = 6
+ end
+ object lblCommands1: TLabel
+ AnchorSideTop.Control = vleContributesCommands
+ AnchorSideRight.Control = vleContributesCommands
+ Left = 23
+ Height = 32
+ Top = 371
+ Width = 89
+ Alignment = taRightJustify
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Right = 8
+ Caption = '&Contribution '#10'Commands'
+ FocusControl = vleContributesCommands
+ ParentColor = False
+ end
+ object vleContributesCommands: TValueListEditor
+ AnchorSideLeft.Control = edtKeywords
+ AnchorSideTop.Control = edtKeywords
+ AnchorSideTop.Side = asrBottom
+ Left = 120
+ Height = 112
+ Top = 371
+ Width = 445
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Top = 8
+ DefaultColWidth = 192
+ FixedCols = 0
+ RowCount = 2
+ TabOrder = 7
+ KeyOptions = [keyEdit, keyAdd, keyDelete, keyUnique]
+ Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goColSizing, goEditing, goAutoAddRows, goAlwaysShowEditor, goThumbTracking]
+ TitleCaptions.Strings = (
+ 'Command Name'
+ 'Command Description'
+ )
+ ColWidths = (
+ 192
+ 251
+ )
+ end
+ object dePackage: TDirectoryEdit
+ Left = 120
+ Height = 27
+ Top = 8
+ Width = 447
+ ShowHidden = False
+ ButtonWidth = 23
+ NumGlyphs = 1
+ Anchors = [akTop, akLeft, akRight]
+ MaxLength = 0
+ TabOrder = 8
+ end
+ object lblDescription1: TLabel
+ AnchorSideTop.Control = dePackage
+ AnchorSideTop.Side = asrCenter
+ AnchorSideRight.Control = dePackage
+ Left = 34
+ Height = 16
+ Top = 13
+ Width = 78
+ Alignment = taRightJustify
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Right = 8
+ Caption = '&Directory'
+ FocusControl = edtDescription
+ ParentColor = False
+ end
+ object lblClassName: TLabel
+ AnchorSideTop.Control = edtClassName
+ AnchorSideTop.Side = asrCenter
+ AnchorSideRight.Control = edtClassName
+ Left = 32
+ Height = 16
+ Top = 119
+ Width = 79
+ Alignment = taRightJustify
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Right = 9
+ Caption = '&Class Name'
+ FocusControl = edtClassName
+ ParentColor = False
+ end
+ object edtClassName: TEdit
+ AnchorSideLeft.Control = edtName
+ AnchorSideTop.Control = edtName
+ AnchorSideTop.Side = asrBottom
+ Left = 120
+ Height = 27
+ Top = 114
+ Width = 184
+ BorderSpacing.Top = 9
+ OnKeyPress = edtClassNameKeyPress
+ TabOrder = 9
+ end
+ object Label1: TLabel
+ AnchorSideTop.Control = edtPublisher
+ AnchorSideTop.Side = asrCenter
+ AnchorSideRight.Control = edtPublisher
+ Left = 34
+ Height = 16
+ Top = 154
+ Width = 78
+ Alignment = taRightJustify
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Right = 8
+ Caption = 'Publisher'
+ ParentColor = False
+ end
+end
diff --git a/components/pas2js/frmpas2jsvscodeextensionsettings.pas b/components/pas2js/frmpas2jsvscodeextensionsettings.pas
new file mode 100644
index 0000000000..3ad2e32b2f
--- /dev/null
+++ b/components/pas2js/frmpas2jsvscodeextensionsettings.pas
@@ -0,0 +1,176 @@
+unit frmPas2jsVSCodeExtensionSettings;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ValEdit,
+ ButtonPanel, EditBtn;
+
+type
+
+ { TVSCodeExtensionSettingsForm }
+
+ TVSCodeExtensionSettingsForm = class(TForm)
+ ButtonPanel1: TButtonPanel;
+ edtPublisher: TEdit;
+ dePackage: TDirectoryEdit;
+ edtDescription: TEdit;
+ edtKeywords: TEdit;
+ edtName: TEdit;
+ edtLicense: TEdit;
+ edtClassName: TEdit;
+ Label1: TLabel;
+ lblCommands1: TLabel;
+ lblDescription: TLabel;
+ lblDescription1: TLabel;
+ lblLicense1: TLabel;
+ lblName: TLabel;
+ lblLicense: TLabel;
+ lblCommands: TLabel;
+ lblClassName: TLabel;
+ vleContributesCommands: TValueListEditor;
+ vleCommands: TValueListEditor;
+ procedure edtClassNameKeyPress(Sender: TObject; var Key: char);
+ procedure edtNameEditingDone(Sender: TObject);
+ procedure edtNameKeyPress(Sender: TObject; var Key: char);
+ procedure edtPublisherKeyPress(Sender: TObject; var Key: char);
+ procedure FormShow(Sender: TObject);
+ private
+ Function GetValueCtl(aIndex : Integer) : TWinControl;
+ function GetB(AIndex: Integer): Boolean;
+ function GetS(AIndex: Integer): String;
+ function GetSL(AIndex: Integer): TStrings;
+ procedure SetB(AIndex: Integer; AValue: Boolean);
+ procedure SetS(AIndex: Integer; AValue: String);
+ procedure SetSL(AIndex: Integer; AValue: TStrings);
+
+ public
+ Property PkgDescription: String Index 0 read GetS Write SetS;
+ Property PkgName : String Index 1 read GetS Write Sets;
+ Property PkgKeyWords : String Index 2 read GetS Write SetS;
+ Property PkgPublisher : String Index 3 read GetS Write SetS;
+ Property PkgCommands : TStrings Index 4 Read GetSL Write SetSL;
+ Property PkgContributesCommands : TStrings Index 5 Read GetSL Write SetSL;
+ Property PkgLicense : String Index 6 read GetS Write SetS;
+ Property PkgDir : String Index 7 read GetS Write SetS;
+ Property PkgClassName : String Index 8 read GetS Write SetS;
+ end;
+
+ function StripNonIdentifierChars(S : String) : string;
+
+var
+ VSCodeExtensionSettingsForm: TVSCodeExtensionSettingsForm;
+
+implementation
+
+{$R *.lfm}
+
+{ TVSCodeExtensionSettingsForm }
+
+procedure TVSCodeExtensionSettingsForm.edtNameKeyPress(Sender: TObject;
+ var Key: char);
+begin
+ if Not (Upcase(key) in ['A'..'Z','-',#8,#127]) then
+ Key:=#0;
+end;
+
+procedure TVSCodeExtensionSettingsForm.edtPublisherKeyPress(Sender: TObject;
+ var Key: char);
+begin
+ if Not (Upcase(key) in ['A'..'Z',#8,#127]) then
+ Key:=#0;
+end;
+
+procedure TVSCodeExtensionSettingsForm.FormShow(Sender: TObject);
+begin
+{$IFDEF WINDOWS}
+ cbLink.checked:=False;
+ cbLink.Enabled:=False;
+{$ENDIF}
+end;
+
+procedure TVSCodeExtensionSettingsForm.edtClassNameKeyPress(Sender: TObject;
+ var Key: char);
+begin
+ if Not (Upcase(Key) in ['A'..'Z','_',#8,#127]) then
+ Key:=#0;
+end;
+
+function StripNonIdentifierChars(S : String) : string;
+
+begin
+ // Name will only contain characters and -
+ Result:=StringReplace(S,'-','_',[rfReplaceAll]);
+end;
+
+procedure TVSCodeExtensionSettingsForm.edtNameEditingDone(Sender: TObject);
+
+begin
+ if (edtClassName.Text='') then
+ edtClassName.Text:='T'+StripNonIdentifierChars(edtName.Text)+'Application';
+end;
+
+function TVSCodeExtensionSettingsForm.GetValueCtl(aIndex: Integer): TWinControl;
+begin
+ Case AIndex of
+ 0 : Result:=edtDescription;
+ 1 : Result:=edtName;
+ 2 : Result:=edtKeywords;
+ 3 : Result:=edtPublisher;
+ 4 : Result:=vleCommands;
+ 5 : Result:=vleContributesCommands;
+ 6 : Result:=edtLicense;
+ 7 : Result:=dePackage;
+ 8 : Result:=edtClassName;
+ end;
+end;
+
+function TVSCodeExtensionSettingsForm.GetB(AIndex: Integer): Boolean;
+begin
+ Result:=(GetValueCtl(aIndex) as TCheckbox).Checked;
+end;
+
+function TVSCodeExtensionSettingsForm.GetS(AIndex: Integer): String;
+
+Var
+ Ctl : TWinControl;
+
+begin
+ ctl:=GetValueCtl(aIndex);
+ if Ctl is TCustomEdit then
+ Result:=(Ctl as TCustomEdit).text
+ else
+ Result:=(Ctl as TCustomEditButton).Text;
+end;
+
+function TVSCodeExtensionSettingsForm.GetSL(AIndex: Integer): TStrings;
+begin
+ Result:=(GetValueCtl(aIndex) as TValueListEditor).Strings;
+end;
+
+procedure TVSCodeExtensionSettingsForm.SetB(AIndex: Integer; AValue: Boolean);
+begin
+ (GetValueCtl(aIndex) as TCheckbox).Checked:=aValue;
+end;
+
+procedure TVSCodeExtensionSettingsForm.SetS(AIndex: Integer; AValue: String);
+Var
+ Ctl : TWinControl;
+
+begin
+ ctl:=GetValueCtl(aIndex);
+ if Ctl is TCustomEdit then
+ (Ctl as TCustomEdit).text:=aValue
+ else
+ (Ctl as TCustomEditButton).Text:=aValue;
+end;
+
+procedure TVSCodeExtensionSettingsForm.SetSL(AIndex: Integer; AValue: TStrings);
+begin
+ (GetValueCtl(aIndex) as TValueListEditor).Strings.Assign(aValue);
+end;
+
+end.
+
diff --git a/components/pas2js/languages/regpas2jsvscode.pot b/components/pas2js/languages/regpas2jsvscode.pot
new file mode 100644
index 0000000000..37a995a8a1
--- /dev/null
+++ b/components/pas2js/languages/regpas2jsvscode.pot
@@ -0,0 +1,11 @@
+msgid ""
+msgstr "Content-Type: text/plain; charset=UTF-8"
+
+#: regpas2jsvscode.snewvscodeextension
+msgid "Pas2js VS Code extension"
+msgstr ""
+
+#: regpas2jsvscode.snewvscodeextensiondescr
+msgid "Create a new pas2js VS Code extension"
+msgstr ""
+
diff --git a/components/pas2js/languages/strpas2jsdesign.fr.po b/components/pas2js/languages/strpas2jsdesign.fr.po
index c480bae3e9..6f281e7893 100644
--- a/components/pas2js/languages/strpas2jsdesign.fr.po
+++ b/components/pas2js/languages/strpas2jsdesign.fr.po
@@ -173,6 +173,10 @@ msgstr "Sélectionner l'exécutable Node.js"
msgid "Select pas2js executable"
msgstr "Sélectionner l'exécutable de pas2js"
+#: strpas2jsdesign.pjsdselectvscodetemplatedir
+msgid "Select VS Code extension template directory"
+msgstr ""
+
#: strpas2jsdesign.pjsdselectxexecutable
#, object-pascal-format
msgctxt "strpas2jsdesign.pjsdselectxexecutable"
diff --git a/components/pas2js/languages/strpas2jsdesign.hu.po b/components/pas2js/languages/strpas2jsdesign.hu.po
index 32c10f4432..e74b7a37f1 100644
--- a/components/pas2js/languages/strpas2jsdesign.hu.po
+++ b/components/pas2js/languages/strpas2jsdesign.hu.po
@@ -173,6 +173,10 @@ msgstr "A Node.js alkalmazás kiválasztása"
msgid "Select pas2js executable"
msgstr "A pas2js alkalmazás kiválasztása"
+#: strpas2jsdesign.pjsdselectvscodetemplatedir
+msgid "Select VS Code extension template directory"
+msgstr ""
+
#: strpas2jsdesign.pjsdselectxexecutable
#, object-pascal-format
msgctxt "strpas2jsdesign.pjsdselectxexecutable"
diff --git a/components/pas2js/languages/strpas2jsdesign.pot b/components/pas2js/languages/strpas2jsdesign.pot
index e9c8ce3805..a50f543af2 100644
--- a/components/pas2js/languages/strpas2jsdesign.pot
+++ b/components/pas2js/languages/strpas2jsdesign.pot
@@ -161,6 +161,10 @@ msgstr ""
msgid "Select pas2js executable"
msgstr ""
+#: strpas2jsdesign.pjsdselectvscodetemplatedir
+msgid "Select VS Code extension template directory"
+msgstr ""
+
#: strpas2jsdesign.pjsdselectxexecutable
#, object-pascal-format
msgctxt "strpas2jsdesign.pjsdselectxexecutable"
diff --git a/components/pas2js/languages/strpas2jsdesign.pt_BR.po b/components/pas2js/languages/strpas2jsdesign.pt_BR.po
index edaced1a99..b75fc0c274 100644
--- a/components/pas2js/languages/strpas2jsdesign.pt_BR.po
+++ b/components/pas2js/languages/strpas2jsdesign.pt_BR.po
@@ -175,6 +175,10 @@ msgstr "Selecionar executável Node.js"
msgid "Select pas2js executable"
msgstr "Selecionar executável pas2js"
+#: strpas2jsdesign.pjsdselectvscodetemplatedir
+msgid "Select VS Code extension template directory"
+msgstr ""
+
#: strpas2jsdesign.pjsdselectxexecutable
#, object-pascal-format
msgid "Select %s executable"
diff --git a/components/pas2js/languages/strpas2jsdesign.ru.po b/components/pas2js/languages/strpas2jsdesign.ru.po
index 7d684b5e8a..c2d61bda8e 100644
--- a/components/pas2js/languages/strpas2jsdesign.ru.po
+++ b/components/pas2js/languages/strpas2jsdesign.ru.po
@@ -171,6 +171,10 @@ msgstr "Выберите исполнимый файл Node.js"
msgid "Select pas2js executable"
msgstr "Выберите исполнимый файл pas2js"
+#: strpas2jsdesign.pjsdselectvscodetemplatedir
+msgid "Select VS Code extension template directory"
+msgstr ""
+
#: strpas2jsdesign.pjsdselectxexecutable
#, object-pascal-format
msgctxt "strpas2jsdesign.pjsdselectxexecutable"
diff --git a/components/pas2js/languages/strpas2jsdesign.tr.po b/components/pas2js/languages/strpas2jsdesign.tr.po
index cc3a2cde50..075db84c3e 100644
--- a/components/pas2js/languages/strpas2jsdesign.tr.po
+++ b/components/pas2js/languages/strpas2jsdesign.tr.po
@@ -173,6 +173,10 @@ msgstr ""
msgid "Select pas2js executable"
msgstr ""
+#: strpas2jsdesign.pjsdselectvscodetemplatedir
+msgid "Select VS Code extension template directory"
+msgstr ""
+
#: strpas2jsdesign.pjsdselectxexecutable
#, object-pascal-format
msgctxt "strpas2jsdesign.pjsdselectxexecutable"
diff --git a/components/pas2js/languages/strpas2jsdesign.uk.po b/components/pas2js/languages/strpas2jsdesign.uk.po
index cd4c50ef43..186b168a0e 100644
--- a/components/pas2js/languages/strpas2jsdesign.uk.po
+++ b/components/pas2js/languages/strpas2jsdesign.uk.po
@@ -173,6 +173,10 @@ msgstr "Вибрати виконуваний файл Node.js"
msgid "Select pas2js executable"
msgstr "Вибрати виконуваний файл pas2js"
+#: strpas2jsdesign.pjsdselectvscodetemplatedir
+msgid "Select VS Code extension template directory"
+msgstr ""
+
#: strpas2jsdesign.pjsdselectxexecutable
#, object-pascal-format
msgctxt "strpas2jsdesign.pjsdselectxexecutable"
diff --git a/components/pas2js/languages/strpas2jsdesign.zh_CN.po b/components/pas2js/languages/strpas2jsdesign.zh_CN.po
index 9f9b35a8c0..ac39f81acb 100644
--- a/components/pas2js/languages/strpas2jsdesign.zh_CN.po
+++ b/components/pas2js/languages/strpas2jsdesign.zh_CN.po
@@ -174,6 +174,10 @@ msgstr ""
msgid "Select pas2js executable"
msgstr ""
+#: strpas2jsdesign.pjsdselectvscodetemplatedir
+msgid "Select VS Code extension template directory"
+msgstr ""
+
#: strpas2jsdesign.pjsdselectxexecutable
#, object-pascal-format
msgctxt "strpas2jsdesign.pjsdselectxexecutable"
diff --git a/components/pas2js/pas2jsdsgn.lpk b/components/pas2js/pas2jsdsgn.lpk
index a5c79ada39..786a2fb260 100644
--- a/components/pas2js/pas2jsdsgn.lpk
+++ b/components/pas2js/pas2jsdsgn.lpk
@@ -18,7 +18,7 @@
-
+
@@ -70,9 +70,22 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/pas2js/pas2jsdsgn.pas b/components/pas2js/pas2jsdsgn.pas
index 303af81043..d76abfa055 100644
--- a/components/pas2js/pas2jsdsgn.pas
+++ b/components/pas2js/pas2jsdsgn.pas
@@ -11,7 +11,8 @@ uses
PJSDsgnRegister, PJSDsgnOptsFrame, frmpas2jsbrowserprojectoptions,
PJSDsgnOptions, frmpas2jsnodejsprojectoptions, pjscontroller,
frmpas2jswebservers, strpas2jsdesign, pjsprojectoptions,
- frmPas2jsAtomPackageSettings, regpas2jsatom, LazarusPackageIntf;
+ frmPas2jsAtomPackageSettings, regpas2jsatom, regpas2jsvscode,
+ frmPas2jsVSCodeExtensionSettings, LazarusPackageIntf;
implementation
@@ -19,6 +20,7 @@ procedure Register;
begin
RegisterUnit('PJSDsgnRegister', @PJSDsgnRegister.Register);
RegisterUnit('regpas2jsatom', @regpas2jsatom.Register);
+ RegisterUnit('regpas2jsvscode', @regpas2jsvscode.Register);
end;
initialization
diff --git a/components/pas2js/pjsdsgnoptions.pas b/components/pas2js/pjsdsgnoptions.pas
index a63d046f3f..45d8cb3661 100644
--- a/components/pas2js/pjsdsgnoptions.pas
+++ b/components/pas2js/pjsdsgnoptions.pas
@@ -35,7 +35,8 @@ Type
p2jcoHTTPServerFilename,
p2jcoHTTPServerPort,
p2jcoNodeJSFilename,
- p2jcoAtomTemplateDir
+ p2jcoAtomTemplateDir,
+ p2jcoVSCodeTemplateDir
);
TPas2jsCachedOptions = set of TPas2jsCachedOption;
const
@@ -44,7 +45,8 @@ const
p2jcoBrowserFilename,
p2jcoHTTPServerFilename,
p2jcoNodeJSFilename,
- p2jcoAtomTemplateDir
+ p2jcoAtomTemplateDir,
+ p2jcoVSCodeTemplateDir
];
type
@@ -69,12 +71,14 @@ type
function GetBrowserFileName: String;
function GetCompilerFilename: string;
function GetStartAtPort: Word;
+ function GetVSCodeTemplateDir: String;
function GetWebServerFileName: string;
function GetModified: boolean;
function GetNodeJSFileName: string;
function GetParsedOptionValue(Option: TPas2jsCachedOption): string;
procedure SetAtomTemplateDir(AValue: String);
procedure SetBrowserFileName(AValue: String);
+ procedure SetVSCodeTemplateDir(AValue: String);
procedure SetWebServerFileName(AValue: string);
procedure SetHTTPServerOpts(AValue: TStrings);
procedure SetModified(AValue: boolean);
@@ -105,6 +109,7 @@ type
property ChangeStamp: int64 read FChangeStamp;
property Modified: boolean read GetModified write SetModified;
Property AtomTemplateDir : String Read GetAtomTemplateDir Write SetAtomTemplateDir;
+ Property VSCodeTemplateDir : String Read GetVSCodeTemplateDir Write SetVSCodeTemplateDir;
end;
var
@@ -224,7 +229,7 @@ end;
function TPas2jsOptions.GetAtomTemplateDir: String;
begin
- Result:=FCachedOptions[p2jcoBrowserFilename].RawValue;
+ Result:=FCachedOptions[p2jcoAtomTemplateDir].RawValue;
end;
function TPas2jsOptions.GetCompilerFilename: string;
@@ -237,6 +242,11 @@ begin
Result:=StrToIntDef(FCachedOptions[p2jcoHTTPServerPort].RawValue,PJSDefaultStartAtPort);
end;
+function TPas2jsOptions.GetVSCodeTemplateDir: String;
+begin
+ Result:=FCachedOptions[p2jcoVSCodeTemplateDir].RawValue;
+end;
+
function TPas2jsOptions.GetWebServerFileName: string;
begin
Result:=FCachedOptions[p2jcoHTTPServerFilename].RawValue;
@@ -268,6 +278,8 @@ begin
FCachedOptions[p2jcoHTTPServerFilename].RawValue:=PJSDefaultWebServer;
FCachedOptions[p2jcoNodeJSFilename].RawValue:=PJSDefaultNodeJS;
FCachedOptions[p2jcoBrowserFilename].RawValue:=PJSDefaultBrowser;
+ FCachedOptions[p2jcoAtomTemplateDir].RawValue:='';
+ FCachedOptions[p2jcoVSCodeTemplateDir].RawValue:='';
for o in TPas2jsCachedOption do
FCachedOptions[o].Stamp:=LUInvalidChangeStamp64;
FHTTPServerOpts:=TStringList.Create;
@@ -315,6 +327,8 @@ Const
KeyHTTPServerOptions = 'webserver/extraoptions/value';
KeyBrowser = 'webbrowser/value';
KeyNodeJS = 'nodejs/value';
+ KeyAtomTemplate = 'atomtemplate/value';
+ KeyVSCodeTemplate = 'vscodetemplate/value';
KeyStartPortAt = 'webserver/startatport/value';
procedure TPas2jsOptions.LoadFromConfig(Cfg: TConfigStorage);
@@ -324,6 +338,8 @@ begin
WebServerFileName:=Cfg.GetValue(KeyHTTPServer,PJSDefaultWebServer);
BrowserFileName:=Cfg.GetValue(KeyBrowser,PJSDefaultBrowser);
NodeJSFileName:=Cfg.GetValue(KeyNodeJS,PJSDefaultNodeJS);
+ AtomTemplateDir:=Cfg.GetValue(KeyAtomTemplate,'');
+ VSCodeTemplateDir:=Cfg.GetValue(KeyVSCodeTemplate,'');
StartAtPort :=Cfg.GetValue(KeyStartPortAt,PJSDefaultStartAtPort);
Cfg.GetValue(KeyHTTPServerOptions,FHTTPServerOpts);
Modified:=false;
@@ -337,6 +353,8 @@ begin
Cfg.SetDeleteValue(KeyStartPortAt,StartAtPort,PJSDefaultStartAtPort);
Cfg.SetDeleteValue(KeyNodeJS,NodeJSFileName,PJSDefaultNodeJS);
Cfg.SetDeleteValue(KeyBrowser,BrowserFileName,PJSDefaultBrowser);
+ Cfg.SetDeleteValue(KeyAtomTemplate,AtomTemplateDir,'');
+ Cfg.SetDeleteValue(KeyVSCodeTemplate,VSCodeTemplateDir,'');
Cfg.SetValue(KeyHTTPServerOptions,FHTTPServerOpts);
Modified:=false;
end;
@@ -425,6 +443,12 @@ begin
SetCachedOption(p2jcoBrowserFilename,AValue);
end;
+procedure TPas2jsOptions.SetVSCodeTemplateDir(AValue: String);
+begin
+ AValue:=TrimFilename(AValue);
+ SetCachedOption(p2jcoVSCodeTemplateDir,AValue);
+end;
+
procedure TPas2jsOptions.SetWebServerFileName(AValue: string);
begin
AValue:=TrimFilename(AValue);
diff --git a/components/pas2js/pjsdsgnoptsframe.lfm b/components/pas2js/pjsdsgnoptsframe.lfm
index d8cf6ca35c..a4efd36102 100644
--- a/components/pas2js/pjsdsgnoptsframe.lfm
+++ b/components/pas2js/pjsdsgnoptsframe.lfm
@@ -1,10 +1,10 @@
object Pas2jsOptionsFrame: TPas2jsOptionsFrame
Left = 0
- Height = 428
+ Height = 479
Top = 0
Width = 507
BorderSpacing.Left = 6
- ClientHeight = 428
+ ClientHeight = 479
ClientWidth = 507
ParentShowHint = False
ShowHint = True
@@ -277,7 +277,7 @@ object Pas2jsOptionsFrame: TPas2jsOptionsFrame
TabOrder = 10
Text = 'AtomTemplateDirComboBox'
end
- object NodeJSBrowseButton1: TButton
+ object AtomTemplateDirBrowseButton: TButton
AnchorSideTop.Control = AtomTemplateDirComboBox
AnchorSideRight.Control = Owner
AnchorSideRight.Side = asrBottom
@@ -291,7 +291,52 @@ object Pas2jsOptionsFrame: TPas2jsOptionsFrame
AutoSize = True
BorderSpacing.Right = 6
Caption = '...'
- OnClick = NodeJSBrowseButton1Click
+ OnClick = AtomTemplateDirBrowseButtonClick
TabOrder = 11
end
+ object lblVSCodeTemplateDir: TLabel
+ AnchorSideLeft.Control = Owner
+ AnchorSideTop.Control = AtomTemplateDirComboBox
+ AnchorSideTop.Side = asrBottom
+ Left = 6
+ Height = 16
+ Top = 413
+ Width = 227
+ BorderSpacing.Left = 6
+ BorderSpacing.Top = 6
+ Caption = 'VS Code Extension template directory'
+ ParentColor = False
+ end
+ object VSCodeTemplateDirComboBox: TComboBox
+ AnchorSideLeft.Control = lblVSCodeTemplateDir
+ AnchorSideTop.Control = lblVSCodeTemplateDir
+ AnchorSideTop.Side = asrBottom
+ AnchorSideRight.Control = NodeJSBrowseButton
+ Left = 6
+ Height = 27
+ Top = 431
+ Width = 472
+ Anchors = [akTop, akLeft, akRight]
+ BorderSpacing.Top = 2
+ ItemHeight = 0
+ TabOrder = 12
+ Text = 'VSCodeTemplateDirComboBox'
+ end
+ object VSCodeTemplateDirBrowseButton: TButton
+ AnchorSideTop.Control = VSCodeTemplateDirComboBox
+ AnchorSideRight.Control = Owner
+ AnchorSideRight.Side = asrBottom
+ AnchorSideBottom.Control = VSCodeTemplateDirComboBox
+ AnchorSideBottom.Side = asrBottom
+ Left = 478
+ Height = 27
+ Top = 431
+ Width = 23
+ Anchors = [akTop, akRight, akBottom]
+ AutoSize = True
+ BorderSpacing.Right = 6
+ Caption = '...'
+ OnClick = VSCodeTemplateDirBrowseButtonClick
+ TabOrder = 13
+ end
end
diff --git a/components/pas2js/pjsdsgnoptsframe.pas b/components/pas2js/pjsdsgnoptsframe.pas
index ff7b039ce2..3c5275f131 100644
--- a/components/pas2js/pjsdsgnoptsframe.pas
+++ b/components/pas2js/pjsdsgnoptsframe.pas
@@ -24,14 +24,17 @@ Type
{ TPas2jsOptionsFrame }
TPas2jsOptionsFrame = class(TAbstractIDEOptionsEditor)
+ VSCodeTemplateDirBrowseButton: TButton;
+ VSCodeTemplateDirComboBox: TComboBox;
BBrowserBrowseButton: TButton;
BrowserComboBox: TComboBox;
BrowserLabel: TLabel;
HTTPServerBrowseButton: TButton;
HTTPServerCmdLabel: TLabel;
HTTPServerComboBox: TComboBox;
+ lblVSCodeTemplateDir: TLabel;
NodeJSBrowseButton: TButton;
- NodeJSBrowseButton1: TButton;
+ AtomTemplateDirBrowseButton: TButton;
NodeJSComboBox: TComboBox;
AtomTemplateDirComboBox: TComboBox;
NodeJSLabel: TLabel;
@@ -45,9 +48,10 @@ Type
HTTPServerOptionsMemo: TMemo;
procedure BBrowserBrowseButtonClick(Sender: TObject);
procedure HTTPServerBrowseButtonClick(Sender: TObject);
- procedure NodeJSBrowseButton1Click(Sender: TObject);
+ procedure AtomTemplateDirBrowseButtonClick(Sender: TObject);
procedure NodeJSBrowseButtonClick(Sender: TObject);
procedure Pas2jsPathBrowseButtonClick(Sender: TObject);
+ procedure VSCodeTemplateDirBrowseButtonClick(Sender: TObject);
private
function CheckCompiler({%H-}Buttons: TMsgDlgButtons): boolean;
public
@@ -84,6 +88,21 @@ begin
end;
end;
+procedure TPas2jsOptionsFrame.VSCodeTemplateDirBrowseButtonClick(Sender: TObject
+ );
+var
+ ADirname: String;
+
+begin
+ aDirName:=VSCodeTemplateDirComboBox.Text;
+ if SelectDirectory(pjsdSelectVSCodeTemplateDir,aDirName,aDirName) then
+ begin
+ ADirName:=CleanAndExpandFilename(ADirName);
+ SetComboBoxText(VSCodeTemplateDirComboBox,ADirName,cstFilename,30);
+ PJSOptions.VSCodeTemplateDir:=ADirName;
+ end;
+end;
+
procedure TPas2jsOptionsFrame.HTTPServerBrowseButtonClick(Sender: TObject);
var
@@ -106,7 +125,7 @@ begin
end;
end;
-procedure TPas2jsOptionsFrame.NodeJSBrowseButton1Click(Sender: TObject);
+procedure TPas2jsOptionsFrame.AtomTemplateDirBrowseButtonClick(Sender: TObject);
var
ADirname: String;
@@ -237,6 +256,8 @@ begin
SetComboBoxText(BrowserComboBox,PJSOptions.BrowserFileName,cstFilename,30);
SetComboBoxText(NodeJSComboBox,PJSOptions.NodejsFileName,cstFilename,30);
HTTPServerOptionsMemo.Lines:=PJSOptions.HTTPServerOpts;
+ SetComboBoxText(AtomTemplateDirComboBox,PJSOptions.AtomTemplateDir,cstFilename,30);
+ SetComboBoxText(VSCodeTemplateDirComboBox,PJSOptions.VSCodeTemplateDir,cstFilename,30);
end;
procedure TPas2jsOptionsFrame.WriteSettings(AOptions: TAbstractIDEOptions);
@@ -247,6 +268,8 @@ begin
PJSOptions.BrowserFileName:=BrowserComboBox.Text;
PJSOptions.NodeJSFileName:=NodeJSComboBox.Text;
PJSOptions.HTTPServerOpts:=HTTPServerOptionsMemo.Lines;
+ PJSOptions.AtomTemplateDir:=AtomTemplateDirComboBox.Text;
+ PJSOptions.VSCodeTemplateDir:=VSCodeTemplateDirComboBox.Text;
If PJSOptions.Modified then
PJSOptions.Save;
end;
diff --git a/components/pas2js/regpas2jsatom.pas b/components/pas2js/regpas2jsatom.pas
index 566fdc1e84..e85d7e77c4 100644
--- a/components/pas2js/regpas2jsatom.pas
+++ b/components/pas2js/regpas2jsatom.pas
@@ -32,6 +32,7 @@ type
procedure CreateProjectDirs;
procedure CreateProjectSource(Src: TStrings);
procedure DoDefaultReplacements(Src: TStrings);
+ procedure InitVars;
procedure InsertHandlerDefinitions(Src: TStrings; aIndex, aIndent: Integer);
procedure InsertHandlerImplementations(Src: TStrings; aIndex: Integer);
procedure InsertHandlerRegistrations(Src: TStrings; aIndex: Integer);
@@ -112,14 +113,10 @@ end;
constructor TAtomPackageProjectDescriptor.Create;
begin
inherited Create;
- FPackageName:='my-atom-package';
- FPackageDescription:='My atom package';
- FPackageClassName:='TMyAtomPackageApplication';
FKeyWords:=TStringList.Create;
- FPackageLicense:='MIT';
- FLinkPackage:=True;
FCommands:=TStringList.Create;
FActivationCommands:=TStringList.Create;
+ InitVars;
Name:='pas2jsatompackage';
end;
@@ -142,23 +139,28 @@ begin
Result:=pjsdNewAtomPackageDescr;
end;
-
-function TAtomPackageProjectDescriptor.DoInitDescriptor: TModalResult;
+Procedure TAtomPackageProjectDescriptor.InitVars;
begin
FPackageDir:=GetUserDir+'github'+pathdelim+'myatompackage';
FPackageName:='my-atom-package';
FPackageDescription:='My atom package';
FPackageClassName:='TMyAtomPackageApplication';
- FKeyWords:=TStringList.Create;
FPackageLicense:='MIT';
{$IFDEF UNIX}
FLinkPackage:=True;
{$ELSE}
FLinkPackage:=False;
{$ENDIF}
+ FKeywords.Clear;
FCommands.Clear;
FActivationCommands.Clear;
+end;
+
+function TAtomPackageProjectDescriptor.DoInitDescriptor: TModalResult;
+
+begin
+ InitVars;
Result:=ShowOptionsDialog;
end;
@@ -187,7 +189,7 @@ begin
{$ENDIF}
end;
-{$I defaults.inc}
+{$I atomdefaults.inc}
Procedure TAtomPackageProjectDescriptor.InsertHandlerDefinitions(Src : TStrings; aIndex,aIndent : Integer);
diff --git a/components/pas2js/regpas2jsvscode.pas b/components/pas2js/regpas2jsvscode.pas
new file mode 100644
index 0000000000..783223ebef
--- /dev/null
+++ b/components/pas2js/regpas2jsvscode.pas
@@ -0,0 +1,493 @@
+unit regpas2jsvscode;
+
+{$mode objfpc}{$H+}
+interface
+
+uses
+ Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
+ ProjectIntf, BaseIDEIntf, LazIDEIntf, LazFileUtils;
+
+type
+
+ { TVSCodeExtensionProjectDescriptor }
+
+ TVSCodeExtensionProjectDescriptor = class(TProjectDescriptor)
+ Private
+ FPackagePublisher : string;
+ FPackageClassName : String;
+ FPackageDir,
+ FPackageLicense,
+ FPackageName,
+ FPackageDescription : String;
+ FKeyWords,
+ FCommands : TStrings;
+ FContributesCommands : TStrings;
+ FFiles : TStrings;
+ procedure AddFileToProject(const aFileName: string);
+ procedure AddGlueFile(aProject: TLazProject);
+ procedure AddLaunchFile(aProject: TLazProject);
+ procedure AddPackageJSONFile(aProject: TLazProject);
+ procedure AddProjectFile(AProject: TLazProject);
+ procedure AddTasksFile(aProject: TLazProject);
+ procedure CreateProjectDirs;
+ procedure CreateProjectSource(Src: TStrings);
+ procedure DoDefaultReplaceMents(Src: TStrings);
+ procedure InitVars;
+ procedure InsertHandlerDefinitions(Src: TStrings; aIndex, aIndent: Integer);
+ procedure InsertHandlerImplementations(Src: TStrings; aIndex: Integer);
+ procedure InsertHandlerRegistrations(Src: TStrings; aIndex,aIndent: Integer);
+ function LoadDefault(Src: TStrings; aFileName: string): boolean;
+ Function ShowOptionsDialog : TModalResult;
+ public
+ constructor Create(); override;
+ destructor destroy; override;
+ Function DoInitDescriptor : TModalResult; override;
+ function GetLocalizedName: string; override;
+ function GetLocalizedDescription: string; override;
+ function InitProject(AProject: TLazProject) : TModalResult; override;
+ function CreateStartFiles({%H-}AProject: TLazProject) : TModalResult; override;
+ published
+ { Published declarations }
+ end;
+
+procedure Register;
+
+implementation
+
+uses
+ fpjson,frmpas2jsvscodeextensionsettings, CompOptsIntf,
+ NewItemIntf, MenuIntf, pjsprojectoptions, pjsdsgnoptions;
+
+Resourcestring
+ SNewVSCodeExtension = 'Pas2js VS Code extension';
+ SNewVSCodeExtensionDescr = 'Create a new pas2js VS Code extension';
+
+Var
+ VSCodeProjDesc:TVSCodeExtensionProjectDescriptor;
+
+procedure Register;
+
+begin
+ VSCodeProjDesc:=TVSCodeExtensionProjectDescriptor.Create();
+ RegisterProjectDescriptor(VSCodeProjDesc);
+end;
+
+
+{ TVSCodeExtensionProjectDescriptor }
+
+function TVSCodeExtensionProjectDescriptor.ShowOptionsDialog : TModalResult;
+
+begin
+ With TVSCodeExtensionSettingsForm.Create(Application) do
+ try
+ PkgDescription:=FPackageDescription;
+ PkgName:=FPackageName;
+ PkgPublisher:=FPackagePublisher;
+ PkgClassName:=FPackageClassName;
+ PkgCommands:=FCommands;
+ PkgContributesCommands:=FContributesCommands;
+ PkgLicense:=FPackageLicense;
+ PkgKeyWords:=FkeyWords.CommaText;
+ PkgDir:=FPackageDir;
+ Result:=ShowModal;
+ if (Result=mrOK) then
+ begin
+ FPackageDescription:=PkgDescription;
+ FPackageName:=PkgName;
+ FPackageClassName:=PkgClassName;
+ FPackagePublisher:=PkgPublisher;
+ FCommands.Assign(PkgCommands);
+ FContributesCommands.Assign(PkgContributesCommands);
+ FPackageLicense:=PkgLicense;
+ FKeyWords.CommaText:=PkgKeyWords;
+ FPackageDir:=IncludeTrailingPathDelimiter(PkgDir);
+ end;
+ finally
+ Free;
+ end;
+end;
+
+
+constructor TVSCodeExtensionProjectDescriptor.Create;
+begin
+ inherited Create;
+ FKeyWords:=TStringList.Create;
+ FCommands:=TStringList.Create;
+ FContributesCommands:=TStringList.Create;
+ FFiles:=TStringList.Create;
+ InitVars;
+ Name:='pas2jsvscodeextension';
+end;
+
+destructor TVSCodeExtensionProjectDescriptor.destroy;
+begin
+ FreeAndNil(FFiles);
+ FreeAndNil(FCommands);
+ FreeAndNil(FKeywords);
+ FreeAndNil(FContributesCommands);
+ Inherited;
+end;
+
+
+function TVSCodeExtensionProjectDescriptor.GetLocalizedName: string;
+begin
+ Result:=SNewVSCodeExtension;
+end;
+
+function TVSCodeExtensionProjectDescriptor.GetLocalizedDescription: string;
+begin
+ Result:=SNewVSCodeExtensionDescr;
+end;
+
+Procedure TVSCodeExtensionProjectDescriptor.InitVars;
+
+begin
+ FPackageDir:=GetUserDir+'myvscodeextension';
+ FPackageClassName:='TMyVSCodeExtensionApplication';
+
+ FPackageName:='myvscodeextension';
+ FPackageDescription:='My VS Code Extension';
+ FPackagePublisher:='me';
+ FPackageLicense:='MIT';
+ FKeyWords.Clear;
+ FCommands.Clear;
+ FContributesCommands.Clear;
+end;
+
+function TVSCodeExtensionProjectDescriptor.DoInitDescriptor: TModalResult;
+
+begin
+ initVars;
+ Result:=ShowOptionsDialog;
+
+end;
+
+Procedure TVSCodeExtensionProjectDescriptor.CreateProjectDirs;
+
+Const
+ DirCount = 3;
+ DefDirs : Array [1..DirCount] of string =
+ ('','.vscode','js');
+
+Var
+ S : String;
+
+begin
+ FPackageDir:=IncludeLeadingPathDelimiter(FPackageDir);
+ For S in DefDirs do
+ If not ForceDirectories(FPackageDir+S) then
+ ShowMessage('Failed to create directory '+FPackageDir+S);
+end;
+
+{$I vscodedefaults.inc}
+
+Procedure TVSCodeExtensionProjectDescriptor.InsertHandlerDefinitions(Src : TStrings; aIndex,aIndent : Integer);
+
+Var
+ I,Cnt : Integer;
+ Prefix,N,V : String;
+
+ procedure AddLn(aLine : String);
+
+ begin
+ Src.Insert(aIndex+Cnt,aLine);
+ inc(cnt);
+ end;
+
+
+begin
+ cnt:=0;
+ Src.Delete(aIndex);
+ Prefix:=StringOfChar(' ',aIndent-2); // approximate
+ For I:=0 to FCommands.Count-1 do
+ begin
+ FCommands.GetNameValue(I,N,V);
+ AddLn(Prefix+'function '+V+'(args : TJSValueDynArray) : JSValue;');
+ end;
+end;
+
+Procedure TVSCodeExtensionProjectDescriptor.InsertHandlerImplementations(Src : TStrings; aIndex : Integer);
+
+Var
+ cnt : Integer;
+
+ procedure AddLn(aLine : String);
+
+ begin
+ Src.Insert(aIndex+Cnt,aLine);
+ inc(cnt);
+ end;
+Var
+ I : Integer;
+ N,V : String;
+
+begin
+ cnt:=0;
+ Src.Delete(aIndex);
+ For I:=0 to FCommands.Count-1 do
+ begin
+ AddLn('');
+ FCommands.GetNameValue(I,N,V);
+ AddLn('function '+FPackageClassName+'.'+V+'(args : TJSValueDynArray) : JSValue;');
+ AddLn('');
+ AddLn('begin');
+ AddLn(' Result:=null;');
+ AddLn('end;');
+ AddLn('');
+ end;
+end;
+
+Procedure TVSCodeExtensionProjectDescriptor.InsertHandlerRegistrations(Src : TStrings; aIndex,aIndent : Integer);
+
+Var
+ cnt : Integer;
+
+ procedure AddLn(aLine : String);
+
+ begin
+ Src.Insert(aIndex+Cnt,' '+aLine);
+ inc(cnt);
+ end;
+Var
+ I : Integer;
+ N,V : String;
+
+begin
+ Src.Delete(aIndex);
+ if FCommands.Count=0 then exit;
+ For I:=0 to FCommands.Count-1 do
+ begin
+ FCommands.GetNameValue(I,N,V);
+ AddLn('disp:=VSCode.commands.registerCommand('''+N+''', @'+V+');');
+ AddLn('TJSArray(ExtensionContext.subscriptions).push(disp);');
+ end;
+end;
+
+Procedure TVSCodeExtensionProjectDescriptor.DoDefaultReplacements(Src : TStrings);
+
+Var
+ I,P : Integer;
+
+begin
+ For I:=Src.Count-1 downto 0 do
+ begin
+ Src[i]:=StringReplace(Src[I],'%PACKAGENAME%',FPackageName,[rfReplaceALl]);
+ Src[i]:=StringReplace(Src[I],'%PACKAGEPROJECTNAME%',StripNonIdentifierChars(FPackageName),[rfReplaceALl]);
+ Src[i]:=StringReplace(Src[I],'%CLASSNAME%',FPackageClassName,[rfReplaceALl]);
+ P:=pos('%PACKAGEHANDLERINTFS%',Src[i]);
+ if P>0 then
+ InsertHandlerDefinitions(Src,I,P);
+ P:=pos('%PACKAGEHANDLERIMPLS%',Src[i]);
+ if P>0 then
+ InsertHandlerImplementations(Src,I);
+ P:=pos('%PACKAGEHANDLERREGS%',Src[i]);
+ if P>0 then
+ InsertHandlerRegistrations(Src,I,P);
+ end;
+end;
+
+function TVSCodeExtensionProjectDescriptor.LoadDefault(Src : TStrings; aFileName : string) : boolean;
+
+Var
+ FN : String;
+
+begin
+ Result:=(PJSOptions.AtomTemplateDir<>'');
+ if Result then
+ begin
+ FN:=IncludeTrailingPathDelimiter(PJSOptions.AtomTemplateDir)+aFileName;
+ Result:=FileExists(FN);
+ if Result then
+ Src.LoadFromFile(FN);
+ end;
+end;
+
+
+Procedure TVSCodeExtensionProjectDescriptor.AddGlueFile(aProject : TLazProject);
+
+Var
+ Src : TStrings;
+ FN : String;
+
+begin
+ FN:=FPackageDir+'js'+PathDelim+'packageglue.js';
+ Src:=TStringList.Create;
+ try
+ if not LoadDefault(Src,'glue.js') then
+ GetDefaultGlueFile(Src);
+ DoDefaultReplaceMents(Src);
+ Src.SaveToFile(FN);
+ finally
+ Src.Free;
+ end;
+ AddFileToProject(FN);
+end;
+
+Procedure TVSCodeExtensionProjectDescriptor.AddTasksFile(aProject : TLazProject);
+
+Var
+ Src : TStrings;
+ FN : String;
+
+begin
+ FN:=FPackageDir+'.vscode'+PathDelim+'tasks.json';
+ Src:=TStringList.Create;
+ try
+ if not LoadDefault(Src,'tasks.json') then
+ GetDefaultTasksFile(Src);
+ DoDefaultReplaceMents(Src);
+ Src.SaveToFile(FN);
+ finally
+ Src.Free;
+ end;
+ AddFileToProject(FN);
+end;
+
+Procedure TVSCodeExtensionProjectDescriptor.AddLaunchFile(aProject : TLazProject);
+
+Var
+ Src : TStrings;
+ FN : String;
+
+begin
+ FN:=FPackageDir+'.vscode'+PathDelim+'launch.json';
+ Src:=TStringList.Create;
+ try
+ if not LoadDefault(Src,'launch.json') then
+ GetDefaultLaunchFile(Src);
+ DoDefaultReplaceMents(Src);
+ Src.SaveToFile(FN);
+ finally
+ Src.Free;
+ end;
+ AddFileToProject(FN);
+end;
+
+
+
+Procedure TVSCodeExtensionProjectDescriptor.AddPackageJSONFile(aProject : TLazProject);
+
+Var
+ b,aJSON,Contribs,Cmd : TJSONObject;
+ cmds, keys : TJSONArray;
+ S,N,V : String;
+ I : Integer;
+ aStream : TStringStream;
+
+begin
+ aJSON:=TJSONObject.Create([
+ 'name',FPackagename,
+ 'main','js/packageglue.js',
+ 'version','0.0.1',
+ 'description',FPackageDescription,
+ 'license',FPackageLicense
+ ]);
+ try
+ Keys:=TJSONArray.Create;
+ aJSON.add('keywords',keys);
+ For S in FKeyWords do
+ Keys.Add(S);
+ Contribs:=TJSONObject.Create;
+ aJSON.Add('contributes',Contribs);
+ cmds:=TJSONArray.Create;
+ Contribs.Add('commands',cmds);
+ For I:=0 to FContributesCommands.Count-1 do
+ begin
+ FContributesCommands.GetNameValue(I,N,V);
+ cmd:=TJSONObject.Create(['command',N,'title',v]);
+ cmds.Add(cmd);
+ end;
+ cmds:=TJSONArray.Create;
+ aJSON.Add('activationEvents',cmds);
+ for I:=0 to FCommands.Count-1 do
+ begin
+ FContributesCommands.GetNameValue(I,N,V);
+ cmds.Add('onCommand:'+N);
+ end;
+ b:=TJSONObject.Create(['vscode','^1.32.0']);
+ aJSON.Add('engines',b);
+ b:=TJSONObject.Create(['@types/vscode', '^1.32.0']);
+ aJSON.Add('devDependencies',b);
+ aStream:=TStringStream.Create(aJSON.FormatJSON);
+ aStream.SaveToFile(FPackageDir+'package.json');
+ finally
+ aJSON.Free;
+ aStream.Free;
+ end;
+end;
+
+procedure TVSCodeExtensionProjectDescriptor.CreateProjectSource(Src : TStrings);
+
+begin
+ if not LoadDefault(Src,'project.lpr') then
+ GetDefaultProjectFile(Src);
+ DoDefaultReplaceMents(Src);
+
+end;
+
+procedure TVSCodeExtensionProjectDescriptor.AddProjectFile(AProject: TLazProject);
+
+Var
+ aFile : TLazProjectFile;
+ FN : String;
+ Src : TStrings;
+
+begin
+ FN:=FPackageDir+StripNonIdentifierChars(FPackageName)+'.lpr';
+ aFile:=aProject.CreateProjectFile(FN);
+ AFile.IsPartOfProject:=true;
+ AProject.AddFile(AFile,False);
+ AProject.MainFileID:=0;
+ Src:=TStringList.Create;
+ try
+ CreateProjectSource(Src);
+ Src.SaveToFile(FN);
+ AProject.MainFile.SetSourceText(src.Text,true);
+ Finally
+ Src.Free;
+ end;
+end;
+
+function TVSCodeExtensionProjectDescriptor.InitProject(AProject: TLazProject) : TModalResult;
+
+Var
+ CompOpts : TLazCompilerOptions;
+begin
+ AProject.Title:=FPackageName;
+ AProject.ProjectInfoFile:=FPackageDir+StripNonIdentifierChars(FPackageName)+'.lpi';
+ CreateProjectDirs;
+ CompOpts:=AProject.LazCompilerOptions;
+ SetDefaultNodeJSCompileOptions(CompOpts);
+ CompOpts.TargetFilename:='lib/'+StripNonIdentifierChars(FPackageName)+'.js';
+ CompOpts.CustomOptions:='-Jivscodeimports.js -Jirtl.js -Jc '+CompOpts.CustomOptions+' -Javscodeexports.js';
+ SetDefaultNodeRunParams(AProject.RunParameters.GetOrCreate('Default'));
+ AddProjectFile(aProject);
+ Result:=mrOK;
+end;
+
+Procedure TVSCodeExtensionProjectDescriptor.AddFileToProject(Const aFileName : string);
+
+begin
+ FFiles.Add(aFileName);
+end;
+
+
+
+Function TVSCodeExtensionProjectDescriptor.CreateStartFiles(AProject: TLazProject) : TModalresult;
+
+var
+ aFileName : String;
+
+begin
+ FFiles.Clear;
+ AddGlueFile(aProject);
+ AddTasksFile(aProject);
+ AddLaunchFile(aProject);
+ AddPackageJSONFile(aProject);
+ For aFileName in FFiles do
+ LazarusIDE.DoOpenEditorFile(aFileName, -1, -1, [ofProjectLoading,ofQuiet,ofAddToProject]);
+ Result:=mrOK;
+end;
+
+
+end.
diff --git a/components/pas2js/strpas2jsdesign.pp b/components/pas2js/strpas2jsdesign.pp
index b8a2ccb302..c5eef88e22 100644
--- a/components/pas2js/strpas2jsdesign.pp
+++ b/components/pas2js/strpas2jsdesign.pp
@@ -38,6 +38,7 @@ Resourcestring
pjsdSelectNodeJSExecutable = 'Select Node.js executable';
pjsdSelectBrowserExecutable = 'Select browser executable';
pjsdSelectAtomTemplateDir = 'Select Atom package template directory';
+ pjsdSelectVSCodeTemplateDir = 'Select VS Code extension template directory';
pjsdYouCanUseIDEMacrosLikeMakeExeWithoutAFullPathIsSea = 'You can use IDE '
+'macros like $MakeExe(). Without a full path, %s is searched in PATH.';
pjsdPathOfXMacroPas2js = 'Path of %s, macro $(pas2js)';
diff --git a/components/pas2js/vscodedefaults.inc b/components/pas2js/vscodedefaults.inc
new file mode 100644
index 0000000000..388a5c59e9
--- /dev/null
+++ b/components/pas2js/vscodedefaults.inc
@@ -0,0 +1,153 @@
+
+Procedure GetDefaultGlueFile(S : TStrings);
+
+begin
+ With S do
+ begin
+ Add('const vscode = require(''vscode'');');
+ Add('const pascalRuntime = require(''./%PACKAGEPROJECTNAME%.js'');');
+ Add('');
+ Add('var callbacks = {');
+ Add(' onDeactivate: function (a) { }');
+ Add('}');
+ Add('');
+ Add('// this method is called when your extension is activated');
+ Add('function activate(context) {');
+ Add(' pascalRuntime.rtl.run();');
+ Add(' var vscodeEnv = {');
+ Add(' vscodeGlobal: vscode,');
+ Add(' extensionContext: context');
+ Add(' }');
+ Add(' pascalRuntime.pas.program.InitVSCode(vscodeEnv,callbacks);');
+ Add('}');
+ Add('');
+ Add('// this method is called when your extension is deactivated');
+ Add('function deactivate() {');
+ Add(' if (callbacks.onDeactivate) {');
+ Add(' callbacks.onDeactivate(); ');
+ Add(' } ');
+ Add('}');
+ Add('');
+ Add('// eslint-disable-next-line no-undef');
+ Add('module.exports = {');
+ Add(' activate,');
+ Add(' deactivate');
+ Add('}');
+ end;
+end;
+
+Procedure GetDefaultProjectFile(S : TStrings);
+
+begin
+ With S do
+ begin
+ Add('program %PACKAGEPROJECTNAME%;');
+ Add('');
+ Add('{$mode objfpc}');
+ Add('');
+ Add('uses');
+ Add(' JS, Types, Classes, SysUtils, libvscode, vscodeapp;');
+ Add('');
+ Add('');
+ Add('Type');
+ Add(' { %CLASSNAME% }');
+ Add('');
+ Add(' %CLASSNAME% = Class(TVSCodeApplication)');
+ Add(' Protected');
+ Add(' procedure DoActivate; override;');
+ Add(' procedure DoDeactivate; override;');
+ Add(' Public');
+ Add(' // %PACKAGEHANDLERINTFS%');
+ Add(' end;');
+ Add('');
+ Add('');
+ Add('// Do not change the name of this procedure, the Javascript glue code depends on it.');
+ Add('// If you do want to change it, change the glue code as well.');
+ Add('Procedure InitVSCode(aVSCode : TVSCodeEnvironment; aCallBacks : TVSCodeExtensionCallBacks);');
+ Add('');
+ Add('begin');
+ Add(' If Application=Nil then');
+ Add(' Application:=%CLASSNAME%.Create(Nil);');
+ Add(' Application.SaveVSCodeEnvironment(aVSCode,aCallBacks);');
+ Add('end;');
+ Add('');
+ Add('{ %CLASSNAME% }');
+ Add('');
+ Add('procedure %CLASSNAME%.DoActivate;');
+ Add('');
+ Add('Var');
+ Add(' disp : TVSDisposable;');
+ Add('');
+ Add('begin');
+ Add(' inherited DoActivate;');
+ Add(' // %PACKAGEHANDLERREGS%');
+ Add('end;');
+ Add('');
+ Add('procedure %CLASSNAME%.DoDeactivate();');
+ Add('begin');
+ Add(' inherited DoDeactivate();');
+ Add('end;');
+ Add('');
+ Add(' // %PACKAGEHANDLERIMPLS%');
+ Add('');
+
+ Add('// This code is needed to prevent the pas2js compiler from removing the InitAtom call.');
+ Add('var');
+ Add(' dummy : JSValue;');
+ Add('');
+ Add('begin');
+ Add(' Application:=%CLASSNAME%.Create(Nil);');
+ Add(' dummy:=@InitVSCode;');
+ Add('end.');
+ end;
+end;
+
+
+Procedure GetDefaultLaunchFile(S : TStrings);
+
+begin
+ With S do
+ begin
+ Add('{');
+ Add(' "version": "0.2.0",');
+ Add(' "configurations": [');
+ Add(' {');
+ Add(' "name": "Run Extension",');
+ Add(' "type": "extensionHost",');
+ Add(' "request": "launch",');
+ Add(' "runtimeExecutable": "${execPath}",');
+ Add(' "args": [');
+ Add(' "--extensionDevelopmentPath=${workspaceFolder}"');
+ Add(' ]');
+ Add(' }');
+ Add(' ]');
+ Add('}');
+ end;
+end;
+
+Procedure GetDefaultTasksFile(S : TStrings);
+
+begin
+ With S do
+ begin
+ Add(' {');
+ Add(' "version": "2.0.0",');
+ Add(' "tasks": [');
+ Add(' {');
+ Add(' "label": "Compile",');
+ Add(' "type": "shell",');
+ Add(' "command": "pas2js %PACKAGEPROJECTNAME%.lpr -ojs/%PACKAGEPROJECTNAME%.js -Tbrowser -Jivscodeimports.js -Jirtl.js -Javscodeexports.js -Jc ",');
+ Add(' "group":{');
+ Add(' "kind": "build",');
+ Add(' "isDefault": true');
+ Add(' },');
+ Add(' "presentation": {');
+ Add(' "reveal": "always",');
+ Add(' "panel": "new"');
+ Add(' }');
+ Add(' }');
+ Add(' ]');
+ Add(' }');
+ end;
+end;
+