* Prepared HTML writer

* Separated highlighting from writing
This commit is contained in:
Andreas Schneider 2015-09-24 21:19:00 +02:00
parent 562c64f69a
commit bd0b6bc3f4
2 changed files with 117 additions and 69 deletions

View File

@ -25,7 +25,7 @@ unit UApp;
interface
uses
Classes, SysUtils, CustApp, RegExpr,
Classes, SysUtils, CustApp, RegExpr, Math,
UFilter, UWriter;
type
@ -105,6 +105,9 @@ begin
FWriter.Add(TConsoleWriter.Create);
if HasOption('html') then
FWriter.Add(THTMLWriter.Create(GetOptionValue('html')));
AssignFile(logFile, FLogFileName);
Reset(logFile);
@ -153,10 +156,73 @@ end;
procedure TLogFilterApplication.WriteContent(AContent: String;
AFilters: TFilterList; AGroupRanges: TGroupRanges);
var
i: Integer;
matchPos, offset: Integer;
highlights: THighlights;
highlight: THighlight;
group: Byte;
writer: TWriter;
begin
highlights := THighlights.Create;
offset := 0;
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 writer in FWriter do
writer.WriteContent(AContent, AFilters, AGroupRanges);
writer.WriteContent(AContent, highlights);
highlights.Free;
end;
constructor TLogFilterApplication.Create(TheOwner: TComponent);

View File

@ -5,13 +5,13 @@ unit UWriter;
interface
uses
Classes, SysUtils, UFilter, Math, crt, fgl;
Classes, SysUtils, UFilter, crt, fgl;
type
TWriter = class
public
procedure WriteContent(AContent: String; AFilters: TFilterList;
AGroupRanges: TGroupRanges); virtual; abstract;
procedure WriteContent(AContent: String;
AHighlights: THighlights); virtual; abstract;
end;
TWriterList = specialize TFPGObjectList<TWriter>;
@ -19,80 +19,64 @@ type
TConsoleWriter = class(TWriter)
public
procedure WriteContent(AContent: String; AFilters: TFilterList;
AGroupRanges: TGroupRanges); override;
procedure WriteContent(AContent: String;
AHighlights: THighlights); override;
end;
{ THTMLWriter }
THTMLWriter = class(TWriter)
protected
FFileStream: TFileStream;
procedure WriteLine(AContent: String);
public
constructor Create(AFileName: String);
destructor Destroy; override;
procedure WriteContent(AContent: String;
AHighlights: THighlights); override;
end;
implementation
{ THTMLWriter }
procedure THTMLWriter.WriteLine(AContent: String);
begin
AContent := AContent + LineEnding;
FFileStream.Write(AContent[1], Length(AContent));
end;
constructor THTMLWriter.Create(AFileName: String);
begin
FFileStream := TFileStream.Create(AFileName, fmCreate);
WriteLine('<html>');
WriteLine('<body>');
end;
destructor THTMLWriter.Destroy;
begin
WriteLine('</body>');
WriteLine('</html>');
FFileStream.Free;
inherited Destroy;
end;
procedure THTMLWriter.WriteContent(AContent: String; AHighlights: THighlights);
begin
end;
{ TConsoleWriter }
procedure TConsoleWriter.WriteContent(AContent: String; AFilters: TFilterList;
AGroupRanges: TGroupRanges);
procedure TConsoleWriter.WriteContent(AContent: String; AHighlights: THighlights
);
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
for highlight in AHighlights do
begin
matchPos := highlight.Start;
offset := highlight.Length;
@ -107,8 +91,6 @@ begin
end;
writeln(Copy(AContent, lastPos, Length(AContent)));
highlights.Free;
end;
end.