Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a pass_through option #19

Closed
goerz opened this issue Jan 10, 2024 · 6 comments · Fixed by #20
Closed

Add a pass_through option #19

goerz opened this issue Jan 10, 2024 · 6 comments · Fixed by #20
Labels
enhancement New feature or request

Comments

@goerz
Copy link
Member

goerz commented Jan 10, 2024

I would like to have a tee option so that

c = IOCapture.capture(tee=true) do
     println("test")
     return 42
 end;

captures the output and value of the code block, but also still prints to the normal stdout and stderr (or combines stderr into stdout, I don't care about keeping them separate). What I do care about is that it should stream stdout as normal, while the function is running, as opposed to just dumping the captured output after the block finished running.

The option could be named something other than tee, of course, if that's too unix-jargony.

@goerz
Copy link
Member Author

goerz commented Jan 10, 2024

@mortenpi mortenpi added the enhancement New feature or request label Jan 10, 2024
@mortenpi
Copy link
Member

mortenpi commented Jan 10, 2024

This seems like a good feature to have here. I would indeed call it something other than tee though, since that does feel a bit jargony.

@goerz
Copy link
Member Author

goerz commented Jan 10, 2024

I'm going to play around a little and see if I come up with something that works

@goerz
Copy link
Member Author

goerz commented Jan 10, 2024

Well, here's a start:

output = IOBuffer()
temp = IOBuffer()
buffer_redirect_task = @async begin
    write(temp, pipe)
    temp_data = take!(temp)
    write(output, temp_data)
    write(default_stdout, temp_data)
end

This seems to capture the data from the pipe while also passing it through the normal stdout.

Is this a good idea, or does this have the potential to block something or slow things down at a low level? If there's an expert on the IO internals that can sign off on this, I can easily build that into a full PR.

@goerz
Copy link
Member Author

goerz commented Jan 10, 2024

This might work, too, and avoid the allocation of temp_data?

output = IOBuffer()
temp = IOBuffer()
buffer_redirect_task = @async begin
    n_bytes = write(temp, pipe)
    seek(temp, 0)
    write(output, read(temp, n_bytes))
    seek(temp, 0)
    write(default_stdout, read(temp, n_bytes))
end

@goerz
Copy link
Member Author

goerz commented Jan 11, 2024

Ugh… neither of these actually works. I should have tested it on a longer-running calculation to start with. It seems like the writing to default_stdout gets buffered until the task ends. I've tried adding a flush(default_stdout), too.

Update: this one works better:

bufsize = 128
buffer = Vector{UInt8}(undef, bufsize)
buffer_redirect_task = @async begin
    while !eof(pipe)
        nbytes = readbytes!(pipe, buffer, bufsize)
        data = view(buffer, 1:nbytes)
        write(output, data)
        write(default_stdout, data)
    end
end

@goerz goerz changed the title Add a tee option Add a pass_through option Jan 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants