added input to stdin support to runnable modules

This commit is contained in:
Basile Burg 2014-11-03 08:13:23 +01:00
parent 493ef821ae
commit 43f2ee3e11
5 changed files with 257 additions and 20 deletions

View File

@ -52,6 +52,11 @@
<Debugging> <Debugging>
<UseHeaptrc Value="True"/> <UseHeaptrc Value="True"/>
</Debugging> </Debugging>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking> </Linking>
<Other> <Other>
<CompilerMessages> <CompilerMessages>
@ -135,7 +140,7 @@
<PackageName Value="LCL"/> <PackageName Value="LCL"/>
</Item6> </Item6>
</RequiredPackages> </RequiredPackages>
<Units Count="27"> <Units Count="28">
<Unit0> <Unit0>
<Filename Value="coedit.lpr"/> <Filename Value="coedit.lpr"/>
<IsPartOfProject Value="True"/> <IsPartOfProject Value="True"/>
@ -304,6 +309,14 @@
<ResourceBaseClass Value="Form"/> <ResourceBaseClass Value="Form"/>
<UnitName Value="ce_toolseditor"/> <UnitName Value="ce_toolseditor"/>
</Unit26> </Unit26>
<Unit27>
<Filename Value="..\src\ce_procinput.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="CEProcInputWidget"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Form"/>
<UnitName Value="ce_procinput"/>
</Unit27>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>

View File

@ -1829,6 +1829,42 @@ object CEMainForm: TCEMainForm
Caption = 'Windows' Caption = 'Windows'
object mnuLayout: TMenuItem object mnuLayout: TMenuItem
Caption = 'Layout' Caption = 'Layout'
Bitmap.Data = {
36040000424D3604000000000000360000002800000010000000100000000100
2000000000000004000064000000640000000000000000000000FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00BE7D
558FBD7C54B5BC7B53EEBA7953FFB67751FFB47651FFB17450FFAD724FFFAA71
4FFFA86F4EFFA76E4DFFA66E4DFEA46E4DF1A66E4DC4FFFFFF00FFFFFF00C080
55DEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA66E4DEDFFFFFF00FFFFFF00C282
58FEFFFFFFFFAF672CFFAD642BFFAD642BFFFFFFFFFF56AB5DFF51A657FF4CA1
52FF479C4CFF449849FF409445FFFFFFFFFFA76F4EFEFFFFFF00FFFFFF00C486
5AFFFFFFFFFFAF672CFFCD9F74FFAD642BFFFFFFFFFF4B9F50FF70C97BFF70C9
7BFF6FC87AFF6EC778FF3E9343FFFFFFFFFFA8714FFFFFFFFF00FFFFFF00C586
5BFFFFFFFFFFAF672CFFCDA075FFAD642BFFFFFFFFFF4EA354FF73CA7DFF72CA
7DFF71C97CFF6FC87AFF419546FFFFFFFFFFAC7250FFFFFFFF00FFFFFF00C788
5AFFFFFFFFFFB46E33FFD0A57EFFB26C2EFFFFFFFFFF50A556FF74CB7EFF73CB
7DFF72CA7CFF70C97BFF449949FFFFFFFFFFB27651FFFFFFFF00FFFFFF00C88A
5BFFFFFFFFFFB77640FFD1A683FFB67338FFFFFFFFFF52A859FF73CB7DFF73CB
7DFF72CA7CFF70C97BFF479C4DFFFFFFFFFFB67853FFFFFFFF00FFFFFF00CA8C
5CFFFFFFFFFFBC7F54FFBA7D4CFFBA7C4AFFFFFFFFFF469B4CFF53A859FF51A6
57FF4FA455FF4DA253FF4A9F50FFFFFFFFFFB97C54FFFFFFFF00FFFFFF00CB8E
5DFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC7E55FFFFFFFF00FFFFFF00CC90
5EFAFFFFFFFFEDC49BFFEDC49BFFEDC49BFFEDC49BFFEDC49BFFEDC49BFFEDC4
9BFFEDC49BFFEDC49BFFEDC49BFFFFFFFFFFBE8157FFFFFFFF00FFFFFF00CD91
5FF0FFFFFFFFEDC49CFFF4DAC1FFF4DAC1FFF4DBC2FFF4DBC2FFF4DBC2FFF4DB
C2FFF4DBC2FFF4DBC2FFEDC49BFFFFFFFFFFC18458FEFFFFFF00FFFFFF00CE93
5FD8FFFFFFFFEDC49CFFEDC49CFFEDC49CFFEDC49BFFEDC49BFFEDC49BFFEDC4
9BFFEDC49BFFEDC49BFFEDC49BFFFFFFFFFFC68C61F8FFFFFF00FFFFFF00CE93
5F9BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6AA89FFFFFFFF00FFFFFF00CE93
5F71CE935F90CE935FCCCE935FFFCD935FFECD925FFFCC905FFFCD9261FFCD93
63FFCB9161FFCB8E5FEFCA9264CBD8AE8BFFD7AC8BFFFFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF
FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00
}
ImageIndex = 31 ImageIndex = 31
end end
end end
@ -3149,4 +3185,10 @@ object CEMainForm: TCEMainForm
OnShowHint = ApplicationProperties1ShowHint OnShowHint = ApplicationProperties1ShowHint
left = 96 left = 96
end end
object OutputTimer: TIdleTimer
Interval = 100
OnTimer = OutputTimerTimer
left = 128
top = 1
end
end end

