diff options
-rw-r--r-- | changelog.md | 2 | ||||
-rw-r--r-- | lib/pure/osproc.nim | 51 | ||||
-rw-r--r-- | tests/osproc/treadlines.nim | 20 |
3 files changed, 73 insertions, 0 deletions
diff --git a/changelog.md b/changelog.md index 3bae911e9..3cdf138ad 100644 --- a/changelog.md +++ b/changelog.md @@ -199,6 +199,8 @@ - Add `initUri(isIpv6: bool)` to `uri` module, now `uri` supports parsing ipv6 hostname. +- Add `readLines(p: Process)` to `osproc` module for `startProcess` convenience. + ## Language changes - The `=destroy` hook no longer has to reset its target, as the compiler now automatically inserts diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 5113695d8..2d48597dc 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -444,6 +444,57 @@ proc execProcesses*(cmds: openArray[string], if afterRunEvent != nil: afterRunEvent(i, p) close(p) +iterator lines*(p: Process): string {.since: (1, 3), tags: [ReadIOEffect].} = + ## Convenience iterator for working with `startProcess` to read data from a + ## background process. + ## + ## See also: + ## * `readLines proc <#readLines,Process>`_ + ## + ## Example: + ## + ## .. code-block:: Nim + ## const opts = {poUsePath, poDaemon, poStdErrToStdOut} + ## var ps: seq[Process] + ## for prog in ["a", "b"]: # run 2 progs in parallel + ## ps.add startProcess("nim", "", ["r", prog], nil, opts) + ## for p in ps: + ## var i = 0 + ## for line in p.lines: + ## echo line + ## i.inc + ## if i > 100: break + ## p.close + var outp = p.outputStream + var line = newStringOfCap(120) + while true: + if outp.readLine(line): + yield line + else: + if p.peekExitCode != -1: break + +proc readLines*(p: Process): (seq[string], int) {.since: (1, 3).} = + ## Convenience function for working with `startProcess` to read data from a + ## background process. + ## + ## See also: + ## * `lines iterator <#lines.i,Process>`_ + ## + ## Example: + ## + ## .. code-block:: Nim + ## const opts = {poUsePath, poDaemon, poStdErrToStdOut} + ## var ps: seq[Process] + ## for prog in ["a", "b"]: # run 2 progs in parallel + ## ps.add startProcess("nim", "", ["r", prog], nil, opts) + ## for p in ps: + ## let (lines, exCode) = p.readLines + ## if exCode != 0: + ## for line in lines: echo line + ## p.close + for line in p.lines: result[0].add(line) + result[1] = p.peekExitCode + when not defined(useNimRtl): proc execProcess(command: string, workingDir: string = "", args: openArray[string] = [], env: StringTableRef = nil, diff --git a/tests/osproc/treadlines.nim b/tests/osproc/treadlines.nim new file mode 100644 index 000000000..3a8303321 --- /dev/null +++ b/tests/osproc/treadlines.nim @@ -0,0 +1,20 @@ +discard """ + output: '''Error: cannot open 'a.nim' +Error: cannot open 'b.nim' +''' + targets: "c" +""" + +import osproc + +var ps: seq[Process] # compile & run 2 progs in parallel +for prog in ["a", "b"]: + ps.add startProcess("nim", "", + ["r", "--hint[Conf]=off", "--hint[Processing]=off", prog], + options = {poUsePath, poDaemon, poStdErrToStdOut}) + +for p in ps: + let (lines, exCode) = p.readLines + if exCode != 0: + for line in lines: echo line + p.close |