Repo for the search and displace ingest module that takes odf, docx and pdf and transforms it into .md to be used with search and displace operations
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

174 lines
3.7 KiB

unit Runner;
interface
uses
Classes, SysUtils, UTF8Process, StdCtrls, ExtCtrls, Options;
type
TFinishReason = (
frFinished,
frStopped,
frFailure
);
TFinishedEvent = procedure(Sender: TObject; Reason: TFinishReason) of object;
TProgressEvent = procedure(Sender: TObject; Index: Integer) of object;
{ TRunner }
TRunner = class
private
FProcess: TProcessUTF8;
FTimer: TTimer;
FOutputMemo: TCustomMemo;
FOnFinished: TFinishedEvent;
FOnProgress: TProgressEvent;
FInputPos: Integer;
FFailures: Integer;
FOptions: TOptions;
FRunning: Boolean;
FStopped: Boolean;
procedure ReadProcessOutput;
procedure TimerTicked(Sender: TObject);
procedure RunNextItem(IsFirstRun: Boolean = False);
procedure Finish(Reason: TFinishReason);
public
constructor Create(AOutputMemo: TCustomMemo);
destructor Destroy; override;
procedure Run(AOptions: TOptions);
procedure Stop;
property IsRunning: Boolean read FRunning;
property Failures: Integer read FFailures;
property InputPos: Integer read FInputPos;
property OnFinished: TFinishedEvent read FOnFinished write FOnFinished;
property OnProgress: TProgressEvent read FOnProgress write FOnProgress;
end;
implementation
uses
Process, Dialogs;
{ TRunner }
constructor TRunner.Create(AOutputMemo: TCustomMemo);
begin
// Unfortunatelly, we cannot use TAsyncProcess since it does not work reliably on all platforms
FProcess := TProcessUTF8.Create(nil);
FProcess.Options := [poUsePipes, {$IFDEF MSWINDOWS}poNoConsole,{$ENDIF} poStderrToOutPut];
FTimer := TTimer.Create(nil);
FTimer.Enabled := False;
FTimer.Interval := 50;
FTimer.OnTimer := TimerTicked;
FOutputMemo := AOutputMemo;
end;
destructor TRunner.Destroy;
begin
FProcess.Free;
FTimer.Free;
inherited Destroy;
end;
procedure TRunner.ReadProcessOutput;
var
BufStr: string;
begin
while FProcess.Output.NumBytesAvailable > 0 do
begin
SetLength(BufStr, FProcess.Output.NumBytesAvailable);
FProcess.Output.Read(BufStr[1], Length(BufStr));
FOutputMemo.Append(BufStr);
end;
end;
procedure TRunner.TimerTicked(Sender: TObject);
begin
ReadProcessOutput;
if not FProcess.Running then
RunNextItem;
end;
procedure TRunner.RunNextItem(IsFirstRun: Boolean);
begin
if not IsFirstRun and (FProcess.ExitCode <> 0) then
Inc(FFailures);
Inc(FInputPos);
if FInputPos >= FOptions.Files.Count then
begin
if FFailures = 0 then
Finish(frFinished)
else
Finish(frFailure);
Exit;
end;
if FStopped then
begin
Finish(frStopped);
Exit;
end;
if Assigned(FOnProgress) then
FOnProgress(Self, FInputPos);
FOptions.ToCmdLineParameters(FProcess.Parameters, FInputPos);
try
FProcess.Execute;
except
on Ex: Exception do
begin
FOutputMemo.Append(Ex.ClassName + ': ' + Ex.Message);
Dialogs.MessageDlg('Failed to execute Deskew',
'Deskew command line executable failed to start. Check that it is in the correct location ' +
'and has the right permissions.' + sLineBreak + sLineBreak +
'Executable path used: ' + FProcess.Executable,
mtError, [mbOK], '');
Finish(frFailure);
Exit;
end;
end;
if IsFirstRun then
FTimer.Enabled := True;
end;
procedure TRunner.Finish(Reason: TFinishReason);
begin
FTimer.Enabled := False;
FRunning := False;
if Assigned(FOnFinished) then
FOnFinished(Self, Reason);
end;
procedure TRunner.Run(AOptions: TOptions);
begin
FInputPos := -1;
FFailures := 0;
FOptions := AOptions;
FStopped := False;
FRunning := True;
FProcess.Executable := FOptions.EffectiveExecutablePath;
RunNextItem(True);
end;
procedure TRunner.Stop;
begin
FStopped := True;
end;
end.