View File

@ -5,13 +5,13 @@ unit ce_main;
interface interface
uses uses
Classes, SysUtils, FileUtil, SynEditKeyCmds, SynHighlighterLFM, Forms, Classes, SysUtils, FileUtil, SynEditKeyCmds, SynHighlighterLFM, Forms, asyncprocess,
AnchorDocking, AnchorDockStorage, AnchorDockOptionsDlg, Controls, Graphics, AnchorDocking, AnchorDockStorage, AnchorDockOptionsDlg, Controls, Graphics,
Dialogs, Menus, ActnList, ExtCtrls, process, XMLPropStorage, ComCtrls, dynlibs, Dialogs, Menus, ActnList, ExtCtrls, process, XMLPropStorage, ComCtrls, dynlibs,
ce_common, ce_dmdwrap, ce_project, ce_dcd, ce_plugin, ce_synmemo, ce_widget, ce_common, ce_dmdwrap, ce_project, ce_dcd, ce_plugin, ce_synmemo, ce_widget,
ce_messages, ce_interfaces, ce_editor, ce_projinspect, ce_projconf, ce_search, ce_messages, ce_interfaces, ce_editor, ce_projinspect, ce_projconf, ce_search,
ce_staticexplorer, ce_miniexplorer, ce_libman, ce_libmaneditor, ce_customtools, ce_staticexplorer, ce_miniexplorer, ce_libman, ce_libmaneditor, ce_customtools,
ce_observer, ce_writableComponent, ce_toolseditor; ce_observer, ce_writableComponent, ce_toolseditor, ce_procinput;
type type
@ -60,6 +60,7 @@ type
actEdUnIndent: TAction; actEdUnIndent: TAction;
Actions: TActionList; Actions: TActionList;
ApplicationProperties1: TApplicationProperties; ApplicationProperties1: TApplicationProperties;
OutputTimer: TIdleTimer;
imgList: TImageList; imgList: TImageList;
mainMenu: TMainMenu; mainMenu: TMainMenu;
MenuItem1: TMenuItem; MenuItem1: TMenuItem;
@ -170,6 +171,7 @@ type
var CanShow: Boolean; var HintInfo: THintInfo); var CanShow: Boolean; var HintInfo: THintInfo);
procedure FormCloseQuery(Sender: TObject; var CanClose: boolean); procedure FormCloseQuery(Sender: TObject; var CanClose: boolean);
procedure FormDropFiles(Sender: TObject; const FileNames: array of String); procedure FormDropFiles(Sender: TObject; const FileNames: array of String);
procedure OutputTimerTimer(Sender: TObject);
private private
fDoc: TCESynMemo; fDoc: TCESynMemo;
@ -189,8 +191,11 @@ type
fProjMru: TMruFileList; fProjMru: TMruFileList;
fFileMru: TMruFileList; fFileMru: TMruFileList;
fLibMan: TLibraryManager; fLibMan: TLibraryManager;
fPrInpWidg: TCEProcInputWidget;
fTools: TCETools; fTools: TCETools;
fRunProc: TProcess;// TAsyncProcess;
// ICEMultiDocObserver // ICEMultiDocObserver
procedure docNew(const aDoc: TCESynMemo); procedure docNew(const aDoc: TCESynMemo);
procedure docClosing(const aDoc: TCESynMemo); procedure docClosing(const aDoc: TCESynMemo);
@ -224,12 +229,14 @@ type
procedure LoadDocking; procedure LoadDocking;
procedure SaveDocking; procedure SaveDocking;
procedure KillPlugs; procedure KillPlugs;
procedure FreeRunnableProc;
// widget interfaces subroutines // widget interfaces subroutines
procedure checkWidgetActions(const aWidget: TCEWidget); procedure checkWidgetActions(const aWidget: TCEWidget);
procedure widgetShowFromAction(sender: TObject); procedure widgetShowFromAction(sender: TObject);
// run & exec sub routines // run & exec sub routines
procedure asyncprocOutput(sender: TObject);
procedure ProcessOutputToMsg(const aProcess: TProcess;aCtxt: TMessageContext = mcUnknown); procedure ProcessOutputToMsg(const aProcess: TProcess;aCtxt: TMessageContext = mcUnknown);
procedure compileAndRunFile(const edIndex: NativeInt; const runArgs: string = ''); procedure compileAndRunFile(const edIndex: NativeInt; const runArgs: string = '');
procedure compileProject(const aProject: TCEProject); procedure compileProject(const aProject: TCEProject);
@ -457,6 +464,7 @@ begin
fExplWidg := TCEMiniExplorerWidget.create(self); fExplWidg := TCEMiniExplorerWidget.create(self);
fLibMWidg := TCELibManEditorWidget.create(self); fLibMWidg := TCELibManEditorWidget.create(self);
fTlsEdWidg:= TCEToolsEditorWidget.create(self); fTlsEdWidg:= TCEToolsEditorWidget.create(self);
fPrInpWidg:= TCEProcInputWidget.create(self);
fWidgList.addWidget(@fMesgWidg); fWidgList.addWidget(@fMesgWidg);
fWidgList.addWidget(@fEditWidg); fWidgList.addWidget(@fEditWidg);
@ -467,6 +475,7 @@ begin
fWidgList.addWidget(@fExplWidg); fWidgList.addWidget(@fExplWidg);
fWidgList.addWidget(@fLibMWidg); fWidgList.addWidget(@fLibMWidg);
fWidgList.addWidget(@fTlsEdWidg); fWidgList.addWidget(@fTlsEdWidg);
fWidgList.addWidget(@fPrInpWidg);
for widg in fWidgList do for widg in fWidgList do
begin begin
@ -661,6 +670,21 @@ begin
fPlugList.Free; fPlugList.Free;
end; end;
procedure TCEMainForm.FreeRunnableProc;
var
fname: string;
begin
if fRunProc = nil then
exit;
//
fname := fRunProc.Executable;
fRunProc.Terminate(0);
fRunProc.Free;
fRunProc := nil;
if fileExists(fname) then
sysutils.DeleteFile(fname);
end;
destructor TCEMainForm.destroy; destructor TCEMainForm.destroy;
begin begin
SaveSettings; SaveSettings;
@ -671,6 +695,7 @@ begin
fProjMru.Free; fProjMru.Free;
fFileMru.Free; fFileMru.Free;
fProject.Free; fProject.Free;
FreeRunnableProc;
// //
EntitiesConnector.removeObserver(self); EntitiesConnector.removeObserver(self);
inherited; inherited;
@ -1177,21 +1202,25 @@ var
dt: PMessageItemData; dt: PMessageItemData;
i: NativeInt; i: NativeInt;
msg: string; msg: string;
hasRead: boolean;
begin begin
If not (poUsePipes in aProcess.Options) then exit; If not (poUsePipes in aProcess.Options) then exit;
// //
readCnt := 0; readCnt := 0;
readSz := 0;
hasRead := false;
ioBuffSz := aProcess.PipeBufferSize; ioBuffSz := aProcess.PipeBufferSize;
str := TMemorystream.Create; str := TMemorystream.Create;
lns := TStringList.Create; lns := TStringList.Create;
readSz := 0;
try try
repeat while aProcess.Output.NumBytesAvailable <> 0 do
str.SetSize(readSz + ioBuffSz); begin
hasRead := true;
str.Size := str.Size + ioBuffSz;
readCnt := aProcess.Output.Read((str.Memory + readSz)^, ioBuffSz); readCnt := aProcess.Output.Read((str.Memory + readSz)^, ioBuffSz);
Inc(readSz, readCnt); readSz += readCnt;
until readCnt = 0; end;
Str.SetSize(readSz); str.Size := readSz;
lns.LoadFromStream(Str); lns.LoadFromStream(Str);
for i:= 0 to lns.Count-1 do begin for i:= 0 to lns.Count-1 do begin
msg := lns.Strings[i]; msg := lns.Strings[i];
@ -1209,19 +1238,36 @@ begin
finally finally
str.Free; str.Free;
lns.Free; lns.Free;
fMesgWidg.scrollToBack; if hasRead then
fMesgWidg.scrollToBack;
end; end;
end; end;
procedure TCEMainForm.OutputTimerTimer(Sender: TObject);
begin
if fRunProc <> nil then
ProcessOutputToMsg(fRunProc, mcEditor);
end;
procedure TCEMainForm.asyncprocOutput(sender: TObject);
begin
//ProcessOutputToMsg(TAsyncProcess(sender), mcEditor);
end;
procedure TCEMainForm.compileAndRunFile(const edIndex: NativeInt; const runArgs: string = ''); procedure TCEMainForm.compileAndRunFile(const edIndex: NativeInt; const runArgs: string = '');
var var
editor: TCESynMemo; editor: TCESynMemo;
dmdproc: TProcess; dmdproc: TProcess;
runproc: TProcess; //runproc: TProcess;
fname: string; fname: string;
begin begin
FreeRunnableProc;
fRunProc := TProcess.Create(nil);
//fRunProc := TAsyncProcess.Create(nil);
//fRunProc.OnReadData := @asyncprocOutput;
dmdproc := TProcess.Create(nil); dmdproc := TProcess.Create(nil);
runproc := TProcess.Create(nil);
editor := fEditWidg.editor[edIndex]; editor := fEditWidg.editor[edIndex];
try try
@ -1250,13 +1296,17 @@ begin
begin begin
ProcessOutputToMsg(dmdproc, mcEditor); ProcessOutputToMsg(dmdproc, mcEditor);
fMesgWidg.addCeInf(editor.fileName + ' successfully compiled', mcEditor ); fMesgWidg.addCeInf(editor.fileName + ' successfully compiled', mcEditor );
runproc.Options := [poStderrToOutPut, poUsePipes]; fRunProc.Options := fRunProc.Options + [poStderrToOutPut, poUsePipes];
runproc.CurrentDirectory := extractFilePath(runProc.Executable); fRunProc.CurrentDirectory := extractFilePath(fRunProc.Executable);
runproc.Parameters.DelimitedText := expandSymbolicString(runArgs); fRunProc.Parameters.DelimitedText := expandSymbolicString(runArgs);
runproc.Executable := fname + exeExt; fRunProc.Executable := fname + exeExt;
runproc.Execute; fPrInpWidg.process := fRunProc;
repeat ProcessOutputToMsg(runproc, mcEditor) until not runproc.Running; fRunProc.Execute;
sysutils.DeleteFile(fname + exeExt);
//ProcessOutputToMsg(fRunProc, mcEditor);
//repeat ProcessOutputToMsg(runproc, mcEditor) until not runproc.Running;
//sysutils.DeleteFile(fname + exeExt);
sysutils.DeleteFile(fname + objExt); sysutils.DeleteFile(fname + objExt);
end end
else begin else begin
@ -1264,9 +1314,11 @@ begin
fMesgWidg.addCeErr(editor.fileName + ' has not been compiled', mcEditor ); fMesgWidg.addCeErr(editor.fileName + ' has not been compiled', mcEditor );
end; end;
//fPrInpWidg.process := nil;
finally finally
dmdproc.Free; dmdproc.Free;
runproc.Free; //runproc.Free;
end; end;
end; end;

