lazarus/components/pas2js/pjsdsgnoptions.pas
michael 2134a62af3 * Implement VS Code template dialog setting
git-svn-id: trunk@64286 -
2020-12-27 16:30:40 +00:00

499 lines
14 KiB
ObjectPascal

{ pas2js options
Author: Mattias Gaertner
}
unit PJSDsgnOptions;
{$mode objfpc}{$H+}
{$Inline on}
interface
uses
Classes, SysUtils,
// LazUtils
LazFileCache, LazConfigStorage, LazFileUtils, FileUtil,
// Codetools
DefineTemplates,
// IdeIntf
MacroIntf, BaseIDEIntf;
const
PJSDsgnOptsFile = 'pas2jsdsgnoptions.xml';
PJSDefaultCompiler = '$MakeExe(IDE,pas2js)';
PJSDefaultWebServerName = 'compileserver';
PJSDefaultWebServer = '$MakeExe(IDE,'+PJSDefaultWebServerName+')';
PJSDefaultStartAtPort = 3000; // compileserver default port
PJSDefaultHTTPServerParams = '-s -p $()';
PJSDefaultBrowser = '$MakeExe(IDE,firefox)';
PJSDefaultNodeJS = '$MakeExe(IDE,nodejs)';
Type
TPas2jsCachedOption = (
p2jcoCompilerFilename,
p2jcoBrowserFilename,
p2jcoHTTPServerFilename,
p2jcoHTTPServerPort,
p2jcoNodeJSFilename,
p2jcoAtomTemplateDir,
p2jcoVSCodeTemplateDir
);
TPas2jsCachedOptions = set of TPas2jsCachedOption;
const
p2jcoFilenames = [
p2jcoCompilerFilename,
p2jcoBrowserFilename,
p2jcoHTTPServerFilename,
p2jcoNodeJSFilename,
p2jcoAtomTemplateDir,
p2jcoVSCodeTemplateDir
];
type
TPas2jsCachedValue = record
RawValue: string;
Stamp: int64;
ParsedValue: string;
end;
PPas2jsCachedValue = ^TPas2jsCachedValue;
{ TPas2jsOptions }
TPas2jsOptions = class
private
FCachedOptions: array[TPas2jsCachedOption] of TPas2jsCachedValue;
FChangeStamp: int64;
FHTTPServerOpts: TStrings;
FSavedStamp: int64;
FStartAtPort: Word;
procedure DoOptsChanged(Sender: TObject);
function GetAtomTemplateDir: String;
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);
procedure SetCompilerFilename(AValue: string);
procedure SetNodeJSFileName(AValue: string);
procedure SetStartAtPort(AValue: Word);
procedure SetCachedOption(Option: TPas2jsCachedOption; const AValue: string);
public
constructor Create;
destructor Destroy; override;
procedure IncreaseChangeStamp; inline;
procedure Load;
procedure Save;
function GetParsedBrowserFilename: string;
function GetParsedCompilerFilename: string;
function GetParsedWebServerFilename: string;
function GetParsedWebServerPort: string;
function GetParsedNodeJSFilename: string;
procedure LoadFromConfig(Cfg: TConfigStorage);
procedure SaveToConfig(Cfg: TConfigStorage);
public
property CompilerFilename: string read GetCompilerFilename write SetCompilerFilename;
Property WebServerFileName : string Read GetWebServerFileName Write SetWebServerFileName;
Property HTTPServerOpts : TStrings Read FHTTPServerOpts Write SetHTTPServerOpts;
Property NodeJSFileName : string Read GetNodeJSFileName Write SetNodeJSFileName;
Property BrowserFileName : String Read GetBrowserFileName Write SetBrowserFileName;
Property StartAtPort : Word Read GetStartAtPort Write SetStartAtPort;
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
PJSOptions: TPas2jsOptions = nil;
function GetStandardPas2jsExe: string;
function GetStandardWebServerExe: string;
function GetStandardBrowser: string;
function GetStandardNodeJS: string;
function GetPas2jsQuality(Filename: string; out Msg: string): boolean;
implementation
uses
strpas2jsdesign;
function GetStandardPas2jsExe: string;
begin
Result:=PJSDefaultCompiler;
if not IDEMacros.SubstituteMacros(Result) then
Result:='pas2js'+GetExeExt;
end;
function GetStandardNodeJS: string;
begin
Result:=PJSDefaultNodeJS;
if not IDEMacros.SubstituteMacros(Result) then
Result:='nodejs'+GetExeExt;
end;
function GetStandardWebServerExe: string;
begin
Result:=PJSDefaultWebServer;
if not IDEMacros.SubstituteMacros(Result) then
Result:='PJSDefaultHTTPServerCmd'+GetExeExt;
end;
function GetStandardBrowser: string;
begin
Result:='$MakeExe(IDE,firefox)';
if not IDEMacros.SubstituteMacros(Result) then
begin
Result:='$MakeExe(IDE,chrome)';
{$ifdef windows}
if not IDEMacros.SubstituteMacros(Result) then
Result:='$MakeExe(IDE,iexplore)';
{$else}
{$ifdef darwin}
if not IDEMacros.SubstituteMacros(Result) then
Result:='$MakeExe(IDE,xdg-open)';
{$endif}
if not IDEMacros.SubstituteMacros(Result) then
Result:='';
{$endif}
end;
end;
function GetPas2jsQuality(Filename: string; out Msg: string): boolean;
var
ShortFile: String;
begin
Msg:='';
Filename:=TrimFilename(Filename);
if (Filename='') then begin
Msg:=pjsdMissingPathToPas2js;
exit(false);
end;
if not FileExistsCached(Filename) then begin
Msg:=SafeFormat(pjsdFileNotFound, [Filename]);
exit(false);
end;
if not DirPathExistsCached(ExtractFilePath(Filename)) then begin
Msg:=SafeFormat(pjsdDirectoryNotFound, [ExtractFilePath(Filename)]);
exit(false);
end;
if not FileIsExecutable(Filename) then begin
Msg:=SafeFormat(pjsdFileNotExecutable, [Filename]);
exit(false);
end;
ShortFile:=ExtractFileNameOnly(Filename);
if not CompareText(LeftStr(ShortFile,length('pas2js')),'pas2js')<>0 then begin
Msg:=pjsdFileNameDoesNotStartWithPas2js;
exit(false);
end;
// run it
//RunTool(Filename);
end;
{ TPas2jsOptions }
procedure TPas2jsOptions.SetModified(AValue: boolean);
begin
if AValue then
IncreaseChangeStamp
else
FSavedStamp:=FChangeStamp;
end;
function TPas2jsOptions.GetModified: boolean;
begin
Result:=FSavedStamp<>FChangeStamp;
end;
function TPas2jsOptions.GetBrowserFileName: String;
begin
Result:=FCachedOptions[p2jcoBrowserFilename].RawValue;
end;
procedure TPas2jsOptions.DoOptsChanged(Sender: TObject);
begin
Self.Modified:=True;
end;
function TPas2jsOptions.GetAtomTemplateDir: String;
begin
Result:=FCachedOptions[p2jcoAtomTemplateDir].RawValue;
end;
function TPas2jsOptions.GetCompilerFilename: string;
begin
Result:=FCachedOptions[p2jcoCompilerFilename].RawValue;
end;
function TPas2jsOptions.GetStartAtPort: Word;
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;
end;
function TPas2jsOptions.GetNodeJSFileName: string;
begin
Result:=FCachedOptions[p2jcoNodeJSFilename].RawValue;
end;
procedure TPas2jsOptions.SetCompilerFilename(AValue: string);
begin
AValue:=TrimFilename(AValue);
SetCachedOption(p2jcoCompilerFilename,AValue);
end;
procedure TPas2jsOptions.SetNodeJSFileName(AValue: string);
begin
AValue:=TrimFilename(AValue);
SetCachedOption(p2jcoNodeJSFilename,AValue);
end;
constructor TPas2jsOptions.Create;
var
o: TPas2jsCachedOption;
begin
FChangeStamp:=LUInvalidChangeStamp64;
FCachedOptions[p2jcoCompilerFilename].RawValue:=PJSDefaultCompiler;
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;
TStringList(FHTTPServerOpts).OnChange:=@DoOptsChanged;
end;
destructor TPas2jsOptions.Destroy;
begin
FreeAndNil(FHTTPServerOpts);
inherited Destroy;
end;
procedure TPas2jsOptions.IncreaseChangeStamp;
begin
LUIncreaseChangeStamp64(FChangeStamp);
end;
procedure TPas2jsOptions.Load;
var
Cfg: TConfigStorage;
begin
Cfg:=GetIDEConfigStorage(PJSDsgnOptsFile,true);
try
LoadFromConfig(Cfg);
finally
Cfg.Free;
end;
end;
procedure TPas2jsOptions.Save;
var
Cfg: TConfigStorage;
begin
Cfg:=GetIDEConfigStorage(PJSDsgnOptsFile,false);
try
SaveToConfig(Cfg);
finally
Cfg.Free;
end;
end;
Const
KeyCompiler = 'compiler/value';
KeyHTTPServer = 'webserver/value';
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);
begin
CompilerFilename:=Cfg.GetValue(KeyCompiler,PJSDefaultCompiler);
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;
end;
procedure TPas2jsOptions.SaveToConfig(Cfg: TConfigStorage);
begin
Cfg.SetDeleteValue(KeyCompiler,CompilerFilename,PJSDefaultCompiler);
Cfg.SetDeleteValue(KeyHTTPServer,WebServerFileName,PJSDefaultWebServer);
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;
function TPas2jsOptions.GetParsedCompilerFilename: string;
begin
Result:=GetParsedOptionValue(p2jcoCompilerFilename);
end;
function TPas2jsOptions.GetParsedWebServerFilename: string;
begin
Result:=GetParsedOptionValue(p2jcoHTTPServerFilename);
end;
function TPas2jsOptions.GetParsedWebServerPort: string;
begin
Result:=GetParsedOptionValue(p2jcoHTTPServerPort);
end;
function TPas2jsOptions.GetParsedNodeJSFilename: string;
begin
Result:=GetParsedOptionValue(p2jcoNodeJSFilename);
end;
function TPas2jsOptions.GetParsedOptionValue(Option: TPas2jsCachedOption
): string;
var
p: PPas2jsCachedValue;
IsFilename: Boolean;
begin
p:=@FCachedOptions[Option];
if p^.Stamp<>IDEMacros.BaseTimeStamp then
begin
p^.Stamp:=IDEMacros.BaseTimeStamp;
p^.ParsedValue:=p^.RawValue;
IDEMacros.SubstituteMacros(p^.ParsedValue);
IsFilename:=Option in p2jcoFilenames;
if IsFilename then
begin
p^.ParsedValue:=TrimFilename(p^.ParsedValue);
if (p^.ParsedValue<>'')
and not FilenameIsAbsolute(p^.ParsedValue) then
begin
if ExtractFilePath(p^.ParsedValue)='' then
p^.ParsedValue:=FindDefaultExecutablePath(p^.ParsedValue)
else
p^.ParsedValue:=''; // not found
end;
end;
if p^.ParsedValue='' then
begin
case Option of
p2jcoCompilerFilename: p^.ParsedValue:=GetStandardPas2jsExe;
p2jcoBrowserFilename: p^.ParsedValue:=GetStandardBrowser;
p2jcoHTTPServerFilename: p^.ParsedValue:=GetStandardWebServerExe;
p2jcoHTTPServerPort: p^.ParsedValue:=IntToStr(PJSDefaultStartAtPort);
p2jcoNodeJSFilename: p^.ParsedValue:=GetStandardNodeJS;
end;
if IsFilename and (p^.ParsedValue<>'')
and not FilenameIsAbsolute(p^.ParsedValue) then
begin
if ExtractFilePath(p^.ParsedValue)='' then
p^.ParsedValue:=FindDefaultExecutablePath(p^.ParsedValue)
else
p^.ParsedValue:=''; // not found
end;
end;
end;
Result:=p^.ParsedValue;
end;
procedure TPas2jsOptions.SetAtomTemplateDir(AValue: String);
begin
AValue:=TrimFilename(AValue);
SetCachedOption(p2jcoAtomTemplateDir,AValue);
end;
function TPas2jsOptions.GetParsedBrowserFilename: string;
begin
Result:=GetParsedOptionValue(p2jcoBrowserFilename);
end;
procedure TPas2jsOptions.SetBrowserFileName(AValue: String);
begin
AValue:=TrimFilename(AValue);
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);
SetCachedOption(p2jcoHTTPServerFilename,AValue);
end;
procedure TPas2jsOptions.SetHTTPServerOpts(AValue: TStrings);
begin
if FHTTPServerOpts=AValue then Exit;
FHTTPServerOpts.Assign(AValue);
end;
procedure TPas2jsOptions.SetStartAtPort(AValue: Word);
begin
if FStartAtPort=AValue then Exit;
FStartAtPort:=AValue;
IncreaseChangeStamp;
end;
procedure TPas2jsOptions.SetCachedOption(Option: TPas2jsCachedOption;
const AValue: string);
begin
if FCachedOptions[Option].RawValue=AValue then exit;
FCachedOptions[Option].RawValue:=AValue;
FCachedOptions[Option].Stamp:=InvalidIDEMacroStamp;
IncreaseChangeStamp;
IDEMacros.IncreaseBaseStamp;
end;
Procedure DonePSJOptions;
begin
if PJSOptions<>nil then
begin
try
if PJSOptions.Modified then
PJSOptions.Save;
except
end;
FreeAndNil(PJSOptions);
end;
end;
finalization
DonePSJOptions;
end.