mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-30 17:03:39 +02:00
491 lines
12 KiB
ObjectPascal
491 lines
12 KiB
ObjectPascal
unit regpas2jsvscode;
|
|
|
|
{$mode objfpc}{$H+}
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
|
|
ProjectIntf, 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({%H-}aProject: TLazProject);
|
|
procedure AddLaunchFile({%H-}aProject: TLazProject);
|
|
procedure AddPackageJSONFile({%H-}aProject: TLazProject);
|
|
procedure AddProjectFile(AProject: TLazProject);
|
|
procedure AddTasksFile({%H-}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, pjscontroller,
|
|
MenuIntf, pjsprojectoptions, pjsdsgnoptions, strpas2jsdesign;
|
|
|
|
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:=pjsdNewVSCodeExtension;
|
|
end;
|
|
|
|
function TVSCodeExtensionProjectDescriptor.GetLocalizedDescription: string;
|
|
begin
|
|
Result:=pjsdNewVSCodeExtensionDescr;
|
|
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,Space(aIndent)+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';
|
|
AProject.CustomData.Values[PJSProject]:='1';
|
|
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.
|