options editor, move the options related to the runnables to their own category

This commit is contained in:
Basile Burg 2016-08-15 04:36:34 +02:00
parent 42fa9149b0
commit e3e42ead05
1 changed files with 239 additions and 62 deletions

View File

@ -25,6 +25,53 @@ type
property OnMouseWheel; property OnMouseWheel;
end; end;
TRunnableToFolderCondition = (
ifInProject, // runnable src is part of the project
ifNotSaved, // runnable src is an unsaved module (tmp_XXXXX)
ifSaved // runnable src not in project but saved not in temp dir
);
TCERunnableOptions = class(TWritableLfmTextComponent)
private
fCompiler: TCECompiler;
fDetectMain: boolean;
fDetectLibraries: boolean;
fOutputFolder: TCEPathname;
fAlwaysToFolder: boolean;
fStaticSwitches: TStringList;
procedure setOutputFolder(const value: TCEPathname);
procedure setStaticSwitches(value: TStringList);
procedure setCompiler(value: TCECompiler);
protected
procedure afterLoad; override;
published
property alwaysToFolder: boolean read fAlwaysToFolder write fAlwaysToFolder;
property compiler: TCECompiler read fCompiler write setCompiler;
property detectMain: boolean read fDetectMain write fDetectMain;
property detectLibraries: boolean read fDetectLibraries write fDetectLibraries;
property outputFolder: TCEPathname read fOutputFolder write setOutputFolder;
property staticSwitches: TStringList read fStaticSwitches write setStaticSwitches;
public
constructor create(aOwner: TComponent); override;
destructor destroy; override;
procedure assign(source: TPersistent); override;
procedure setDefaultSwitches;
procedure sanitizeSwitches;
end;
TCEEditableRunnableOptions = class(TCERunnableOptions, ICEEditableOptions)
private
fBackup: TCERunnableOptions;
function optionedWantCategory(): string;
function optionedWantEditorKind: TOptionEditorKind;
function optionedWantContainer: TPersistent;
procedure optionedEvent(event: TOptionEditorEvent);
function optionedOptionsModified: boolean;
public
constructor create(aOwner: TComponent); override;
destructor destroy; override;
end;
{ TCEMainForm } { TCEMainForm }
TCEMainForm = class(TForm, ICEDocumentObserver, ICEEditableShortCut, ICEProjectObserver) TCEMainForm = class(TForm, ICEDocumentObserver, ICEEditableShortCut, ICEProjectObserver)
actFileCompAndRun: TAction; actFileCompAndRun: TAction;
@ -272,13 +319,12 @@ type
private private
fRunnablesOptions: TCEEditableRunnableOptions;
fRunnableCompiler: TCECompiler; fRunnableCompiler: TCECompiler;
fRunnableDestination: string;
fSymStringExpander: ICESymStringExpander; fSymStringExpander: ICESymStringExpander;
fProjectGroup: ICEProjectGroup; fProjectGroup: ICEProjectGroup;
fCovModUt: boolean; fCovModUt: boolean;
fDscanUnittests: boolean; fDscanUnittests: boolean;
fAlwaysUseDest: boolean;
fDoc: TCESynMemo; fDoc: TCESynMemo;
fFirstTimeCoedit: boolean; fFirstTimeCoedit: boolean;
fActionHandler: TCEActionProviderSubject; fActionHandler: TCEActionProviderSubject;
@ -316,7 +362,6 @@ type
fGroupCompilationCnt: integer; fGroupCompilationCnt: integer;
fProjFromCommandLine: boolean; fProjFromCommandLine: boolean;
fInitialized: boolean; fInitialized: boolean;
fRunnableSw: string;
fRunProc: TCEProcess; fRunProc: TCEProcess;
fMsgs: ICEMessagesDisplay; fMsgs: ICEMessagesDisplay;
fMainMenuSubj: TCEMainMenuSubject; fMainMenuSubj: TCEMainMenuSubject;
@ -504,21 +549,22 @@ type
property maxRecentDocuments: integer read fMaxRecentDocs write fMaxRecentDocs; property maxRecentDocuments: integer read fMaxRecentDocs write fMaxRecentDocs;
property dubCompiler: TCECompiler read getDubCompiler write setDubCompiler; property dubCompiler: TCECompiler read getDubCompiler write setDubCompiler;
property nativeProjectCompiler: TCECompiler read getNativeProjecCompiler write setNativeProjecCompiler; property nativeProjectCompiler: TCECompiler read getNativeProjecCompiler write setNativeProjecCompiler;
property runnableCompiler: TCECompiler read getRunnableCompiler write setRunnableCompiler;
property runnableDestination: TCEPathname read fRunnableDest write setRunnableDestination;
property runnableDestinationAlways: boolean read fAlwaysUseDest write fAlwaysUseDest;
property dscanUnittests: boolean read fDscanUnittests write fDscanUnittests default true; property dscanUnittests: boolean read fDscanUnittests write fDscanUnittests default true;
property autoSaveProjectFiles: boolean read fAutoSaveProjectFiles write fAutoSaveProjectFiles default false; property autoSaveProjectFiles: boolean read fAutoSaveProjectFiles write fAutoSaveProjectFiles default false;
property flatLook: boolean read fFlatLook write fFlatLook; property flatLook: boolean read fFlatLook write fFlatLook;
property detectMain: boolean read fDetectMain write fDetectMain;
property detectRunnableImports: boolean read fDetectRunnableImports write fDetectRunnableImports;
property splitterScrollSpeed: byte read fSplitterScrollSpeed write setSplitterScsrollSpeed; property splitterScrollSpeed: byte read fSplitterScrollSpeed write setSplitterScsrollSpeed;
// published for ICEEditableOptions but stored by DCD wrapper since it reloads before CEMainForm // published for ICEEditableOptions but stored by DCD wrapper since it reloads before CEMainForm
property dcdPort: word read fDcdPort write fDcdPort stored false; property dcdPort: word read fDcdPort write fDcdPort stored false;
// TODO-cmaintenance: remove this property from version 3 gold
property detectRunnableImports: boolean read fDetectRunnableImports write fDetectRunnableImports stored false; deprecated;
property runnableCompiler: TCECompiler read getRunnableCompiler write setRunnableCompiler stored false; deprecated;
property detectMain: boolean read fDetectMain write fDetectMain stored false; deprecated;
// TODO-cmaintenance: remove this property from version 3 update 1 // TODO-cmaintenance: remove this property from version 3 update 1
property nativeProjecCompiler: TCECompiler read getNativeProjecCompiler write setNativeProjecCompiler stored false; property nativeProjecCompiler: TCECompiler read getNativeProjecCompiler write setNativeProjecCompiler stored false; deprecated;
property runnableDestination: TCEPathname read fRunnableDest write setRunnableDestination stored false; deprecated;
property runnableDestinationAlways: boolean read fAlwaysUseDest write fAlwaysUseDest stored false; deprecated;
end; end;
TCEApplicationOptions = class(TCEApplicationOptionsBase, ICEEditableOptions) TCEApplicationOptions = class(TCEApplicationOptionsBase, ICEEditableOptions)
@ -546,7 +592,162 @@ implementation
uses uses
SynMacroRecorder, ce_dcd; SynMacroRecorder, ce_dcd;
{$REGION TCEApplicationOptions ------------------------------------------------------} {$REGION TCERunnableOptions ----------------------------------------------------}
constructor TCERunnableOptions.create(aOwner: TComponent);
begin
inherited;
fStaticSwitches := TStringList.create;
fStaticSwitches.Duplicates := TDuplicates.dupIgnore;
end;
destructor TCERunnableOptions.destroy;
begin
fStaticSwitches.free;
inherited;
end;
procedure TCERunnableOptions.assign(source: TPersistent);
var
src: TCERunnableOptions;
begin
if source is TCERunnableOptions then
begin
src := TCERunnableOptions(source);
fCompiler:= src.fCompiler;
fDetectMain:= src.fDetectMain;
fDetectLibraries:= src.fDetectLibraries;
fOutputFolder:= src.fOutputFolder;
fAlwaysToFolder:= src.alwaysToFolder;
fStaticSwitches.assign(src.fStaticSwitches);
end
else inherited;
end;
procedure TCERunnableOptions.setStaticSwitches(value: TStringList);
begin
fStaticSwitches.Assign(value);
sanitizeSwitches;
end;
procedure TCERunnableOptions.afterLoad;
begin
inherited;
if fStaticSwitches.Count = 0 then
setDefaultSwitches
else
sanitizeSwitches;
end;
procedure TCERunnableOptions.setDefaultSwitches;
begin
fStaticSwitches.Clear;
fStaticSwitches.AddStrings(['-vcolumns', '-w', '-wi']);
end;
procedure TCERunnableOptions.sanitizeSwitches;
var
i: integer;
sw: string;
lst: TStringList;
begin
lst := TStringList.Create;
try
for i:= 0 to fStaticSwitches.Count-1 do
begin
sw := fStaticSwitches[i];
RemovePadChars(sw, [#0..#32]);
// not a switch
if sw.length < 2 then
continue
else if sw[1] <> '-' then
continue
// set according to the context
else if sw = '-unittest' then
continue
else if sw = '-main' then
continue
// would break location detection
else if (sw.length > 2) and (sw[1..3] = '-of') then
continue
else
lst.Add(sw);
end;
fStaticSwitches.Assign(lst);
finally
lst.free;
end;
end;
procedure TCERunnableOptions.setOutputFolder(const value: TCEPathname);
begin
fOutputFolder := value;
if (length(fOutputFolder) > 0)
and (fOutputFolder[length(fOutputFolder)] <> DirectorySeparator) then
fOutputFolder += DirectorySeparator;
end;
procedure TCERunnableOptions.setCompiler(value: TCECompiler);
begin
case value of
ldc: if not exeInSysPath('ldmd2' + exeExt) then
value := dmd;
gdc: if not exeInSysPath('gdmd' + exeExt) then
value := dmd;
end;
fCompiler :=value;
end;
constructor TCEEditableRunnableOptions.create(aOwner: TComponent);
begin
inherited;
fBackup := TCERunnableOptions.create(nil);
EntitiesConnector.addObserver(self);
end;
destructor TCEEditableRunnableOptions.destroy;
begin
fBackup.free;
EntitiesConnector.removeObserver(self);
inherited;
end;
function TCEEditableRunnableOptions.optionedWantCategory(): string;
begin
exit('Runnable modules');
end;
function TCEEditableRunnableOptions.optionedWantEditorKind: TOptionEditorKind;
begin
exit(oekGeneric);
end;
function TCEEditableRunnableOptions.optionedWantContainer: TPersistent;
begin
exit(self);
fBackup.assign(self);
end;
procedure TCEEditableRunnableOptions.optionedEvent(event: TOptionEditorEvent);
begin
case event of
oeeAccept:
begin
fBackup.assign(self);
sanitizeSwitches;
end;
oeeCancel: assign(fBackup);
oeeSelectCat: fBackup.assign(self);
end;
end;
function TCEEditableRunnableOptions.optionedOptionsModified: boolean;
begin
exit(false);
end;
{$ENDREGION --------------------------------------------------------------------}
{$REGION TCEApplicationOptions -------------------------------------------------}
constructor TCEApplicationOptions.Create(AOwner: TComponent); constructor TCEApplicationOptions.Create(AOwner: TComponent);
begin begin
inherited; inherited;
@ -651,8 +852,6 @@ begin
fMaxRecentDocs:= CEMainForm.fFileMru.maxCount; fMaxRecentDocs:= CEMainForm.fFileMru.maxCount;
fDcdPort := DcdWrapper.port; fDcdPort := DcdWrapper.port;
fCovModUt:= CEMainForm.fCovModUt; fCovModUt:= CEMainForm.fCovModUt;
fRunnableDest := CEMainForm.fRunnableDestination;
fAlwaysUseDest := CEMainForm.fAlwaysUseDest;
fDscanUnittests := CEMainForm.fDscanUnittests; fDscanUnittests := CEMainForm.fDscanUnittests;
end else if source = fBackup then end else if source = fBackup then
begin begin
@ -663,8 +862,6 @@ begin
fReloadLastDocuments:=fBackup.fReloadLastDocuments; fReloadLastDocuments:=fBackup.fReloadLastDocuments;
fFloatingWidgetOnTop := fBackup.fFloatingWidgetOnTop; fFloatingWidgetOnTop := fBackup.fFloatingWidgetOnTop;
fFlatLook:=fBackup.fFlatLook; fFlatLook:=fBackup.fFlatLook;
CEMainForm.fRunnableDestination := fBackup.fRunnableDest;
CEmainForm.fAlwaysUseDest := fBackup.fAlwaysUseDest;
CEMainForm.fDscanUnittests := fDscanUnittests; CEMainForm.fDscanUnittests := fDscanUnittests;
end end
else inherited; else inherited;
@ -680,8 +877,6 @@ begin
CEMainForm.fProjMru.maxCount := fMaxRecentProjs; CEMainForm.fProjMru.maxCount := fMaxRecentProjs;
CEMainForm.fFileMru.maxCount := fMaxRecentDocs; CEMainForm.fFileMru.maxCount := fMaxRecentDocs;
CEMainForm.updateFloatingWidgetOnTop(fFloatingWidgetOnTop); CEMainForm.updateFloatingWidgetOnTop(fFloatingWidgetOnTop);
CEMainForm.fRunnableDestination := fRunnableDest;
CEMainForm.fAlwaysUseDest := fAlwaysUseDest;
CEMainForm.fDscanUnittests := fDscanUnittests; CEMainForm.fDscanUnittests := fDscanUnittests;
DcdWrapper.port:=fDcdPort; DcdWrapper.port:=fDcdPort;
for i := 0 to CEMainForm.fWidgList.Count-1 do for i := 0 to CEMainForm.fWidgList.Count-1 do
@ -694,8 +889,6 @@ begin
fBackup.fFloatingWidgetOnTop:=fFloatingWidgetOnTop; fBackup.fFloatingWidgetOnTop:=fFloatingWidgetOnTop;
fBackup.fDcdPort:=fDcdPort; fBackup.fDcdPort:=fDcdPort;
fBackup.fCovModUt:=fCovModUt; fBackup.fCovModUt:=fCovModUt;
fBackup.fRunnableDest:= fRunnableDest;
fBackup.fAlwaysUseDest := fAlwaysUseDest;
fBackup.fDscanUnittests:= fDscanUnittests; fBackup.fDscanUnittests:= fDscanUnittests;
fBackup.fFlatLook:= fFlatLook; fBackup.fFlatLook:= fFlatLook;
end end
@ -1250,6 +1443,11 @@ begin
finally finally
Free; Free;
end; end;
// runnables opts
fRunnablesOptions := TCEEditableRunnableOptions.create(self);
fname := getCoeditDocPath + 'runnables.txt';
if fname.fileExists then
fRunnablesOptions.loadFromFile(fname);
// globals opts // globals opts
fAppliOpts := TCEApplicationOptions.Create(self); fAppliOpts := TCEApplicationOptions.Create(self);
fname := getCoeditDocPath + 'application.txt'; fname := getCoeditDocPath + 'application.txt';
@ -1284,6 +1482,8 @@ begin
// globals opts // globals opts
fAppliOpts.assign(self); fAppliOpts.assign(self);
fAppliOpts.saveToFile(getCoeditDocPath + 'application.txt'); fAppliOpts.saveToFile(getCoeditDocPath + 'application.txt');
// runnables opts
fRunnablesOptions.saveToFile(getCoeditDocPath + 'runnables.txt');
end; end;
procedure TCEMainForm.SaveDocking; procedure TCEMainForm.SaveDocking;
@ -2220,6 +2420,8 @@ end;
{$REGION run -------------------------------------------------------------------} {$REGION run -------------------------------------------------------------------}
function TCEMainForm.runnableExename: string; function TCEMainForm.runnableExename: string;
var
ofr: string;
begin begin
result := ''; result := '';
if fDoc.isNil then if fDoc.isNil then
@ -2228,19 +2430,20 @@ begin
result := stripFileExt(fDoc.fileName) + exeExt; result := stripFileExt(fDoc.fileName) + exeExt;
if fDoc.isTemporary then if fDoc.isTemporary then
exit; exit;
if fRunnableDestination.isNotEmpty then ofr := fRunnablesOptions.outputFolder;
if ofr.isNotEmpty then
begin begin
if not fAlwaysUseDest and assigned(fProject) if not fRunnablesOptions.alwaysToFolder and assigned(fProject)
and not fProject.isSource(fDoc.fileName) then and not fProject.isSource(fDoc.fileName) then
exit; exit;
if FilenameIsAbsolute(fRunnableDestination) then if FilenameIsAbsolute(ofr) then
begin begin
if fRunnableDestination.dirExists then if ofr.dirExists then
result := fRunnableDestination + stripFileExt(fDoc.fileName.extractFileName) result := ofr + stripFileExt(fDoc.fileName.extractFileName)
+ exeExt; + exeExt;
end else end else
begin begin
result := fDoc.fileName.extractFilePath + fRunnableDestination result := fDoc.fileName.extractFilePath + ofr
+ stripFileExt(fDoc.fileName.extractFileName) + exeExt; + stripFileExt(fDoc.fileName.extractFileName) + exeExt;
end; end;
end; end;
@ -2289,45 +2492,19 @@ var
i, j: integer; i, j: integer;
cur: string; cur: string;
begin begin
if fRunnableSw = '' then if fRunnablesOptions.fStaticSwitches.Count = 0 then
fRunnableSw := '-vcolumns'#13'-w'#13'-wi'; fRunnablesOptions.setDefaultSwitches;
form := TForm.Create(nil); form := TForm.Create(nil);
form.BorderIcons:= [biSystemMenu]; form.BorderIcons:= [biSystemMenu];
memo := TMemo.Create(form); memo := TMemo.Create(form);
memo.Align := alClient; memo.Align := alClient;
memo.BorderSpacing.Around:=4; memo.BorderSpacing.Around:=4;
memo.Text := fRunnableSw; memo.Lines.Assign(fRunnablesOptions.staticSwitches);
memo.Parent := form; memo.Parent := form;
form.ShowModal; form.ShowModal;
// //
fRunnableSw := ''; fRunnablesOptions.staticSwitches.Assign(memo.Lines);
for i := memo.Lines.Count-1 downto 0 do fRunnablesOptions.sanitizeSwitches;
begin
cur := memo.Lines[i];
// duplicated item
j := memo.Lines.IndexOf(cur);
if (j > -1) and (j < i) then
continue;
// not a switch
if cur.length < 2 then
continue;
if cur[1] <> '-' then
continue;
// added dynamically when needed
if cur = '-unittest' then
continue;
if cur = '-main' then
continue;
// would break some internal stuff
if (cur.length > 2) and (cur[1..3] = '-of') then
continue;
RemoveTrailingChars(cur, [#0..#30]);
fRunnableSw += (cur + #13);
end;
if fRunnableSw.isNotEmpty and (fRunnableSw[fRunnableSw.length] = #13) then
fRunnableSw := fRunnableSw[1..fRunnableSw.length-1];
if fRunnableSw.isEmpty then
fRunnableSw := '-vcolumns'#13'-w'#13'-wi';
// //
form.Free; form.Free;
end; end;
@ -2387,8 +2564,8 @@ begin
fDoc.saveTempFile; fDoc.saveTempFile;
fname := stripFileExt(runnableExename); fname := stripFileExt(runnableExename);
if fRunnableSw.isEmpty then if fRunnablesOptions.staticSwitches.Count = 0 then
fRunnableSw := '-vcolumns'#13'-w'#13'-wi'; fRunnablesOptions.setDefaultSwitches;
{$IFDEF RELEASE} {$IFDEF RELEASE}
dmdProc.ShowWindow := swoHIDE; dmdProc.ShowWindow := swoHIDE;
{$ENDIF} {$ENDIF}
@ -2406,10 +2583,10 @@ begin
else else
dmdproc.Parameters.Add('-of' + fname + objExt); dmdproc.Parameters.Add('-of' + fname + objExt);
dmdproc.Parameters.Add('-J' + fDoc.fileName.extractFilePath); dmdproc.Parameters.Add('-J' + fDoc.fileName.extractFilePath);
dmdproc.Parameters.AddText(fRunnableSw); dmdproc.Parameters.AddStrings(fRunnablesOptions.staticSwitches);
if lst.isNotNil and (lst.Count <> 0) then if lst.isNotNil and (lst.Count <> 0) then
dmdproc.Parameters.AddStrings(lst); dmdproc.Parameters.AddStrings(lst);
if fAppliOpts.detectMain then if fRunnablesOptions.detectMain then
begin begin
hasMain := fDoc.implementMain; hasMain := fDoc.implementMain;
case hasMain of case hasMain of
@ -2422,7 +2599,7 @@ begin
end; end;
if unittest then if unittest then
begin begin
if not fAppliOpts.detectMain then if not fRunnablesOptions.detectMain then
dmdproc.Parameters.Add('-main'); dmdproc.Parameters.Add('-main');
dmdproc.Parameters.Add('-unittest'); dmdproc.Parameters.Add('-unittest');
if fCovModUt then if fCovModUt then
@ -2430,7 +2607,7 @@ begin
end end
else dmdproc.Parameters.Add('-version=runnable_module'); else dmdproc.Parameters.Add('-version=runnable_module');
if fAppliOpts.detectRunnableImports then if fRunnablesOptions.detectLibraries then
LibMan.getLibsForSource(fDoc.Lines, dmdproc.Parameters, dmdproc.Parameters) LibMan.getLibsForSource(fDoc.Lines, dmdproc.Parameters, dmdproc.Parameters)
else else
begin begin
@ -2674,7 +2851,7 @@ begin
fRunProc.Options := fRunProc.Options + [poNewConsole]; fRunProc.Options := fRunProc.Options + [poNewConsole];
{$ENDIF} {$ENDIF}
end; end;
case fAppliOpts.runnableCompiler of case fRunnablesOptions.compiler of
gdc: fRunProc.Parameters.add('--compiler=gdc'); gdc: fRunProc.Parameters.add('--compiler=gdc');
ldc: fRunProc.Parameters.add('--compiler=ldc2'); ldc: fRunProc.Parameters.add('--compiler=ldc2');
end; end;