lazarus/components/pas2js/regpas2jsatom.pas

518 lines
12 KiB
ObjectPascal

unit regpas2jsatom;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
ProjectIntf, LazIDEIntf, LazFileUtils;
type
{ TAtomPackageProjectDescriptor }
TAtomPackageProjectDescriptor = class(TProjectDescriptor)
Private
FPackageClassName,
FPackageDir,
FPackageLicense,
FPackageName,
FPackageDescription : String;
FlinkPackage : Boolean;
FKeyWords,
FCommands : TStrings;
FActivationCommands : TStrings;
FFiles : TStrings;
procedure AddCSSFile({%H-}aProject: TLazProject);
procedure AddFileToProject(const aFileName: string);
procedure AddGlueFile({%H-}aProject: TLazProject);
procedure AddKeyMapFile({%H-}aProject: TLazProject);
procedure AddMenuFile({%H-}aProject: TLazProject);
procedure AddPackageJSONFile({%H-}aProject: TLazProject);
procedure AddProjectFile(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: 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
{$IFDEF UNIX}
baseunix,
{$ENDIF}
fpjson,frmpas2jsatompackagesettings, CompOptsIntf, pjscontroller,
MenuIntf, pjsprojectoptions, pjsdsgnoptions, strpas2jsdesign;
Var
AtomProjDesc:TAtomPackageProjectDescriptor;
procedure Register;
begin
//RegisterIdeMenuCommand(itmOptionsDialogs,STemplateSettings,SProjectTemplateSettings,nil,@ChangeSettings);
AtomProjDesc:=TAtomPackageProjectDescriptor.Create();
RegisterProjectDescriptor(AtomProjDesc);
end;
{ TAtomPackageProjectDescriptor }
function TAtomPackageProjectDescriptor.ShowOptionsDialog : TModalResult;
begin
With TAtomPackageSettingsForm.Create(Application) do
try
PkgDescription:=FPackageDescription;
PkgName:=FPackageName;
pkgClassName:= FPackageClassName;
pkgLink:=FlinkPackage;
PkgCommands:=FCommands;
PkgActivationCommands:=FActivationCommands;
PkgLicense:=FPackageLicense;
PkgKeyWords:=FkeyWords.CommaText;
PkgDir:=FPackageDir;
Result:=ShowModal;
if (Result=mrOK) then
begin
FPackageDescription:=PkgDescription;
FPackageName:=PkgName;
FlinkPackage:=pkgLink;
FCommands.Assign(PkgCommands);
FActivationCommands.Assign(PkgActivationCommands);
FPackageLicense:=PkgLicense;
FKeyWords.CommaText:=PkgKeyWords;
FPackageDir:=IncludeTrailingPathDelimiter(PkgDir);
FPackageClassName:=pkgClassName;
end;
finally
Free;
end;
end;
constructor TAtomPackageProjectDescriptor.Create;
begin
inherited Create;
FKeyWords:=TStringList.Create;
FCommands:=TStringList.Create;
FActivationCommands:=TStringList.Create;
FFiles:=TStringList.Create;
InitVars;
Name:='pas2jsatompackage';
end;
destructor TAtomPackageProjectDescriptor.destroy;
begin
FreeAndNil(FFiles);
FreeAndNil(FCommands);
FreeAndNil(FKeywords);
FreeAndNil(FActivationCommands);
Inherited;
end;
function TAtomPackageProjectDescriptor.GetLocalizedName: string;
begin
Result:=pjsdNewAtomPackage;
end;
function TAtomPackageProjectDescriptor.GetLocalizedDescription: string;
begin
Result:=pjsdNewAtomPackageDescr;
end;
Procedure TAtomPackageProjectDescriptor.InitVars;
begin
FPackageDir:=GetUserDir+'github'+pathdelim+'myatompackage';
FPackageName:='my-atom-package';
FPackageDescription:='My atom package';
FPackageClassName:='TMyAtomPackageApplication';
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;
Procedure TAtomPackageProjectDescriptor.CreateProjectDirs;
Const
DirCount = 5;
DefDirs : Array [1..DirCount] of string =
('','lib','keymaps','menus','styles');
Var
S : String;
{$IFDEF UNIX}
L : String;
{$ENDIF}
begin
FPackageDir:=IncludeLeadingPathDelimiter(FPackageDir);
For S in DefDirs do
If not ForceDirectories(FPackageDir+S) then
ShowMessage('Failed to create directory '+FPackageDir+S);
{$IFDEF UNIX}
if FLinkPackage then
begin
L:=Sysutils.GetUserDir+'.atom'+PathDelim+'packages/'+FPackageName;
fpSymlink(PChar(FPackageDir),PChar(L));
end;
{$ENDIF}
end;
{$I atomdefaults.inc}
Procedure TAtomPackageProjectDescriptor.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+'Procedure '+V+';');
end;
end;
Procedure TAtomPackageProjectDescriptor.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('Procedure '+FPackageClassName+'.'+V+';');
AddLn('');
AddLn('begin');
AddLn('end;');
AddLn('');
end;
end;
Procedure TAtomPackageProjectDescriptor.InsertHandlerRegistrations(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
Src.Delete(aIndex);
if FCommands.Count=0 then exit;
AddLn('cmds:=TJSObject.New;');
For I:=0 to FCommands.Count-1 do
begin
FCommands.GetNameValue(I,N,V);
AddLn('cmds['''+N+''']:=@'+V+';');
end;
AddLn('subscriptions.add(atom.commands.add(''workspace'', cmds));');
end;
Procedure TAtomPackageProjectDescriptor.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);
end;
end;
function TAtomPackageProjectDescriptor.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 TAtomPackageProjectDescriptor.AddGlueFile(aProject : TLazProject);
Var
Src : TStrings;
FN : String;
begin
FN:=FPackageDir+'lib'+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 TAtomPackageProjectDescriptor.AddCSSFile(aProject : TLazProject);
Var
Src : TStrings;
FN : String;
begin
FN:=FPackageDir+'styles'+PathDelim+'package.less';
Src:=TStringList.Create;
try
if not LoadDefault(Src,'package.less') then
GetDefaultCSSFile(Src);
DoDefaultReplaceMents(Src);
Src.SaveToFile(FN);
finally
Src.Free;
end;
AddFileToProject(FN);
end;
Procedure TAtomPackageProjectDescriptor.AddKeyMapFile(aProject : TLazProject);
Var
Src : TStrings;
FN : String;
begin
FN:=FPackageDir+'keymaps'+PathDelim+'keymaps.json';
Src:=TStringList.Create;
try
if not LoadDefault(Src,'keymaps.json') then
GetDefaultKeyMapFile(Src);
DoDefaultReplaceMents(Src);
Src.SaveToFile(FN);
finally
Src.Free;
end;
AddFileToProject(FN);
end;
Procedure TAtomPackageProjectDescriptor.AddMenuFile(aProject : TLazProject);
Var
Src : TStrings;
FN : String;
begin
FN:=FPackageDir+'menus'+PathDelim+'menu.json';
Src:=TStringList.Create;
try
if not LoadDefault(Src,'menu.json') then
GetDefaultMenuFile(Src);
DoDefaultReplaceMents(Src);
Src.SaveToFile(FN);
finally
Src.Free;
end;
AddFileToProject(FN);
end;
Procedure TAtomPackageProjectDescriptor.AddPackageJSONFile(aProject : TLazProject);
Var
aJSON,B : TJSONObject;
keys : TJSONArray;
S,N,V,FN : String;
JS : TJSONStringType;
I : Integer;
aStream : TStringStream;
begin
aJSON:=TJSONObject.Create([
'name',FPackagename,
'main','lib/packageglue',
'version','0.0.1',
'description',FPackageDescription,
'license',FPackageLicense
]);
try
Keys:=TJSONArray.Create;
aJSON.add('keywords',keys);
For S in FKeyWords do
Keys.Add(S);
b:=TJSONObject.Create;
aJSON.Add('activationCommands',b);
For I:=0 to FActivationCommands.Count-1 do
begin
FActivationCommands.GetNameValue(I,N,V);
b.Add(V,FPackageName+':'+N);
end;
b:=TJSONObject.Create(['atom','>=1.0.0 <2.0.0']);
aJSON.Add('engines',b);
b:=TJSONObject.Create([]);
aJSON.Add('dependencies',b);
JS:=aJSON.FormatJSON;
aStream:=TStringStream.Create(JS);
FN:=FPackageDir+'package.json';
aStream.SaveToFile(FN);
addFileToProject(FN);
finally
aJSON.Free;
end;
end;
procedure TAtomPackageProjectDescriptor.CreateProjectSource(Src : TStrings);
begin
if not LoadDefault(Src,'project.lpr') then
GetDefaultProjectFile(Src);
DoDefaultReplaceMents(Src);
end;
procedure TAtomPackageProjectDescriptor.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 TAtomPackageProjectDescriptor.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:='-Jiatomimports.js -Jirtl.js -Jc '+CompOpts.CustomOptions+' -Jaatomexports.js';
SetDefaultNodeRunParams(AProject.RunParameters.GetOrCreate('Default'));
AddProjectFile(aProject);
Result:=mrOK;
end;
Procedure TAtomPackageProjectDescriptor.AddFileToProject(Const aFileName : string);
begin
FFiles.Add(aFileName);
end;
Function TAtomPackageProjectDescriptor.CreateStartFiles(AProject: TLazProject) : TModalresult;
Var
aFileName : String;
begin
AddGlueFile(aProject);
AddCSSFile(aProject);
AddKeyMapFile(aProject);
AddMenuFile(aProject);
AddPackageJSONFile(aProject);
For aFileName in FFiles do
LazarusIDE.DoOpenEditorFile(aFileName, -1, -1, [ofProjectLoading,ofQuiet,ofAddToProject]);
Result:=mrOK;
end;
end.