7 people like it.

exec with redirected io as sequences

Since F# is my new scripting language, I needed something like Perl's exec but with sequences for Std In and Out.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
open System.Diagnostics
open System.IO
open System.Threading

let inline asOptionBy f v = match f v with | null -> None; | _ -> Some v
let inline asOption v = asOptionBy id

// Something like Perl's exec - path to exe, comand line arguments, input stream
// returns a sequence of strings from StdOut.  
// note: Each enumeration will relaunch the process so cache if appropriate
let exec exePath exeArgs iSeq =
    seq {
        let pInfo = new ProcessStartInfo( exePath, 
                                          exeArgs, 
                                          CreateNoWindow = true, 
                                          UseShellExecute = false, 
                                          RedirectStandardInput = true, 
                                          RedirectStandardOutput = true)
        use p = Process.Start( pInfo )
        let cts = new CancellationTokenSource()
        let fwdInp = async {Seq.iter (fun (line:string) -> p.StandardInput.WriteLine(line) ) iSeq }

        // Start a task to feed the process input
        let task = Async.StartAsTask( fwdInp, cancellationToken = cts.Token )
                    .ContinueWith( (fun (t:Tasks.Task<unit>) -> p.StandardInput.Dispose()) )

        // Map the lines coming from the process into a sequence
        yield! Seq.unfold (fun (s:StreamReader) -> (s.ReadLine(),s) |> asOptionBy fst) p.StandardOutput
        cts.Cancel()
        task.Wait()
        }

