{
    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 .
}
unit UApp;
{$mode objfpc}{$H+}
{.$define debugmatches}
interface
uses
  Classes, SysUtils, CustApp, math, RegExpr,
  UFilter, UWriter;
type
  { TLogFilterApplication }
  TLogFilterApplication = class(TCustomApplication)
  protected
    FLineFilters: TLineFilters;
    FCurrentLineFilter: TLineFilter;
    FCommandMatcher: TRegExpr;
    FCommandFileName: String;
    FLogFileName: String;
    FWriter: TWriterList;
    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
{ TLogFilterApplication }
procedure TLogFilterApplication.DoRun;
var
  commandFile: TextFile;
  logFile: TextFile;
  groupRanges: TGroupRanges;
  lineFilter: TLineFilter;
  line: String;
begin
  if HasOption('h', 'help') or not HasOption('c', 'commandfile') then
  begin
    WriteHelp;
    Terminate;
    Exit;
  end;
  FCommandFileName := GetOptionValue('c', 'commandfile');
  if not FileExists(FCommandFileName) then
  begin
    Writeln('Commandfile not found: ', FCommandFileName);
    ExitCode := 1;
    Terminate;
    Exit;
  end;
  AssignFile(commandFile, FCommandFileName);
  Reset(commandFile);
  // 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;
  CloseFile(commandFile);
  if HasOption('f', 'logfile') then
    FLogFileName := GetOptionValue('f', 'logfile');
  if not FileExists(FLogFileName) then
  begin
    Writeln('Logfile not found: ', FLogFileName);
    ExitCode := 1;
    Terminate;
    Exit;
  end;
  FWriter.Add(TConsoleWriter.Create);
  AssignFile(logFile, FLogFileName);
  Reset(logFile);
  // Filter log
  while not EOF(logFile) do
  begin
    Readln(logFile, line);
    for lineFilter in FLineFilters do
    begin
      if lineFilter.Matches(line, groupRanges) then
      begin
        WriteContent(line, lineFilter.Filters, groupRanges);
        Break;
      end;
    end;
  end;
  CloseFile(logFile);
  // One run is enough.
  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;
    'file':
      begin
        FLogFileName := AParams;
      end;
  end;
end;
procedure TLogFilterApplication.WriteContent(AContent: String;
  AFilters: TFilterList; AGroupRanges: TGroupRanges);
var
  writer: TWriter;
begin
  for writer in FWriter do
    writer.WriteContent(AContent, AFilters, AGroupRanges);
end;
constructor TLogFilterApplication.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  FLineFilters := TLineFilters.Create;
  FCommandMatcher := TRegExpr.Create('^(\w+)( (.*)|)$'); // 1 = command, 3 = OPTIONAL params
  FWriter := TWriterList.Create;
end;
destructor TLogFilterApplication.Destroy;
begin
  FLineFilters.Free;
  FCommandMatcher.Free;
  FWriter.Free;
  inherited Destroy;
end;
procedure TLogFilterApplication.WriteHelp;
begin
  Writeln('Usage: ', ExtractFileName(ExeName), ' [options]');
  Writeln;
  Writeln('Options:');
  Writeln('  -c --commandfile=');
  Writeln('    specifies the filename with filter commands');
  Writeln('  -f --logfile=');
  Writeln('    specifies the logfile to be parsed');
  Writeln('  -h --help');
  Writeln('    show this help screen');
end;
end.