7 people like it.
Like the snippet!
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
More information