59
src/ce_procinput.lfm Normal file
View File

@ -0,0 +1,59 @@
inherited CEProcInputWidget: TCEProcInputWidget
Left = 1427
Height = 61
Top = 335
Width = 481
Caption = 'Process input'
ClientHeight = 61
ClientWidth = 481
inherited Back: TPanel
Height = 61
Width = 481
ClientHeight = 61
ClientWidth = 481
inherited Content: TPanel
Height = 61
Width = 481
ClientHeight = 61
ClientWidth = 481
object txtInp: TEdit[0]
Left = 4
Height = 27
Top = 30
Width = 394
Align = alClient
BorderSpacing.Left = 4
BorderSpacing.Top = 2
BorderSpacing.Right = 4
BorderSpacing.Bottom = 4
OnKeyPress = txtInpKeyPress
TabOrder = 0
end
object btnSend: TButton[1]
Left = 402
Height = 27
Top = 30
Width = 75
Align = alRight
BorderSpacing.Top = 2
BorderSpacing.Right = 4
BorderSpacing.Bottom = 4
Caption = 'Send'
OnClick = btnSendClick
TabOrder = 1
end
object txtExeName: TStaticText[2]
Left = 4
Height = 22
Top = 4
Width = 473
Align = alTop
BorderSpacing.Around = 4
BorderStyle = sbsSunken
Caption = 'no process'
TabOrder = 2
Transparent = False
end
end
end
end

