diff options
author | c-blake <c-blake@users.noreply.github.com> | 2020-10-01 12:06:38 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-01 18:06:38 +0200 |
commit | 26d656e73e2354bc6f177073b948a7791e8f7427 (patch) | |
tree | f9c71e406db77778e9543838f1b6b54e391e9513 | |
parent | 531ed2dc365d6d33c7bccdfbe22df561cf14af86 (diff) | |
download | Nim-26d656e73e2354bc6f177073b948a7791e8f7427.tar.gz |
Add first draft of new osproc.readLines (#15429)
* Add first draft of new osproc.readLines * Add test for new osproc.readLines * Rename test to start w/t to run; Also add newline to output * Suppress hint messages. * Output should match this time. * Shoulda picked a program with simpler syntax than ..lol * Address https://github.com/nim-lang/Nim/pull/15429#issuecomment-701890898 and https://github.com/nim-lang/Nim/pull/15429#issuecomment-701985976 by factoring `readLines` into `iterator lines` and a wrapper `proc`. * Address https://github.com/nim-lang/Nim/pull/15429#issuecomment-702127289 and also add a `ReadIOEffect` tag to the iterator (called by the wrapper.. so it should need no separate tag, if I understand correctly).
-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 |