yuin / gopher-lua

GopherLua: VM and compiler for Lua in Go
MIT License
6.3k stars 655 forks source link

Allow redirecting stdout with io.write #349

Open drognisep opened 3 years ago

drognisep commented 3 years ago

Please answer the following before submitting your issue:

  1. What version of GopherLua are you using? : github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9
  2. What version of Go are you using? : go version go1.17.1 windows/amd64
  3. What operating system and processor architecture are you using? : Windows 10 20H2 19042.1320, Intel(R) Core(TM) i7-10875H CPU @ 2.30GHz
  4. What did you do? : Redirected os.Stdout to the write side of an os.Pipe
  5. What did you expect to see? : I expected print and io.write to print to the redirected stream.
  6. What did you see instead? : print prints to os.Stdout (using fmt.Print), but io.write does not. I would expect these functions to be consistent in how they select their output stream.

I'm trying to wrap gopher-lua into a graphical script runner with Fyne along with an output panel to show the result of the script. I've observed that Lua-side print writes to os.Stdout no problem because it uses fmt.Print, but io.write instead writes to the application's original stdout stream regardless of the value of os.Stdout. To support this functionality it would be nice if both print and io.write (and other I/O functions) used Go-side os.Stdout, os.Stderr, os.Stdin streams so they can be easily redirected to the graphical component. The alternative is generating a new executable and running it in a new process to redirect streams every time the user changes the script in the UI, which would be a huge pain.

ZenLiuCN commented 3 years ago

335 use overrid global function to redirect to anything you like.

drognisep commented 3 years ago

@ZenLiuCN Of course I can override if need be. Shouldn't it be consistent in the base implementation? What is the benefit of not having both reference the same streams in the same way?

I think linking both of them to Go's os.* streams would make this use-case simpler for people and make the change to redirect much more consistent with gopher expectations without having force people to dig into the internals and override global functions. Is there something I'm missing?

ZenLiuCN commented 3 years ago

@ZenLiuCN Of course I can override if need be. Shouldn't it be consistent in the base implementation? What is the benefit of not having both reference the same streams in the same way?

I think linking both of them to Go's os.* streams would make this use-case simpler for people and make the change to redirect much more consistent with gopher expectations without having force people to dig into the internals and override global functions. Is there something I'm missing?

so why not just try to make a pull request?

drognisep commented 3 years ago

Maybe I misunderstood. Is this not being maintained anymore?

ZenLiuCN commented 3 years ago

I do not know. just been use this lib current days. ^_^

drognisep commented 3 years ago

Ah, okay. I don't have the time to prop up a lib with no maintainer. Thanks for the tip though @ZenLiuCN. :D

GwynethLlewelyn commented 2 years ago

I have a very similar issue: I'm running Lua scripts as part of a web server and want to capture the output to send it to a webpage (using SSE, WebSockets, or anything like that). The 'obvious' choice would be simply to redirect Lua's stdout to some Go stream and push that out to the HTTP stream (probably it may be even simpler than the code I'm writing; I'm adding some error checking, etc.). Sadly, GopherLua seems to simply send everything from print() to stdout, with no way to grab it. Is that so? I'm still looking through all the posted issues here to see if there is a way using the current codebase...

Oh, sure, I could simply override print(), but, in that case, I'd have to deal with all the syntactic sugar from Lua's own print(). I might more easily create my own pseudoprint() which just sends output... uh, somewhere where I can grab it (note that I'm using luar to make things much simpler, so I might not be able to delve as deep as I wish).

GwynethLlewelyn commented 2 years ago

Update: On another issue here, I've found something that would work in my case: https://github.com/xyproto/algernon/blob/34d3806bfa890e7f6296cc400e8fd51951cdc926/basic.go#L67

maja42 commented 2 years ago

Im maintaining a fork of this project since a few years, where I added the feature to optionally redirect stdin, stdout and stderr. All calls (even internal usages of stdout/stderr) are using those instead.

The streams can be overwritten in lua.Options, where I added the following fields:

// Options is a configuration that is used to create a new LState.
type Options struct {
    // <other fields>

    // Stdin stream. Defaults to os.Stdin
    Stdin io.ReadCloser
    // Stdout stream. Defaults to os.Stdout
    Stdout io.WriteCloser
    // Stderr stream. Defaults to os.Stderr
    Stderr io.WriteCloser
}

I'm using this fork in production for a few years now without any issues. If there's any interest, I'd be glad to provide a PR.

GwynethLlewelyn commented 2 years ago

Speaking strictly as an end-user of gopher-lua, I'd love to have your PR! Hopefully, @yuin is able to review it and add it to the main branch...