From 9fba13a9658139d6168a7f384f64a0c90444f00d Mon Sep 17 00:00:00 2001 From: Jonathan Bernard Date: Wed, 16 Aug 2017 11:01:22 -0500 Subject: [PATCH] Refactor exec interface. --- cliutils.nim | 83 +++++++++++++++++++++++++++---------------------- cliutils.nimble | 2 +- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/cliutils.nim b/cliutils.nim index 057f780..576a87d 100644 --- a/cliutils.nim +++ b/cliutils.nim @@ -31,48 +31,15 @@ proc sendMsg*(h: HandleProcMsgCB, outMsg: TaintedString, errMsg: TaintedString = nil, cmd: string = ""): void = if h != nil: h(outMsg, errMsg, cmd) -proc waitForWithOutput*(p: Process, msgCB: HandleProcMsgCB, - procCmd: string = ""): - tuple[output: TaintedString, error: TaintedString, exitCode: int] = - - var pout = outputStream(p) - var perr = errorStream(p) - - result = (TaintedString"", TaintedString"", -1) - var line = newStringOfCap(120).TaintedString - while true: - if pout.readLine(line): - msgCB.sendMsg(line, nil, procCmd) - result[0].string.add(line.string) - result[0].string.add("\n") - elif perr.readLine(line): - msgCB.sendMsg(nil, line, procCmd) - result[1].string.add(line.string) - result[1].string.add("\n") - else: - result[2] = peekExitCode(p) - if result[2] != -1: break - close(p) - -proc exec*(command: string, workingDir: string = "", - args: openArray[string] = [], env: StringTableRef = nil, - options: set[ProcessOption] = {poUsePath}, - msgCB: HandleProcMsgCB = nil): - tuple[output: TaintedString, error: TaintedString, exitCode: int] - {.tags: [ExecIOEffect, ReadIOEffect], gcsafe.} = - - var p = startProcess(command, workingDir, args, env, options) - result = waitForWithOutput(p, msgCb, command) - -proc makeProcMsgHandler*(outSink, errSink: File): HandleProcMsgCB = +proc makeProcMsgHandler*(outSink, errSink: File, prefixCmd: bool = true): HandleProcMsgCB = result = proc(outMsg, errMsg: TaintedString, cmd: string): void {.closure.} = - let prefix = if cmd != nil: cmd & ": " else: "" + let prefix = if cmd == nil or not prefixCmd: "" else: cmd & ": " if outMsg != nil: outSink.writeLine(prefix & outMsg) if errMsg != nil: errSink.writeLine(prefix & errMsg) -proc makeProcMsgHandler*(outSink, errSink: Stream): HandleProcMsgCB = +proc makeProcMsgHandler*(outSink, errSink: Stream, prefixCmd: bool = true): HandleProcMsgCB = result = proc(outMsg, errMsg: TaintedString, cmd: string): void {.closure.} = - let prefix = if cmd != nil: cmd & ": " else: "" + let prefix = if cmd == nil or not prefixCmd: "" else: cmd & ": " if outMsg != nil: outSink.writeLine(prefix & outMsg) if errMsg != nil: errSink.writeLine(prefix & errMsg) @@ -84,6 +51,48 @@ proc combineProcMsgHandlers*(a, b: HandleProcMsgCB): HandleProcMsgCB = a(cmd, outMsg, errMsg) b(cmd, outMsg, errMsg) +proc waitFor*(p: Process, msgCB: HandleProcMsgCB, procCmd: string = ""): int = + + var pout = outputStream(p) + var perr = errorStream(p) + + var line = newStringOfCap(120).TaintedString + while true: + if pout.readLine(line): + msgCB.sendMsg(line, nil, procCmd) + elif perr.readLine(line): + msgCB.sendMsg(nil, line, procCmd) + else: + result = peekExitCode(p) + if result != -1: break + close(p) + +proc exec*(command: string, workingDir: string = "", + args: openArray[string] = [], env: StringTableRef = nil, + options: set[ProcessOption] = {poUsePath}, + msgCB: HandleProcMsgCB = nil): int + {.tags: [ExecIOEffect, ReadIOEffect], gcsafe.} = + + var p = startProcess(command, workingDir, args, env, options) + result = waitFor(p, msgCB, command) + +proc execWithOutput*(command: string, workingDir:string = "", + args: openArray[string] = [], env: StringTableRef = nil, + options: set[ProcessOption] = {poUsePath}, + msgCB: HandleProcMsgCB = nil): + tuple[output: TaintedString, error: TaintedString, exitCode: int] = + + result = (TaintedString"", TaintedString"", -1) + var outSeq, errSeq: seq[TaintedString] + outSeq = @[]; errSeq = @[] + var outputCollector = combineProcMsgHandlers(msgCB, + proc(outMsg, errMsg: TaintedString, cmd: string): void {.closure.} = + if outMsg != nil: outSeq.add(outMsg) + if errMsg != nil: errSeq.add(errMsg)) + + result[2] = exec(command, workingDir, args, env, options, outputCollector) + result[0] = outSeq.join("\n") + result[1] = errSeq.join("\n") ## Daemonize diff --git a/cliutils.nimble b/cliutils.nimble index 6afe096..52a0491 100644 --- a/cliutils.nimble +++ b/cliutils.nimble @@ -1,6 +1,6 @@ # Package -version = "0.2.1" +version = "0.3.0" author = "Jonathan Bernard" description = "Helper functions for writing command line interfaces." license = "MIT"