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; +