// Print current ipv4 addresses sorted
exec "ipconfig" "" Seq.empty |> exec "findstr" "IPv4" |> exec "sort" "" |> Seq.iter (printfn "%s")
namespace System
namespace System.Diagnostics
namespace System.IO
namespace System.Threading
val asOptionBy : f:('a -> 'b) -> v:'a -> 'a option (requires 'b : null)

Full name: Script.asOptionBy
val f : ('a -> 'b) (requires 'b : null)
val v : 'a
union case Option.None: Option<'T>
union case Option.Some: Value: 'T -> Option<'T>
val asOption : v:'a -> ('b -> 'b option) (requires 'b : null)

Full name: Script.asOption
val id : x:'T -> 'T

Full name: Microsoft.FSharp.Core.Operators.id
val exec : exePath:string -> exeArgs:string -> iSeq:seq<string> -> seq<string>

Full name: Script.exec
val exePath : string
val exeArgs : string
val iSeq : seq<string>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = System.Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
val pInfo : ProcessStartInfo
Multiple items
type ProcessStartInfo =
  new : unit -> ProcessStartInfo + 2 overloads
  member Arguments : string with get, set
  member CreateNoWindow : bool with get, set
  member Domain : string with get, set
  member EnvironmentVariables : StringDictionary
  member ErrorDialog : bool with get, set
  member ErrorDialogParentHandle : nativeint with get, set
  member FileName : string with get, set
  member LoadUserProfile : bool with get, set
  member Password : SecureString with get, set
  ...

Full name: System.Diagnostics.ProcessStartInfo

--------------------
ProcessStartInfo() : unit
ProcessStartInfo(fileName: string) : unit
ProcessStartInfo(fileName: string, arguments: string) : unit
val p : Process
Multiple items
type Process =
  inherit Component
  new : unit -> Process
  member BasePriority : int
  member BeginErrorReadLine : unit -> unit
  member BeginOutputReadLine : unit -> unit
  member CancelErrorRead : unit -> unit
  member CancelOutputRead : unit -> unit
  member Close : unit -> unit
  member CloseMainWindow : unit -> bool
  member EnableRaisingEvents : bool with get, set
  member ExitCode : int
  ...

Full name: System.Diagnostics.Process

--------------------
Process() : unit
Process.Start(startInfo: ProcessStartInfo) : Process
Process.Start(fileName: string) : Process
Process.Start(fileName: string, arguments: string) : Process
Process.Start(fileName: string, userName: string, password: System.Security.SecureString, domain: string) : Process
Process.Start(fileName: string, arguments: string, userName: string, password: System.Security.SecureString, domain: string) : Process
val cts : CancellationTokenSource
Multiple items
type CancellationTokenSource =
  new : unit -> CancellationTokenSource
  member Cancel : unit -> unit + 1 overload
  member Dispose : unit -> unit
  member IsCancellationRequested : bool
  member Token : CancellationToken
  static member CreateLinkedTokenSource : [<ParamArray>] tokens:CancellationToken[] -> CancellationTokenSource + 1 overload

Full name: System.Threading.CancellationTokenSource

--------------------
CancellationTokenSource() : unit
val fwdInp : Async<unit>
val async : AsyncBuilder

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.async
module Seq

from Microsoft.FSharp.Collections
val iter : action:('T -> unit) -> source:seq<'T> -> unit

Full name: Microsoft.FSharp.Collections.Seq.iter
val line : string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
property Process.StandardInput: StreamWriter
TextWriter.WriteLine() : unit
   (+0 other overloads)
TextWriter.WriteLine(value: obj) : unit
   (+0 other overloads)
TextWriter.WriteLine(value: string) : unit
   (+0 other overloads)
TextWriter.WriteLine(value: decimal) : unit
   (+0 other overloads)
TextWriter.WriteLine(value: float) : unit
   (+0 other overloads)
TextWriter.WriteLine(value: float32) : unit
   (+0 other overloads)
TextWriter.WriteLine(value: uint64) : unit
   (+0 other overloads)
TextWriter.WriteLine(value: int64) : unit
   (+0 other overloads)
TextWriter.WriteLine(value: uint32) : unit
   (+0 other overloads)
TextWriter.WriteLine(value: int) : unit
   (+0 other overloads)
val task : Tasks.Task
Multiple items
type Async
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
static member Ignore : computation:Async<'T> -> Async<unit>
static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
static member Sleep : millisecondsDueTime:int -> Async<unit>
static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
static member SwitchToNewThread : unit -> Async<unit>
static member SwitchToThreadPool : unit -> Async<unit>
static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
static member CancellationToken : Async<CancellationToken>
static member DefaultCancellationToken : CancellationToken

Full name: Microsoft.FSharp.Control.Async

--------------------
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>
static member Async.StartAsTask : computation:Async<'T> * ?taskCreationOptions:Tasks.TaskCreationOptions * ?cancellationToken:CancellationToken -> Tasks.Task<'T>
property CancellationTokenSource.Token: CancellationToken
val t : Tasks.Task<unit>
namespace System.Threading.Tasks
Multiple items
type Task<'TResult> =
  inherit Task
  new : function:Func<'TResult> -> Task<'TResult> + 7 overloads
  member ContinueWith : continuationAction:Action<Task<'TResult>> -> Task + 9 overloads
  member Result : 'TResult with get, set
  static member Factory : TaskFactory<'TResult>

Full name: System.Threading.Tasks.Task<_>

--------------------
type Task =
  new : action:Action -> Task + 7 overloads
  member AsyncState : obj
  member ContinueWith : continuationAction:Action<Task> -> Task + 9 overloads
  member CreationOptions : TaskCreationOptions
  member Dispose : unit -> unit
  member Exception : AggregateException
  member Id : int
  member IsCanceled : bool
  member IsCompleted : bool
  member IsFaulted : bool
  ...

Full name: System.Threading.Tasks.Task

--------------------
Tasks.Task(function: System.Func<'TResult>) : unit
Tasks.Task(function: System.Func<'TResult>, cancellationToken: CancellationToken) : unit
Tasks.Task(function: System.Func<'TResult>, creationOptions: Tasks.TaskCreationOptions) : unit
Tasks.Task(function: System.Func<obj,'TResult>, state: obj) : unit
Tasks.Task(function: System.Func<'TResult>, cancellationToken: CancellationToken, creationOptions: Tasks.TaskCreationOptions) : unit
Tasks.Task(function: System.Func<obj,'TResult>, state: obj, cancellationToken: CancellationToken) : unit
Tasks.Task(function: System.Func<obj,'TResult>, state: obj, creationOptions: Tasks.TaskCreationOptions) : unit
Tasks.Task(function: System.Func<obj,'TResult>, state: obj, cancellationToken: CancellationToken, creationOptions: Tasks.TaskCreationOptions) : unit

--------------------
Tasks.Task(action: System.Action) : unit
Tasks.Task(action: System.Action, cancellationToken: CancellationToken) : unit
Tasks.Task(action: System.Action, creationOptions: Tasks.TaskCreationOptions) : unit
Tasks.Task(action: System.Action<obj>, state: obj) : unit
Tasks.Task(action: System.Action, cancellationToken: CancellationToken, creationOptions: Tasks.TaskCreationOptions) : unit
Tasks.Task(action: System.Action<obj>, state: obj, cancellationToken: CancellationToken) : unit
Tasks.Task(action: System.Action<obj>, state: obj, creationOptions: Tasks.TaskCreationOptions) : unit
Tasks.Task(action: System.Action<obj>, state: obj, cancellationToken: CancellationToken, creationOptions: Tasks.TaskCreationOptions) : unit
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
TextWriter.Dispose() : unit
val unfold : generator:('State -> ('T * 'State) option) -> state:'State -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.unfold
val s : StreamReader
Multiple items
type StreamReader =
  inherit TextReader
  new : stream:Stream -> StreamReader + 9 overloads
  member BaseStream : Stream
  member Close : unit -> unit
  member CurrentEncoding : Encoding
  member DiscardBufferedData : unit -> unit
  member EndOfStream : bool
  member Peek : unit -> int
  member Read : unit -> int + 1 overload
  member ReadLine : unit -> string
  member ReadToEnd : unit -> string
  ...

Full name: System.IO.StreamReader

--------------------
StreamReader(stream: Stream) : unit
StreamReader(path: string) : unit
StreamReader(stream: Stream, detectEncodingFromByteOrderMarks: bool) : unit
StreamReader(stream: Stream, encoding: System.Text.Encoding) : unit
StreamReader(path: string, detectEncodingFromByteOrderMarks: bool) : unit
StreamReader(path: string, encoding: System.Text.Encoding) : unit
StreamReader(stream: Stream, encoding: System.Text.Encoding, detectEncodingFromByteOrderMarks: bool) : unit
StreamReader(path: string, encoding: System.Text.Encoding, detectEncodingFromByteOrderMarks: bool) : unit
StreamReader(stream: Stream, encoding: System.Text.Encoding, detectEncodingFromByteOrderMarks: bool, bufferSize: int) : unit
StreamReader(path: string, encoding: System.Text.Encoding, detectEncodingFromByteOrderMarks: bool, bufferSize: int) : unit
StreamReader.ReadLine() : string
val fst : tuple:('T1 * 'T2) -> 'T1

Full name: Microsoft.FSharp.Core.Operators.fst
property Process.StandardOutput: StreamReader
CancellationTokenSource.Cancel() : unit
CancellationTokenSource.Cancel(throwOnFirstException: bool) : unit
Tasks.Task.Wait() : unit
Tasks.Task.Wait(millisecondsTimeout: int) : bool
Tasks.Task.Wait(cancellationToken: CancellationToken) : unit
Tasks.Task.Wait(timeout: System.TimeSpan) : bool
Tasks.Task.Wait(millisecondsTimeout: int, cancellationToken: CancellationToken) : bool
val empty<'T> : seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.empty
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
Raw view Test code New version

More information

Link:http://fssnip.net/4A
Posted:12 years ago
Author:Tony Lee
Tags: sequence , scripting