[Pkg-cli-apps-commits] [fsharp] 42/60: reimplement async reading from redirected stdout\stderr

Christopher Halse Rogers raof-guest at moszumanska.debian.org
Sun Sep 14 08:13:41 UTC 2014


This is an automated email from the git hooks/post-receive script.

raof-guest pushed a commit to branch master
in repository fsharp.

commit d29a5e226e881374e9065df2bcc9fcb850a39e91
Author: desco <desco.by at gmail.com>
Date:   Sat Aug 23 23:32:48 2014 -0700

    reimplement async reading from redirected stdout\stderr
---
 .../src/vs/FsPkgs/FSharp.VS.FSI/sessions.fs        | 55 ++++++++++++++++++----
 1 file changed, 47 insertions(+), 8 deletions(-)

diff --git a/vsintegration/src/vs/FsPkgs/FSharp.VS.FSI/sessions.fs b/vsintegration/src/vs/FsPkgs/FSharp.VS.FSI/sessions.fs
index 35bab88..d7be909 100644
--- a/vsintegration/src/vs/FsPkgs/FSharp.VS.FSI/sessions.fs
+++ b/vsintegration/src/vs/FsPkgs/FSharp.VS.FSI/sessions.fs
@@ -171,6 +171,48 @@ let determineFsiPath () =
     else
         raise (SessionError (VFSIstrings.SR.couldNotFindFsiExe fsiRegistryPath))
 
+let readLinesAsync(reader: System.IO.StreamReader): IEvent<string> =
+    let newLine = Event<_>()
+    let buffer = System.Text.StringBuilder(1024)
+    let byteBuffer = Array.zeroCreate 128
+    let encoding = System.Text.Encoding.UTF8
+    let decoder = encoding.GetDecoder()
+    let async0 = async.Return 0
+    let charBuffer = 
+        let maxCharsInBuffer = encoding.GetMaxCharCount byteBuffer.Length
+        Array.zeroCreate maxCharsInBuffer
+    
+    let rec findLinesInBuffer pos =
+        if pos >= buffer.Length then max (buffer.Length - 1) 0 // exit and point to the last char
+        else
+        let c = buffer.[pos]
+        if c = '\r' || c = '\n' then
+            let line = buffer.ToString(0, pos)
+            newLine.Trigger line
+
+            let deletePos = 
+                if c = '\r' && (pos + 1) < buffer.Length && buffer.[pos + 1] = '\n' then pos + 2 else pos + 1
+            buffer.Remove(0, deletePos) |> ignore
+            findLinesInBuffer 0
+        else
+            findLinesInBuffer (pos + 1)
+
+    let rec read pos = 
+        async {
+            let! bytesRead = 
+                try 
+                    reader.BaseStream.AsyncRead(byteBuffer, 0, byteBuffer.Length)
+                with
+                    | :? IOException -> async0
+            if bytesRead <> 0 then
+                let charsRead = decoder.GetChars(byteBuffer, 0, bytesRead, charBuffer, 0)
+                buffer.Append(charBuffer, 0, charsRead) |> ignore
+                let newPos = findLinesInBuffer pos
+                return! read newPos
+        }
+    Async.StartImmediate (read 0)
+    newLine.Publish
+
 let fsiStartInfo channelName =
     let procInfo = new ProcessStartInfo()
     let fsiPath  = determineFsiPath () 
@@ -208,16 +250,13 @@ let fsiProcess (procInfo:ProcessStartInfo) =
     let outW,outE = let e = new Event<_>() in e.Trigger, e.Publish
     let errW,errE = let e = new Event<_>() in e.Trigger, e.Publish
     let exitE = (cmdProcess.Exited |> Observable.map (fun x -> x)) // this gives the event the F# "standard" event type IEvent<'a> rather than IEvent<_,_>
-        
-    // wire up output (to both stdout and stderr) 
-    cmdProcess.OutputDataReceived |> catchAll |> Observable.add(fun data -> 
-        //System.Windows.Forms.MessageBox.Show (sprintf "OutputDataRecieved '%s'\n" data.Data) |> ignore
-        outW(data.Data));
-    cmdProcess.ErrorDataReceived  |> catchAll |> Observable.add (fun data -> errW(data.Data));
 
     let _ = cmdProcess.Start()
-    cmdProcess.BeginOutputReadLine();
-    cmdProcess.BeginErrorReadLine();    
+    // wire up output (to both stdout and stderr)
+    readLinesAsync cmdProcess.StandardOutput |> catchAll |> Observable.add(fun data -> 
+        //System.Windows.Forms.MessageBox.Show (sprintf "OutputDataRecieved '%s'\n" data.Data) |> ignore
+        outW(data));
+    readLinesAsync cmdProcess.StandardError  |> catchAll |> Observable.add (fun data -> errW(data));
 
     // wire up input 
     // Fix 982: Force input to be written in UTF8 regardless of the apparent encoding.

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-cli-apps/packages/fsharp.git



More information about the Pkg-cli-apps-commits mailing list