From 2cd3455fcb6275643b27ca00e4fd8e758fdade4d Mon Sep 17 00:00:00 2001 From: Wasin Chintapanyakul Date: Wed, 9 Aug 2023 09:00:36 +0700 Subject: [PATCH 1/4] Fix std/random bug - Remove OpenSystemsLab/tempfile.nim and replace with build-in `std/tempfiles` - Remove low level stuff that might break in newer Windows update and replace with build-in `fusion/ioutils` - Add ability to name the temp file --- src/nimib/capture.nim | 62 +++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/src/nimib/capture.nim b/src/nimib/capture.nim index f82a2978..fca1a9c2 100644 --- a/src/nimib/capture.nim +++ b/src/nimib/capture.nim @@ -1,30 +1,40 @@ ## This submodule implements only one template to temporarily redirect and capture stdout during execution of a chunk of code. -import tempfile - -# see https://stackoverflow.com/questions/64026829/how-to-temporarily-capture-stdout -# Thanks, Clonk! - -# low level, should be Posix only but they happen to work on (my) Windows, too! -proc dup(oldfd: FileHandle): FileHandle {.importc, header: "unistd.h".} -proc dup2(oldfd: FileHandle, newfd: FileHandle): cint {.importc, header: "unistd.h".} +import fusion/ioutils +import std/os +import std/tempfiles template captureStdout*(ident: untyped, body: untyped) = - ## redirect stdout to a temporary file and captures output of body in ident - let - # Duplicate stdout - stdoutFileno = stdout.getFileHandle() - stdoutDupfd = dup(stdoutFileno) - # Create a new temporary file - (tmpFile, tmpFilename) = mkstemp(mode=fmWrite) - tmpFileFd: FileHandle = tmpFile.getFileHandle() - discard dup2(tmpFileFd, stdoutFileno) # writing to stdoutFileno now writes to tmpFile + captureStdout(ident, "", body) - body - flushFile stdout - - # before reading tmpFile, flush and close - tmpFile.flushFile() - tmpFile.close() - ident = readFile(tmpFileName) - # Restore stdout - discard dup2(stdoutDupfd, stdoutFileno) +template captureStdout*(ident: untyped, filename: string, body: untyped) = + ## redirect stdout to a temporary file and captures output of body in ident + # Duplicate stdout + let stdoutFileno: FileHandle = stdout.getFileHandle() + let stdoutDupFd: FileHandle = stdoutFileno.duplicate() + + # Create a new temporary file or attemp to open it + let (tmpFile, tmpFileName {.used.}) = when filename == "": + createTempFile("tmp", "") + else: + let tmpName = getTempDir() / filename + (tmpName.open(fmAppend), tmpName) + let tmpFileFd: FileHandle = tmpFile.getFileHandle() + + # writing to stdoutFileno now writes to tmpFile + tmpFileFd.duplicateTo(stdoutFileno) + + # Execute body code + body + + # Flush stdout and tmpFile, read tmpFile from start to ident and then close tmpFile + stdout.flushFile() + tmpFile.flushFile() + when filename == "": + tmpFile.setFilePos(0) + else: + discard tmpFile.reopen(tmpFileName) + ident = tmpFile.readAll() + tmpFile.close() + + # Restore stdout + stdoutDupFd.duplicateTo(stdoutFileno) From 9faa28aa4362164508ea448dd5df776215a801c3 Mon Sep 17 00:00:00 2001 From: Wasin Chintapanyakul Date: Wed, 9 Aug 2023 20:35:44 +0700 Subject: [PATCH 2/4] Reorder template and change from `when` to `if` --- src/nimib/capture.nim | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/nimib/capture.nim b/src/nimib/capture.nim index fca1a9c2..c70ba8fa 100644 --- a/src/nimib/capture.nim +++ b/src/nimib/capture.nim @@ -3,17 +3,14 @@ import fusion/ioutils import std/os import std/tempfiles -template captureStdout*(ident: untyped, body: untyped) = - captureStdout(ident, "", body) - template captureStdout*(ident: untyped, filename: string, body: untyped) = ## redirect stdout to a temporary file and captures output of body in ident # Duplicate stdout let stdoutFileno: FileHandle = stdout.getFileHandle() let stdoutDupFd: FileHandle = stdoutFileno.duplicate() - # Create a new temporary file or attemp to open it - let (tmpFile, tmpFileName {.used.}) = when filename == "": + # Create a new temporary file or attempt to open it + let (tmpFile, tmpFileName {.used.}) = if filename == "": createTempFile("tmp", "") else: let tmpName = getTempDir() / filename @@ -29,7 +26,7 @@ template captureStdout*(ident: untyped, filename: string, body: untyped) = # Flush stdout and tmpFile, read tmpFile from start to ident and then close tmpFile stdout.flushFile() tmpFile.flushFile() - when filename == "": + if filename == "": tmpFile.setFilePos(0) else: discard tmpFile.reopen(tmpFileName) @@ -38,3 +35,6 @@ template captureStdout*(ident: untyped, filename: string, body: untyped) = # Restore stdout stdoutDupFd.duplicateTo(stdoutFileno) + +template captureStdout*(ident: untyped, body: untyped) = + captureStdout(ident, "", body) From 8a03d8cd3d4f254e697d484137b81f6837d03ef3 Mon Sep 17 00:00:00 2001 From: Wasin Chintapanyakul Date: Wed, 9 Aug 2023 20:38:23 +0700 Subject: [PATCH 3/4] Update nimib.nimble --- nimib.nimble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimib.nimble b/nimib.nimble index 4ee2de10..a63b931a 100644 --- a/nimib.nimble +++ b/nimib.nimble @@ -9,7 +9,7 @@ srcDir = "src" # Dependencies requires "nim >= 1.4.0" -requires "tempfile >= 0.1.6" +requires "fusion >= 1.2" requires "markdown >= 0.8.1" requires "mustache >= 0.2.1" requires "parsetoml >= 0.7.0" From ead11e436e7a9d45da58c7bf1f48b7de7f4bb7c2 Mon Sep 17 00:00:00 2001 From: Wasin Chintapanyakul Date: Thu, 10 Aug 2023 08:01:12 +0700 Subject: [PATCH 4/4] Remove filename overload --- src/nimib/capture.nim | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/src/nimib/capture.nim b/src/nimib/capture.nim index c70ba8fa..d3906761 100644 --- a/src/nimib/capture.nim +++ b/src/nimib/capture.nim @@ -1,20 +1,15 @@ ## This submodule implements only one template to temporarily redirect and capture stdout during execution of a chunk of code. import fusion/ioutils -import std/os import std/tempfiles -template captureStdout*(ident: untyped, filename: string, body: untyped) = +template captureStdout*(ident: untyped, body: untyped) = ## redirect stdout to a temporary file and captures output of body in ident # Duplicate stdout let stdoutFileno: FileHandle = stdout.getFileHandle() let stdoutDupFd: FileHandle = stdoutFileno.duplicate() # Create a new temporary file or attempt to open it - let (tmpFile, tmpFileName {.used.}) = if filename == "": - createTempFile("tmp", "") - else: - let tmpName = getTempDir() / filename - (tmpName.open(fmAppend), tmpName) + let (tmpFile, _) = createTempFile("tmp", "") let tmpFileFd: FileHandle = tmpFile.getFileHandle() # writing to stdoutFileno now writes to tmpFile @@ -26,15 +21,9 @@ template captureStdout*(ident: untyped, filename: string, body: untyped) = # Flush stdout and tmpFile, read tmpFile from start to ident and then close tmpFile stdout.flushFile() tmpFile.flushFile() - if filename == "": - tmpFile.setFilePos(0) - else: - discard tmpFile.reopen(tmpFileName) + tmpFile.setFilePos(0) ident = tmpFile.readAll() tmpFile.close() # Restore stdout stdoutDupFd.duplicateTo(stdoutFileno) - -template captureStdout*(ident: untyped, body: untyped) = - captureStdout(ident, "", body)