Redirect to FileCharacter : Fix an issue with existing files. A call MoveToEnd()
has been added to avoid a content erase. commit cbc51a96ceea867b502ddf2a152afb3e089e1c3c
This is a small library to handle IO redirect in ObjectScript.
Features :
Make sure you have git and Docker desktop installed.
Clone/git pull the repo into any local directory
$ git clone https://github.com/lscalese/IO-Redirect
Open the terminal in this directory and run:
$ docker-compose build
$ docker-compose up -d
zpm "install io-redirect"
For non ZPM user, xml export are available in dist
directory.
In Iris Terminal:
Set ^UnitTestRoot = "/irisrun/repo/test/"
Do ##class(%UnitTest.Manager).RunTest(,"/nodelete")
Or by zpm
zpm "test io-redirect"
It works in 3 steps :
Redirect is controlled by IORedirect.Redirect
class and need IO handlers classname as parameters.
Do ##class(IORedirect.Redirect).RedirectIO(<OutputHandler>,<InputHandler>)
InputHandler
parameter is not mandatory.
Current available handlers are :
Handlers | Type | Description | Setup |
---|---|---|---|
IORedirect.OutputStream |
Output | Redirect Output to a stream | Set output stream with Do ##class(IORedirect.OutputStream).Set(stream) |
IORedirect.OutputString |
Output | Redirect Output to a string | Init string Do ##class(IORedirect.OutputString).Set("") |
IORedirect.OutputGlobal |
Output | Redirect Output to a global | Set output global name with : Do ##class(IORedirect.OutputGlobal).Set($Name(^||IORedirect)) |
IORedirect.OutputNull |
Output | Cancel the output | Init string Do ##class(IORedirect.Redirect).ToNull() |
IORedirect.InputStream |
Input | Read Input from a stream | Set input stream with Do ##class(IORedirect.InputStream).Set(inputStream) |
IORedirect.InputString |
Input | Read Input from a stream | Set input stream with Do ##class(IORedirect.InputString).Set(inputString) |
To disable IO Redirect simply call :
Do ##class(IORedirect.Redirect).RestoreIO()
To redirect to a simple string :
Do ##class(IORedirect.Redirect).ToString()
; some code ...
Do ##class(IORedirect.Redirect).RestoreIO()
Set outputString = ##class(IORedirect.Redirect).Get()
Echo feature allows redirecting the output AND duplicates the write to the current device.
For example, in a terminal :
Do ##class(IORedirect.Redirect).ToString(1)
Write "this an echo test"
Do ##class(IORedirect.Redirect).RestoreIO()
Set outputString = ##class(IORedirect.Redirect).Get()
Write "Var outputString : ", outputString
Redirect the write to a string variable and also write the text in the terminal.
Echo is enabled with the value in argument Do ##class(IORedirect.Redirect).ToString(1)
Set line1 = "Stream First line" Set line2 = "Stream second line" Set line3 = 65 Set stream = ##class(%Stream.GlobalCharacter).%New()
Do ##class(IORedirect.Redirect).ToStream(stream)
Write line1
Write !,line2
Write !
Write *line3Do ##class(IORedirect.Redirect).RestoreIO()
Do ##class(IORedirect.Redirect).ClearConfig()
Do stream.OutputToDevice()
Do ##class(IORedirect.Redirect).ToStream(stream)
is equivalent to :
Do ##class(IORedirect.Redirect).RedirectIO("IORedirect.OutputStream")
Do ##class(IORedirect.OutputStream).Set(stream)
To enable echo redirect use Do ##class(IORedirect.Redirect).ToStream(stream, 1)
To redirect to a file you can use :
Do ##class(IORedirect.Redirect).ToFileCharacter(filename)
; some code ...
Do ##class(IORedirect.Redirect).RestoreIO()
Set fcs = ##class(IORedirect.Redirect).Get() ; to retrieve the %Stream.FileCharacter instance.
To enable echo redirect use Do ##class(IORedirect.Redirect).ToFileCharacter(filename, 1)
Set sc = $$$OK Set line1 = "Stream First line" Set line2 = "Stream second line" Set line3 = 65 Kill ^||IORedirect
Do ##class(IORedirect.Redirect).ToGlobal($Name(^||IORedirect))
Write line1
Write !,line2
Write !
Write *line3Do ##class(IORedirect.Redirect).RestoreIO()
Do ##class(IORedirect.Redirect).ClearConfig()
Zwrite ^||IORedirect
Kill ^||IORedirect
Do ##class(IORedirect.Redirect).ToGlobal($Name(^||IORedirect))
is equivalent to :
Do ##class(IORedirect.Redirect).RedirectIO("IORedirect.OutputGlobal")
Do ##class(IORedirect.OutputGlobal).SetRedirectLocation($Name(^||IORedirect))
To enable echo redirect use Do ##class(IORedirect.Redirect).ToGlobal($Name(^||IORedirect), 1)
In the following example, we redirect the IO Into a global and the input is in a stream object.
Set inputStream = ##class(%Stream.GlobalCharacter).%New() Set inputLine1 = "This is my input line 1" Do inputStream.WriteLine(inputLine1) Do inputStream.Rewind()
Set line1 = "This is a test with Input and Output redirect"
Set line2 = "Now, we READ something:"
Set line3 = "Read line is : "Set stream = ##class(%Stream.GlobalCharacter).%New()
Kill ^||IORedirectDo ##class(IORedirect.Redirect).ToGlobal($Name(^||IORedirect))
Do ##class(IORedirect.Redirect).InputStream(inputStream)Write line1
Write !,line2
READ x:2
Write !,line3
Write !,xDo ##class(IORedirect.Redirect).RestoreIO()
Do ##class(IORedirect.Redirect).ClearConfig()
Write !,"Read input value in var x is : ", !, x, !
Write !,"Output global ^||IORedirect : "
ZWrite ^||IORedirect
Kill ^||IORedirect
Similar to redirect from stream, use this line to enable :
Do ##class(IORedirect.Redirect).InputString(inputString)
This development is inspired by this community post.
IORedirect does not work if the process switch to another namespace for Reading\Writting.
You can easily fix this problem by adding a package mapping “IORedirect” on %ALL namespace.
Noticed by Timothy Leavitt·
One important note on I/O redirection, from the documentation:
When a process performs I/O redirection, this redirection is performed using the user’s login $ROLES value, not the current $ROLES value.
In other words, if the I/O redirection is happening in a CSP application or privileged routine application context, in which matching or application roles are added that grant permissions on resources protecting assets the I/O functions need, you might get an unexpected error, with roles seeming to disappear in wstr()/etc.