# this file contains some utilities copied from the Documenter.jl package # (https://github.com/JuliaDocs/Documenter.jl), see LICENSE.md for license module Documenter function withoutput(f) # Save the default output streams. default_stdout = stdout default_stderr = stderr # Redirect both the `stdout` and `stderr` streams to a single `Pipe` object. pipe = Pipe() Base.link_pipe!(pipe; reader_supports_async = true, writer_supports_async = true) redirect_stdout(pipe.in) redirect_stderr(pipe.in) # Also redirect logging stream to the same pipe logger = Base.CoreLogging.SimpleLogger(pipe.in) # Bytes written to the `pipe` are captured in `output` and converted to a `String`. output = UInt8[] # Run the function `f`, capturing all output that it might have generated. # Success signals whether the function `f` did or did not throw an exception. result, success, backtrace = Base.CoreLogging.with_logger(logger) do try f(), true, Vector{Ptr{Cvoid}}() catch err err, false, catch_backtrace() finally # Force at least a single write to `pipe`, otherwise `readavailable` blocks. println() # Restore the original output streams. redirect_stdout(default_stdout) redirect_stderr(default_stderr) # NOTE: `close` must always be called *after* `readavailable`. append!(output, readavailable(pipe)) close(pipe) end end return result, success, backtrace, chomp(String(output)) end end