* Externalized writer
* Fixed logfile parameter being ignored
This commit is contained in:
parent
dd0bade723
commit
3606a34054
122
UApp.pas
122
UApp.pas
|
@ -19,29 +19,17 @@
|
||||||
unit UApp;
|
unit UApp;
|
||||||
|
|
||||||
{$mode objfpc}{$H+}
|
{$mode objfpc}{$H+}
|
||||||
{$modeswitch advancedrecords}
|
|
||||||
|
|
||||||
{.$define debugmatches}
|
{.$define debugmatches}
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, CustApp, math, fgl, RegExpr, crt,
|
Classes, SysUtils, CustApp, math, RegExpr,
|
||||||
UFilter;
|
UFilter, UWriter;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
{ THighlight }
|
|
||||||
|
|
||||||
THighlight = record
|
|
||||||
FGColor: Byte;
|
|
||||||
BGColor: Byte;
|
|
||||||
Start: Integer;
|
|
||||||
Length: Integer;
|
|
||||||
class operator =(A, B: THighlight): Boolean;
|
|
||||||
end;
|
|
||||||
THighlights = specialize TFPGList<THighlight>;
|
|
||||||
|
|
||||||
{ TLogFilterApplication }
|
{ TLogFilterApplication }
|
||||||
|
|
||||||
TLogFilterApplication = class(TCustomApplication)
|
TLogFilterApplication = class(TCustomApplication)
|
||||||
|
@ -51,6 +39,7 @@ type
|
||||||
FCommandMatcher: TRegExpr;
|
FCommandMatcher: TRegExpr;
|
||||||
FCommandFileName: String;
|
FCommandFileName: String;
|
||||||
FLogFileName: String;
|
FLogFileName: String;
|
||||||
|
FWriter: TWriterList;
|
||||||
procedure DoRun; override;
|
procedure DoRun; override;
|
||||||
procedure ProcessCommand(ACommand, AParams: String);
|
procedure ProcessCommand(ACommand, AParams: String);
|
||||||
procedure WriteContent(AContent: String; AFilters: TFilterList;
|
procedure WriteContent(AContent: String; AFilters: TFilterList;
|
||||||
|
@ -63,22 +52,6 @@ type
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
{ THighlight }
|
|
||||||
|
|
||||||
class operator THighlight. = (A, B: THighlight): Boolean;
|
|
||||||
begin
|
|
||||||
Result := (A.Start = B.Start) and (A.Length = B.Length);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function CompareHighlights(const AHL1: THighlight; const AHL2: THighlight): Integer;
|
|
||||||
begin
|
|
||||||
if AHL1.Start = AHL2.Start then
|
|
||||||
begin
|
|
||||||
Result := AHL1.Length - AHL2.Length;
|
|
||||||
end else
|
|
||||||
Result := AHL1.Start - AHL2.Start;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TLogFilterApplication }
|
{ TLogFilterApplication }
|
||||||
|
|
||||||
procedure TLogFilterApplication.DoRun;
|
procedure TLogFilterApplication.DoRun;
|
||||||
|
@ -119,6 +92,9 @@ begin
|
||||||
|
|
||||||
CloseFile(commandFile);
|
CloseFile(commandFile);
|
||||||
|
|
||||||
|
if HasOption('f', 'logfile') then
|
||||||
|
FLogFileName := GetOptionValue('f', 'logfile');
|
||||||
|
|
||||||
if not FileExists(FLogFileName) then
|
if not FileExists(FLogFileName) then
|
||||||
begin
|
begin
|
||||||
Writeln('Logfile not found: ', FLogFileName);
|
Writeln('Logfile not found: ', FLogFileName);
|
||||||
|
@ -127,6 +103,8 @@ begin
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
FWriter.Add(TConsoleWriter.Create);
|
||||||
|
|
||||||
AssignFile(logFile, FLogFileName);
|
AssignFile(logFile, FLogFileName);
|
||||||
Reset(logFile);
|
Reset(logFile);
|
||||||
|
|
||||||
|
@ -146,6 +124,7 @@ begin
|
||||||
|
|
||||||
CloseFile(logFile);
|
CloseFile(logFile);
|
||||||
|
|
||||||
|
// One run is enough.
|
||||||
Terminate;
|
Terminate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -174,85 +153,10 @@ end;
|
||||||
procedure TLogFilterApplication.WriteContent(AContent: String;
|
procedure TLogFilterApplication.WriteContent(AContent: String;
|
||||||
AFilters: TFilterList; AGroupRanges: TGroupRanges);
|
AFilters: TFilterList; AGroupRanges: TGroupRanges);
|
||||||
var
|
var
|
||||||
i: Integer;
|
writer: TWriter;
|
||||||
matchPos, offset, lastPos: Integer;
|
|
||||||
highlights: THighlights;
|
|
||||||
highlight: THighlight;
|
|
||||||
group: Byte;
|
|
||||||
begin
|
begin
|
||||||
highlights := THighlights.Create;
|
for writer in FWriter do
|
||||||
|
writer.WriteContent(AContent, AFilters, AGroupRanges);
|
||||||
offset := 0;
|
|
||||||
lastPos := 1;
|
|
||||||
|
|
||||||
for i := 0 to AFilters.Count - 1 do
|
|
||||||
begin
|
|
||||||
if AFilters[i].Expression.Exec(AContent) then
|
|
||||||
begin
|
|
||||||
repeat
|
|
||||||
// We need these values anyway.
|
|
||||||
matchPos := AFilters[i].Expression.MatchPos[0];
|
|
||||||
offset := AFilters[i].Expression.MatchLen[0];
|
|
||||||
|
|
||||||
group := AFilters[i].Group;
|
|
||||||
if group < Length(AGroupRanges) then
|
|
||||||
begin
|
|
||||||
if (matchPos + offset < AGroupRanges[group].StartIdx) or
|
|
||||||
(matchPos > AGroupRanges[group].EndIdx) then
|
|
||||||
continue; //Pointless; nothing we can do here
|
|
||||||
|
|
||||||
highlight.Start := Max(AGroupRanges[group].StartIdx, matchPos);
|
|
||||||
highlight.Length := Min(AGroupRanges[group].EndIdx - highlight.Start,
|
|
||||||
highlight.Start + offset - matchPos);
|
|
||||||
|
|
||||||
{$ifdef debugmatches}
|
|
||||||
writeln(' Highlight: ', highlight.Start, ', ', highlight.Length);
|
|
||||||
writeln(' MatchPos: ', matchPos, ', StartIdx: ', AGroupRanges[group].StartIdx);
|
|
||||||
writeln(' Offset: ', offset, ', EndIdx: ', AGroupRanges[group].EndIdx);
|
|
||||||
{$endif}
|
|
||||||
end else
|
|
||||||
begin
|
|
||||||
highlight.Start := matchPos;
|
|
||||||
highlight.Length := offset;
|
|
||||||
end;
|
|
||||||
|
|
||||||
highlight.FGColor := AFilters[i].FGColor;
|
|
||||||
highlight.BGColor := AFilters[i].BGColor;
|
|
||||||
highlights.Add(highlight);
|
|
||||||
until not AFilters[i].Expression.ExecNext;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
highlights.Sort(@CompareHighlights);
|
|
||||||
|
|
||||||
// Sanitize highlights
|
|
||||||
for i := 0 to highlights.Count - 2 do
|
|
||||||
begin
|
|
||||||
if (highlights[i].Start + highlights[i].Length) > highlights[i+1].Start then
|
|
||||||
begin
|
|
||||||
highlight := highlights[i];
|
|
||||||
highlight.Length := highlights[i+1].Start - highlights[i].Start;
|
|
||||||
highlights[i] := highlight;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
for highlight in highlights do
|
|
||||||
begin
|
|
||||||
matchPos := highlight.Start;
|
|
||||||
offset := highlight.Length;
|
|
||||||
write(Copy(AContent, lastPos, matchPos - lastPos));
|
|
||||||
if highlight.FGColor < $FF then
|
|
||||||
TextColor(highlight.FGColor);
|
|
||||||
if highlight.BGColor < $FF then
|
|
||||||
TextBackground(highlight.BGColor);
|
|
||||||
write(Copy(AContent, matchPos, offset));
|
|
||||||
NormVideo;
|
|
||||||
lastPos := matchPos + offset;
|
|
||||||
end;
|
|
||||||
|
|
||||||
writeln(Copy(AContent, lastPos, Length(AContent)));
|
|
||||||
|
|
||||||
highlights.Free;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
constructor TLogFilterApplication.Create(TheOwner: TComponent);
|
constructor TLogFilterApplication.Create(TheOwner: TComponent);
|
||||||
|
@ -260,12 +164,14 @@ begin
|
||||||
inherited Create(TheOwner);
|
inherited Create(TheOwner);
|
||||||
FLineFilters := TLineFilters.Create;
|
FLineFilters := TLineFilters.Create;
|
||||||
FCommandMatcher := TRegExpr.Create('^(\w+)( (.*)|)$'); // 1 = command, 3 = OPTIONAL params
|
FCommandMatcher := TRegExpr.Create('^(\w+)( (.*)|)$'); // 1 = command, 3 = OPTIONAL params
|
||||||
|
FWriter := TWriterList.Create;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
destructor TLogFilterApplication.Destroy;
|
destructor TLogFilterApplication.Destroy;
|
||||||
begin
|
begin
|
||||||
FLineFilters.Free;
|
FLineFilters.Free;
|
||||||
FCommandMatcher.Free;
|
FCommandMatcher.Free;
|
||||||
|
FWriter.Free;
|
||||||
inherited Destroy;
|
inherited Destroy;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
30
UFilter.pas
30
UFilter.pas
|
@ -19,6 +19,7 @@
|
||||||
unit UFilter;
|
unit UFilter;
|
||||||
|
|
||||||
{$mode objfpc}{$H+}
|
{$mode objfpc}{$H+}
|
||||||
|
{$modeswitch advancedrecords}
|
||||||
|
|
||||||
{.$define debugmatches}
|
{.$define debugmatches}
|
||||||
|
|
||||||
|
@ -65,6 +66,19 @@ type
|
||||||
end;
|
end;
|
||||||
TLineFilters = specialize TFPGObjectList<TLineFilter>;
|
TLineFilters = specialize TFPGObjectList<TLineFilter>;
|
||||||
|
|
||||||
|
{ THighlight }
|
||||||
|
|
||||||
|
THighlight = record
|
||||||
|
FGColor: Byte;
|
||||||
|
BGColor: Byte;
|
||||||
|
Start: Integer;
|
||||||
|
Length: Integer;
|
||||||
|
class operator =(A, B: THighlight): Boolean;
|
||||||
|
end;
|
||||||
|
THighlights = specialize TFPGList<THighlight>;
|
||||||
|
|
||||||
|
function CompareHighlights(const AHL1: THighlight; const AHL2: THighlight): Integer;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
{ THighlightFilter }
|
{ THighlightFilter }
|
||||||
|
@ -130,6 +144,22 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ THighlight }
|
||||||
|
|
||||||
|
class operator THighlight. = (A, B: THighlight): Boolean;
|
||||||
|
begin
|
||||||
|
Result := (A.Start = B.Start) and (A.Length = B.Length);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function CompareHighlights(const AHL1: THighlight; const AHL2: THighlight): Integer;
|
||||||
|
begin
|
||||||
|
if AHL1.Start = AHL2.Start then
|
||||||
|
begin
|
||||||
|
Result := AHL1.Length - AHL2.Length;
|
||||||
|
end else
|
||||||
|
Result := AHL1.Start - AHL2.Start;
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
THighlightFilter.FilterExpression := TRegExpr.Create('( (FG|BG|Grp)(\d+))*$');
|
THighlightFilter.FilterExpression := TRegExpr.Create('( (FG|BG|Grp)(\d+))*$');
|
||||||
THighlightFilter.ParamExpression := TRegExpr.Create('(FG|BG|Grp)(\d+)');
|
THighlightFilter.ParamExpression := TRegExpr.Create('(FG|BG|Grp)(\d+)');
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
unit UWriter;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, UFilter, Math, crt, fgl;
|
||||||
|
|
||||||
|
type
|
||||||
|
TWriter = class
|
||||||
|
public
|
||||||
|
procedure WriteContent(AContent: String; AFilters: TFilterList;
|
||||||
|
AGroupRanges: TGroupRanges); virtual; abstract;
|
||||||
|
end;
|
||||||
|
TWriterList = specialize TFPGObjectList<TWriter>;
|
||||||
|
|
||||||
|
{ TConsoleWriter }
|
||||||
|
|
||||||
|
TConsoleWriter = class(TWriter)
|
||||||
|
public
|
||||||
|
procedure WriteContent(AContent: String; AFilters: TFilterList;
|
||||||
|
AGroupRanges: TGroupRanges); override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
{ TConsoleWriter }
|
||||||
|
|
||||||
|
procedure TConsoleWriter.WriteContent(AContent: String; AFilters: TFilterList;
|
||||||
|
AGroupRanges: TGroupRanges);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
matchPos, offset, lastPos: Integer;
|
||||||
|
highlights: THighlights;
|
||||||
|
highlight: THighlight;
|
||||||
|
group: Byte;
|
||||||
|
begin
|
||||||
|
highlights := THighlights.Create;
|
||||||
|
|
||||||
|
offset := 0;
|
||||||
|
lastPos := 1;
|
||||||
|
|
||||||
|
for i := 0 to AFilters.Count - 1 do
|
||||||
|
begin
|
||||||
|
if AFilters[i].Expression.Exec(AContent) then
|
||||||
|
begin
|
||||||
|
repeat
|
||||||
|
// We need these values anyway.
|
||||||
|
matchPos := AFilters[i].Expression.MatchPos[0];
|
||||||
|
offset := AFilters[i].Expression.MatchLen[0];
|
||||||
|
|
||||||
|
group := AFilters[i].Group;
|
||||||
|
if group < Length(AGroupRanges) then
|
||||||
|
begin
|
||||||
|
if (matchPos + offset < AGroupRanges[group].StartIdx) or
|
||||||
|
(matchPos > AGroupRanges[group].EndIdx) then
|
||||||
|
continue; //Pointless; nothing we can do here
|
||||||
|
|
||||||
|
highlight.Start := Max(AGroupRanges[group].StartIdx, matchPos);
|
||||||
|
highlight.Length := Min(AGroupRanges[group].EndIdx - highlight.Start,
|
||||||
|
highlight.Start + offset - matchPos);
|
||||||
|
|
||||||
|
{$ifdef debugmatches}
|
||||||
|
writeln(' Highlight: ', highlight.Start, ', ', highlight.Length);
|
||||||
|
writeln(' MatchPos: ', matchPos, ', StartIdx: ', AGroupRanges[group].StartIdx);
|
||||||
|
writeln(' Offset: ', offset, ', EndIdx: ', AGroupRanges[group].EndIdx);
|
||||||
|
{$endif}
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
highlight.Start := matchPos;
|
||||||
|
highlight.Length := offset;
|
||||||
|
end;
|
||||||
|
|
||||||
|
highlight.FGColor := AFilters[i].FGColor;
|
||||||
|
highlight.BGColor := AFilters[i].BGColor;
|
||||||
|
highlights.Add(highlight);
|
||||||
|
until not AFilters[i].Expression.ExecNext;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
highlights.Sort(@CompareHighlights);
|
||||||
|
|
||||||
|
// Sanitize highlights
|
||||||
|
for i := 0 to highlights.Count - 2 do
|
||||||
|
begin
|
||||||
|
if (highlights[i].Start + highlights[i].Length) > highlights[i+1].Start then
|
||||||
|
begin
|
||||||
|
highlight := highlights[i];
|
||||||
|
highlight.Length := highlights[i+1].Start - highlights[i].Start;
|
||||||
|
highlights[i] := highlight;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
for highlight in highlights do
|
||||||
|
begin
|
||||||
|
matchPos := highlight.Start;
|
||||||
|
offset := highlight.Length;
|
||||||
|
write(Copy(AContent, lastPos, matchPos - lastPos));
|
||||||
|
if highlight.FGColor < $FF then
|
||||||
|
TextColor(highlight.FGColor);
|
||||||
|
if highlight.BGColor < $FF then
|
||||||
|
TextBackground(highlight.BGColor);
|
||||||
|
write(Copy(AContent, matchPos, offset));
|
||||||
|
NormVideo;
|
||||||
|
lastPos := matchPos + offset;
|
||||||
|
end;
|
||||||
|
|
||||||
|
writeln(Copy(AContent, lastPos, Length(AContent)));
|
||||||
|
|
||||||
|
highlights.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
<FormatVersion Value="1"/>
|
<FormatVersion Value="1"/>
|
||||||
</local>
|
</local>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<Units Count="3">
|
<Units Count="4">
|
||||||
<Unit0>
|
<Unit0>
|
||||||
<Filename Value="logfilter.pas"/>
|
<Filename Value="logfilter.pas"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
|
@ -67,6 +67,10 @@
|
||||||
<Filename Value="UApp.pas"/>
|
<Filename Value="UApp.pas"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
</Unit2>
|
</Unit2>
|
||||||
|
<Unit3>
|
||||||
|
<Filename Value="UWriter.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
</Unit3>
|
||||||
</Units>
|
</Units>
|
||||||
</ProjectOptions>
|
</ProjectOptions>
|
||||||
<CompilerOptions>
|
<CompilerOptions>
|
||||||
|
|
|
@ -21,7 +21,7 @@ program logfilter;
|
||||||
{$mode objfpc}{$H+}
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, UApp, UFilter;
|
Classes, SysUtils, UApp, UFilter, UWriter;
|
||||||
|
|
||||||
var
|
var
|
||||||
Application: TLogFilterApplication;
|
Application: TLogFilterApplication;
|
||||||
|
|
Loading…
Reference in New Issue