71
src/ce_procinput.pas Normal file
View File

@ -0,0 +1,71 @@
unit ce_procinput;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
Menus, StdCtrls, ce_widget, process, ce_common;
type
{ TCEProcInputWidget }
TCEProcInputWidget = class(TCEWidget)
btnSend: TButton;
txtInp: TEdit;
txtExeName: TStaticText;
procedure btnSendClick(Sender: TObject);
procedure txtInpKeyPress(Sender: TObject; var Key: char);
private
fProc: TProcess;
procedure sendInput;
procedure setProc(const aValue: TProcess);
public
property process: TProcess read fProc write setProc;
end;
implementation
{$R *.lfm}
procedure TCEProcInputWidget.setProc(const aValue: TProcess);
begin
txtExeName.Caption := 'no process';
fProc := nil;
if aValue = nil then
exit;
if not (poUsePipes in aValue.Options) then
exit;
fProc := aValue;
txtExeName.Caption := shortenPath(fProc.Executable);
end;
procedure TCEProcInputWidget.sendInput;
var
inp: string;
begin
inp := txtInp.Text + lineEnding;
fProc.Input.Write(inp[1], length(inp));
txtInp.Text := '';
end;
procedure TCEProcInputWidget.txtInpKeyPress(Sender: TObject; var Key: char);
begin
if fProc = nil then
exit;
if key <> lineEnding[1] then
exit;
sendInput;
end;
procedure TCEProcInputWidget.btnSendClick(Sender: TObject);
begin
if fProc = nil then
exit;
sendInput;
end;
end.