From 52be1650f4a30ec303ee38a36417782dfca22499 Mon Sep 17 00:00:00 2001 From: Basile Burg Date: Tue, 18 Nov 2014 11:13:27 +0100 Subject: [PATCH] added a class dedicated t sym string processing --- lazproj/coedit.lpi | 7 +- lazproj/coedit.lpr | 2 +- src/ce_symstring.pas | 253 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 260 insertions(+), 2 deletions(-) create mode 100644 src/ce_symstring.pas diff --git a/lazproj/coedit.lpi b/lazproj/coedit.lpi index be5b58bf..729ea109 100644 --- a/lazproj/coedit.lpi +++ b/lazproj/coedit.lpi @@ -93,7 +93,7 @@ - + @@ -283,6 +283,11 @@ + + + + + diff --git a/lazproj/coedit.lpr b/lazproj/coedit.lpr index f5010cc4..5c955a55 100644 --- a/lazproj/coedit.lpr +++ b/lazproj/coedit.lpr @@ -7,7 +7,7 @@ uses cthreads, {$ENDIF}{$ENDIF} Interfaces, Forms, lazcontrols, runtimetypeinfocontrols, - ce_dcd, ce_observer, ce_main, ce_writableComponent, ce_options; + ce_dcd, ce_observer, ce_main, ce_writableComponent, ce_options, ce_symstring; {$R *.res} diff --git a/src/ce_symstring.pas b/src/ce_symstring.pas new file mode 100644 index 00000000..f86bee4c --- /dev/null +++ b/src/ce_symstring.pas @@ -0,0 +1,253 @@ +unit ce_symstring; + +{$I ce_defines.inc} + +interface + +uses + ce_observer, ce_interfaces, ce_project, ce_synmemo, ce_common; + +type + + + (** + * Enumerates the symbol kinds, used to index an associative array. + *) + TCESymbol = (CAF, CAP, CFF, CFP, CI, CPF, CPP, CPR, CPN, CPFS); + + (** + * TCESymbolExpander is designed to expand Coedit symbolic strings, + * using the information collected from several observer interfaces. + *) + TCESymbolExpander = class(ICEMultiDocObserver, ICEProjectObserver) + private + fProj: TCEProject; + fDoc: TCESynMemo; + fSymbols: array[TCESymbol] of string; + procedure updateSymbols; + public + constructor create; + destructor destroy; + // + procedure projNew(aProject: TCEProject); + procedure projClosing(aProject: TCEProject); + procedure projFocused(aProject: TCEProject); + procedure projChanged(aProject: TCEProject); + // + procedure docNew(aDoc: TCESynMemo); + procedure docClosing(aDoc: TCESynMemo); + procedure docFocused(aDoc: TCESynMemo); + procedure docChanged(aDoc: TCESynMemo); + // expands the symbols contained in symString + function get(const symString: string): string; + end; + +var + symbolExpander: TCESymbolExpander; + +implementation + +uses + Forms, sysutils, classes; + +{$REGION Standard Comp/Obj------------------------------------------------------} +constructor TCESymbolExpander.create; +begin + EntitiesConnector.addObserver(self); +end; + +destructor TCESymbolExpander.destroy; +begin + EntitiesConnector.removeObserver(self); +end; +{$ENDREGION} + +{$REGION ICEProjectObserver ----------------------------------------------------} +procedure TCESymbolExpander.projNew(aProject: TCEProject); +begin + fProj := aProject; + updateSymbols; +end; + +procedure TCESymbolExpander.projClosing(aProject: TCEProject); +begin + if fProj <> aProject then exit; + fProj := nil; + updateSymbols; +end; + +procedure TCESymbolExpander.projFocused(aProject: TCEProject); +begin + fProj := aProject; +end; + +procedure TCESymbolExpander.projChanged(aProject: TCEProject); +begin + if fProj <> aProject then exit; + updateSymbols; +end; +{$ENDREGION} + +{$REGION ICEMultiDocObserver ---------------------------------------------------} +procedure TCESymbolExpander.docNew(aDoc: TCESynMemo); +begin + fDoc := aDoc; + updateSymbols; +end; + +procedure TCESymbolExpander.docClosing(aDoc: TCESynMemo); +begin + if aDoc <> fDoc then exit; + fDoc := nil; + updateSymbols; +end; + +procedure TCESymbolExpander.docFocused(aDoc: TCESynMemo); +begin + fDoc := aDoc; + updateSymbols; +end; + +procedure TCESymbolExpander.docChanged(aDoc: TCESynMemo); +begin + if aDoc <> fDoc then exit; + updateSymbols; +end; +{$ENDREGION} + +{$REGION Symbol things ---------------------------------------------------------} +procedure TCESymbolExpander.updateSymbols; +var + hasProj: boolean; + hasDoc: boolean; + extLen: Integer; + i: Integer; +const + na = '``'; +begin + hasProj := fProj <> nil; + hasDoc := fDoc <> nil; + // application + fSymbols[CAF] := Application.ExeName; + fSymbols[CAP] := ExtractFilePath(Application.ExeName); + // document + if hasDoc then + begin + if fileExists(fDoc.fileName) then begin + fSymbols[CFF] := fDoc.fileName; + fSymbols[CFP] := ExtractFilePath(fDoc.fileName); + end + else begin + fSymbols[CFF] := na; + fSymbols[CFP] := na; + end; + fSymbols[CI] := fDoc.Identifier; + end else begin + fSymbols[CFF] := na; + fSymbols[CFP] := na; + fSymbols[CI ] := na; + end; + // project + if hasProj then + begin + if fileExists(fProj.fileName) then begin + fSymbols[CPF] := fProj.fileName; + fSymbols[CPP] := ExtractFilePath(fProj.fileName); + fSymbols[CPR] := fProj.RootFolder; + fSymbols[CPN] := extractFileName(fProj.fileName); + extLen := length(ExtractFileExt(fSymbols[CPN])); + fSymbols[CPN] := fSymbols[CPN][1..length(fSymbols[CPN])-extLen]; + end else begin + fSymbols[CPF] := na; + fSymbols[CPP] := na; + fSymbols[CPR] := na; + fSymbols[CPN] := na; + end; + fSymbols[CPFS] := ''; + for i := 0 to fProj.Sources.Count-1 do + begin + fSymbols[CPFS] += fProj.getAbsoluteSourceName(i); + if fProj.Sources.Count > 1 then + if i <> fProj.Sources.Count-1 then + fSymbols[CPFS] += LineEnding; + end; + if fProj.Sources.Count = 0 then fSymbols[CPFS] := na; + end else begin + fSymbols[CPF] := na; + fSymbols[CPP] := na; + fSymbols[CPR] := na; + fSymbols[CPN] := na; + fSymbols[CPN] := na; + fSymbols[CPFS]:= na; + end; +end; + +function TCESymbolExpander.get(const symString: string): string; +var + elems: TStringList; + elem: string; + begs, ends: boolean; + i: integer; +begin + result := ''; + if symString = '' then exit; + // + elems := TStringList.Create; + try + i := 0; + elem := ''; + repeat + inc(i); + if not (symString[i] in ['<', '>']) then + elem += symString[i] + else + begin + if symString[i] = '<' then + begs := true; + ends := symString[i] = '>'; + elems.Add(elem); + elem := ''; + if begs and ends then + begin + begs := false; + ends := false; + // elem.obj is a flag to diferenciate symbols from elements + elems.Objects[elems.Count-1] := Self; + end; + end; + until + i = length(symString); + elems.Add(elem); + elem := ''; + for i:= 0 to elems.Count-1 do + begin + if elems.Objects[i] = nil then + result += elems.Strings[i] + else case elems.Strings[i] of + '<','>': continue; + 'CAF', 'CoeditApplicationFile':result += fSymbols[CAF]; + 'CAP', 'CoeditApplicationPath':result += fSymbols[CAP]; + // + 'CFF', 'CurrentFileFile': result += fSymbols[CFF]; + 'CFP', 'CurrentFilePath': result += fSymbols[CFP]; + 'CI', 'CurrentIdentifier': result += fSymbols[CI]; + // + 'CPF', 'CurrentProjectFile': result += fSymbols[CPF]; + 'CPFS', 'CurrentProjectFiles': result += fSymbols[CPFS]; + 'CPN', 'CurrentProjectName': result += fSymbols[CPN]; + 'CPP', 'CurrentProjectPath': result += fSymbols[CPP]; + 'CPR', 'CurrentProjectRoot': result += fSymbols[CPR]; + end; + end; + finally + elems.Free; + end; +end; +{$ENDREGION} + +initialization + symbolExpander := TCESymbolExpander.create; +finalization + symbolExpander.Free; +end. +