Split implementation into units
This commit is contained in:
parent
d46f442699
commit
c9b6b19479
|
@ -0,0 +1,242 @@
|
|||
{
|
||||
This file is part of logfilter.
|
||||
|
||||
Copyright (C) 2015 Andreas Schneider
|
||||
|
||||
logfilter is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
logfilter is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with logfilter. If not, see <http://www.gnu.org/licenses/>.
|
||||
}
|
||||
unit UApp;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$modeswitch advancedrecords}
|
||||
|
||||
{.$define debugmatches}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, CustApp, math, fgl, RegExpr, crt,
|
||||
UFilter;
|
||||
|
||||
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 = class(TCustomApplication)
|
||||
protected
|
||||
FLineFilters: TLineFilters;
|
||||
FCurrentLineFilter: TLineFilter;
|
||||
FCommandMatcher: TRegExpr;
|
||||
procedure DoRun; override;
|
||||
procedure ProcessCommand(ACommand, AParams: String);
|
||||
procedure WriteContent(AContent: String; AFilters: TFilterList;
|
||||
AGroupRanges: TGroupRanges);
|
||||
public
|
||||
constructor Create(TheOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
procedure WriteHelp; virtual;
|
||||
end;
|
||||
|
||||
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 }
|
||||
|
||||
procedure TLogFilterApplication.DoRun;
|
||||
var
|
||||
commandFile: TextFile;
|
||||
logFile: TextFile;
|
||||
groupRanges: TGroupRanges;
|
||||
lineFilter: TLineFilter;
|
||||
line: String;
|
||||
begin
|
||||
AssignFile(commandFile, ParamStr(1));
|
||||
Reset(commandFile);
|
||||
AssignFile(logFile, ParamStr(2));
|
||||
Reset(logFile);
|
||||
|
||||
// Parse command file first
|
||||
while not EOF(commandFile) do
|
||||
begin
|
||||
Readln(commandFile, line);
|
||||
if FCommandMatcher.Exec(line) then
|
||||
ProcessCommand(FCommandMatcher.Match[1], FCommandMatcher.Match[3]);
|
||||
end;
|
||||
|
||||
// Filter log
|
||||
while not EOF(logFile) do
|
||||
begin
|
||||
Readln(logFile, line);
|
||||
for lineFilter in FLineFilters do
|
||||
begin
|
||||
if lineFilter.Matches(line, groupRanges) then
|
||||
WriteContent(line, lineFilter.Filters, groupRanges);
|
||||
end;
|
||||
end;
|
||||
|
||||
CloseFile(commandFile); //TODO: narrow scope!
|
||||
CloseFile(logFile);
|
||||
|
||||
Terminate;
|
||||
end;
|
||||
|
||||
procedure TLogFilterApplication.ProcessCommand(ACommand, AParams: String);
|
||||
var
|
||||
highlightFilter: THighlightFilter;
|
||||
begin
|
||||
case LowerCase(ACommand) of
|
||||
'filter':
|
||||
begin
|
||||
FCurrentLineFilter := TLineFilter.Create(AParams);
|
||||
FLineFilters.Add(FCurrentLineFilter);
|
||||
end;
|
||||
'highlight':
|
||||
begin
|
||||
highlightFilter := THighlightFilter.Create(AParams);
|
||||
FCurrentLineFilter.Filters.Add(highlightFilter);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TLogFilterApplication.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;
|
||||
|
||||
constructor TLogFilterApplication.Create(TheOwner: TComponent);
|
||||
begin
|
||||
inherited Create(TheOwner);
|
||||
FLineFilters := TLineFilters.Create;
|
||||
FCommandMatcher := TRegExpr.Create('^(\w+)( (.*)|)$'); // 1 = command, 3 = OPTIONAL params
|
||||
end;
|
||||
|
||||
destructor TLogFilterApplication.Destroy;
|
||||
begin
|
||||
FLineFilters.Free;
|
||||
FCommandMatcher.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TLogFilterApplication.WriteHelp;
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
{
|
||||
This file is part of logfilter.
|
||||
|
||||
Copyright (C) 2015 Andreas Schneider
|
||||
|
||||
logfilter is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
logfilter is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with logfilter. If not, see <http://www.gnu.org/licenses/>.
|
||||
}
|
||||
unit UFilter;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
{.$define debugmatches}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes, SysUtils, fgl, RegExpr;
|
||||
|
||||
type
|
||||
{ THighlightFilter }
|
||||
|
||||
THighlightFilter = class
|
||||
Expression: TRegExpr;
|
||||
FGColor: Byte;
|
||||
BGColor: Byte;
|
||||
Group: Byte;
|
||||
constructor Create(AString: String);
|
||||
destructor Destroy; override;
|
||||
class var
|
||||
FilterExpression: TRegExpr;
|
||||
ParamExpression: TRegExpr;
|
||||
end;
|
||||
TFilterList = specialize TFPGObjectList<THighlightFilter>;
|
||||
|
||||
{ TGroupRange }
|
||||
|
||||
TGroupRange = record
|
||||
StartIdx: Integer;
|
||||
EndIdx: Integer;
|
||||
end;
|
||||
TGroupRanges = array of TGroupRange;
|
||||
|
||||
{ TLineFilter }
|
||||
|
||||
TLineFilter = class
|
||||
constructor Create(AExpression: String);
|
||||
destructor Destroy; override;
|
||||
protected
|
||||
FExpression: TRegExpr;
|
||||
FFilters: TFilterList;
|
||||
public
|
||||
function Matches(ALine: String; var GroupRanges: TGroupRanges): Boolean;
|
||||
property Filters: TFilterList read FFilters;
|
||||
end;
|
||||
TLineFilters = specialize TFPGObjectList<TLineFilter>;
|
||||
|
||||
implementation
|
||||
|
||||
{ THighlightFilter }
|
||||
|
||||
constructor THighlightFilter.Create(AString: String);
|
||||
begin
|
||||
FGColor := $FF;
|
||||
BGColor := $FF;
|
||||
Group := $FF;
|
||||
if FilterExpression.Exec(AString) then
|
||||
begin
|
||||
Expression := TRegExpr.Create(Copy(AString, 1, FilterExpression.MatchPos[0] - 1));
|
||||
if ParamExpression.Exec(FilterExpression.Match[0]) then
|
||||
repeat
|
||||
if ParamExpression.Match[1] = 'FG' then
|
||||
FGColor := StrToInt(ParamExpression.Match[2])
|
||||
else if ParamExpression.Match[1] = 'BG' then
|
||||
BGColor := StrToInt(ParamExpression.Match[2])
|
||||
else if ParamExpression.Match[1] = 'Grp' then
|
||||
Group := StrToInt(ParamExpression.Match[2]);
|
||||
until not ParamExpression.ExecNext;
|
||||
end else
|
||||
Expression := TRegExpr.Create(AString);
|
||||
end;
|
||||
|
||||
destructor THighlightFilter.Destroy;
|
||||
begin
|
||||
Expression.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
{ TLineFilter }
|
||||
|
||||
constructor TLineFilter.Create(AExpression: String);
|
||||
begin
|
||||
FExpression := TRegExpr.Create(AExpression);
|
||||
FFilters := TFilterList.Create;
|
||||
end;
|
||||
|
||||
destructor TLineFilter.Destroy;
|
||||
begin
|
||||
FExpression.Free;
|
||||
FFilters.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TLineFilter.Matches(ALine: String; var GroupRanges: TGroupRanges
|
||||
): Boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
Result := FExpression.Exec(ALine);
|
||||
if Result then
|
||||
begin
|
||||
{$ifdef debugmatches}writeln(' Match: ', FExpression.Match[0]);{$endif}
|
||||
SetLength(GroupRanges, FExpression.SubExprMatchCount + 1);
|
||||
for i := 0 to FExpression.SubExprMatchCount do
|
||||
begin
|
||||
{$ifdef debugmatches}writeln(' [', i, ']: ', FExpression.Match[i]);{$endif}
|
||||
GroupRanges[i].StartIdx := FExpression.MatchPos[i];
|
||||
GroupRanges[i].EndIdx := GroupRanges[i].StartIdx + FExpression.MatchLen[i];
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
initialization
|
||||
THighlightFilter.FilterExpression := TRegExpr.Create('( (FG|BG|Grp)(\d+))*$');
|
||||
THighlightFilter.ParamExpression := TRegExpr.Create('(FG|BG|Grp)(\d+)');
|
||||
finalization
|
||||
THighlightFilter.FilterExpression.Free;
|
||||
THighlightFilter.ParamExpression.Free;
|
||||
end.
|
||||
|
|
@ -30,11 +30,19 @@
|
|||
<FormatVersion Value="1"/>
|
||||
</local>
|
||||
</RunParams>
|
||||
<Units Count="1">
|
||||
<Units Count="3">
|
||||
<Unit0>
|
||||
<Filename Value="logfilter.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit0>
|
||||
<Unit1>
|
||||
<Filename Value="UFilter.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit1>
|
||||
<Unit2>
|
||||
<Filename Value="UApp.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit2>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
|
288
logfilter.pas
288
logfilter.pas
|
@ -19,293 +19,17 @@
|
|||
program logfilter;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$modeswitch advancedrecords}
|
||||
|
||||
{.$define debugmatches}
|
||||
|
||||
uses
|
||||
Classes, SysUtils, math, fgl, RegExpr, crt;
|
||||
|
||||
type
|
||||
|
||||
{ THighlightFilter }
|
||||
|
||||
THighlightFilter = class
|
||||
Expression: TRegExpr;
|
||||
FGColor: Byte;
|
||||
BGColor: Byte;
|
||||
Group: Byte;
|
||||
constructor Create(AString: String);
|
||||
destructor Destroy; override;
|
||||
class var
|
||||
FilterExpression: TRegExpr;
|
||||
ParamExpression: TRegExpr;
|
||||
end;
|
||||
TFilterList = specialize TFPGObjectList<THighlightFilter>;
|
||||
|
||||
{ THighlight }
|
||||
|
||||
THighlight = record
|
||||
FGColor: Byte;
|
||||
BGColor: Byte;
|
||||
Start: Integer;
|
||||
Length: Integer;
|
||||
class operator =(A, B: THighlight): Boolean;
|
||||
end;
|
||||
THighlights = specialize TFPGList<THighlight>;
|
||||
|
||||
TGroupRange = record
|
||||
StartIdx: Integer;
|
||||
EndIdx: Integer;
|
||||
end;
|
||||
TGroupRanges = array of TGroupRange;
|
||||
|
||||
{ TLineFilter }
|
||||
|
||||
TLineFilter = class
|
||||
constructor Create(AExpression: String);
|
||||
destructor Destroy; override;
|
||||
protected
|
||||
FExpression: TRegExpr;
|
||||
FFilters: TFilterList;
|
||||
public
|
||||
function Matches(ALine: String; var GroupRanges: TGroupRanges): Boolean;
|
||||
property Filters: TFilterList read FFilters;
|
||||
end;
|
||||
TLineFilters = specialize TFPGObjectList<TLineFilter>;
|
||||
|
||||
{ THighlight }
|
||||
|
||||
class operator THighlight. = (A, B: THighlight): Boolean;
|
||||
begin
|
||||
Result := (A.Start = B.Start) and (A.Length = B.Length);
|
||||
end;
|
||||
|
||||
|
||||
{ THighlightFilter }
|
||||
|
||||
constructor THighlightFilter.Create(AString: String);
|
||||
begin
|
||||
FGColor := $FF;
|
||||
BGColor := $FF;
|
||||
Group := $FF;
|
||||
if FilterExpression.Exec(AString) then
|
||||
begin
|
||||
Expression := TRegExpr.Create(Copy(AString, 1, FilterExpression.MatchPos[0] - 1));
|
||||
if ParamExpression.Exec(FilterExpression.Match[0]) then
|
||||
repeat
|
||||
if ParamExpression.Match[1] = 'FG' then
|
||||
FGColor := StrToInt(ParamExpression.Match[2])
|
||||
else if ParamExpression.Match[1] = 'BG' then
|
||||
BGColor := StrToInt(ParamExpression.Match[2])
|
||||
else if ParamExpression.Match[1] = 'Grp' then
|
||||
Group := StrToInt(ParamExpression.Match[2]);
|
||||
until not ParamExpression.ExecNext;
|
||||
end else
|
||||
Expression := TRegExpr.Create(AString);
|
||||
end;
|
||||
|
||||
destructor THighlightFilter.Destroy;
|
||||
begin
|
||||
Expression.Free;
|
||||
inherited Destroy;
|
||||
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;
|
||||
|
||||
{ TLineFilter }
|
||||
|
||||
constructor TLineFilter.Create(AExpression: String);
|
||||
begin
|
||||
FExpression := TRegExpr.Create(AExpression);
|
||||
FFilters := TFilterList.Create;
|
||||
end;
|
||||
|
||||
destructor TLineFilter.Destroy;
|
||||
begin
|
||||
FExpression.Free;
|
||||
FFilters.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
function TLineFilter.Matches(ALine: String; var GroupRanges: TGroupRanges
|
||||
): Boolean;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
Result := FExpression.Exec(ALine);
|
||||
if Result then
|
||||
begin
|
||||
{$ifdef debugmatches}writeln(' Match: ', FExpression.Match[0]);{$endif}
|
||||
SetLength(GroupRanges, FExpression.SubExprMatchCount + 1);
|
||||
for i := 0 to FExpression.SubExprMatchCount do
|
||||
begin
|
||||
{$ifdef debugmatches}writeln(' [', i, ']: ', FExpression.Match[i]);{$endif}
|
||||
GroupRanges[i].StartIdx := FExpression.MatchPos[i];
|
||||
GroupRanges[i].EndIdx := GroupRanges[i].StartIdx + FExpression.MatchLen[i];
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
//-----------------------------------------------------------
|
||||
Classes, SysUtils, UApp, UFilter;
|
||||
|
||||
var
|
||||
lineFilters: TLineFilters;
|
||||
currentLineFilter: TLineFilter;
|
||||
commandMatcher: TRegExpr;
|
||||
commandFile, logFile: TextFile;
|
||||
line: String;
|
||||
|
||||
procedure ProcessCommand(ACommand, AParams: String);
|
||||
var
|
||||
highlightFilter: THighlightFilter;
|
||||
begin
|
||||
case LowerCase(ACommand) of
|
||||
'filter':
|
||||
begin
|
||||
currentLineFilter := TLineFilter.Create(AParams);
|
||||
lineFilters.Add(currentLineFilter);
|
||||
end;
|
||||
'highlight':
|
||||
begin
|
||||
highlightFilter := THighlightFilter.Create(AParams);
|
||||
currentLineFilter.Filters.Add(highlightFilter);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure 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;
|
||||
|
||||
var
|
||||
groupRanges: TGroupRanges;
|
||||
Application: TLogFilterApplication;
|
||||
|
||||
begin
|
||||
AssignFile(commandFile, ParamStr(1));
|
||||
Reset(commandFile);
|
||||
AssignFile(logFile, ParamStr(2));
|
||||
Reset(logFile);
|
||||
|
||||
THighlightFilter.FilterExpression := TRegExpr.Create('( (FG|BG|Grp)(\d+))*$');
|
||||
THighlightFilter.ParamExpression := TRegExpr.Create('(FG|BG|Grp)(\d+)');
|
||||
lineFilters := TLineFilters.Create;
|
||||
commandMatcher := TRegExpr.Create('^(\w+)( (.*)|)$'); // 1 = command, 3 = OPTIONAL params
|
||||
|
||||
try
|
||||
// Parse command file first
|
||||
while not EOF(commandFile) do
|
||||
begin
|
||||
Readln(commandFile, line);
|
||||
if commandMatcher.Exec(line) then
|
||||
ProcessCommand(commandMatcher.Match[1], commandMatcher.Match[3]);
|
||||
end;
|
||||
|
||||
// Filter log
|
||||
while not EOF(logFile) do
|
||||
begin
|
||||
Readln(logFile, line);
|
||||
for currentLineFilter in lineFilters do
|
||||
begin
|
||||
if currentLineFilter.Matches(line, groupRanges) then
|
||||
WriteContent(line, currentLineFilter.Filters, groupRanges);
|
||||
end;
|
||||
end;
|
||||
finally
|
||||
commandMatcher.Free;
|
||||
lineFilters.Free;
|
||||
THighlightFilter.FilterExpression.Free;
|
||||
THighlightFilter.ParamExpression.Free;
|
||||
end;
|
||||
|
||||
CloseFile(commandFile); //TODO: narrow scope!
|
||||
CloseFile(logFile);
|
||||
Application := TLogFilterApplication.Create(nil);
|
||||
Application.Title := 'LogFilter';
|
||||
Application.Run;
|
||||
Application.Free;
|
||||
end.
|
||||
|
||||
|
|
Loading…
Reference in New Issue