go-isatty icon indicating copy to clipboard operation
go-isatty copied to clipboard

Allow to check a `io.Writer` instead of raw file descriptor

Open cardil opened this issue 2 years ago • 8 comments

The lib allows checking TTY versus a raw file descriptor. It would be convenient to allow checking of a given io.Writer instead.

Related https://github.com/mattn/go-colorable/issues/65

cardil avatar Feb 28 '23 12:02 cardil

Also: io.Reader.

dolmen avatar Mar 15 '23 09:03 dolmen

tty should always be checked with Writer.

mattn avatar Mar 15 '23 12:03 mattn

Why can't pass raw file?

mattn avatar Mar 15 '23 12:03 mattn

Why can't pass raw file?

When you can pass a io.Writer, you can also pass any type that implements it, file as well.

cardil avatar Mar 15 '23 14:03 cardil

You can do type assertion before pass to the function like:

isatty.IsTerminal(w.(*os.File).Fd())

mattn avatar Mar 15 '23 14:03 mattn

@mattn wrote:

tty should always be checked with Writer.

I disagree. I usually check if os.Stdin is a tty in programs that optionally accepts data on stdin. This allows to skip stdin or to show usage when the user didn't redirect stdin.

dolmen avatar Mar 22 '23 15:03 dolmen

The time that I had a look at this package I also thought: why not an io.Writer?

But after that initial thought, I realized that the current API is very appropriate because:

  1. checking for tty and applying wrappers to handle is something that must be done early in the program, usually in the main package, where you have access to raw os handles. The current API works fine for that use case. High level libraries (such as loggers) must instead work on abstractions such as io.Writer and it should not be their responsability to do dirty stuff like applying wrappers to OS handles.
  2. the fact that you need to have access to the raw file descriptors to use the functions of go-isatty IS a feature as it blocks bad uses of go-isatty deeply in libraries. It forces users of the API to design the program in a way and that is a good thing because calls to go-isatty are costly because of syscalls.
  3. adding a wrapper to allow easy access to io.Writer/io.Reader would just make it easy to use go-isatty incorrectly (for example on every call to a log method of a logger object) and that would be just bad for the whole Go ecosystem.
  4. the proposed wrappers for io.Writer/io.Reader can easily be written outside of go-isatty. Making them available in the go-isatty module brings no benefits compared to making them available is a separate package, but brings the drawback of 3.

dolmen avatar Mar 23 '23 08:03 dolmen

Thanks for your comments. I had the same issue as @cardil and was going to ask how to implement this.

Using isatty.IsTerminal(w.(*os.File).Fd()) is insane 😁 but it totally works 😮

And that's more than enough for me. My use case is simple: I just wish to check if I'm writing logs to a TTY or to a file, and use coloured output if it's a TTY. Many packages already do that; some don't, and so I have to check if the output is a TTY before using some of the features — but as @dolmen commented, this happens very early in main() and is just requested once.

GwynethLlewelyn avatar Aug 01 '23 00:08 GwynethLlewelyn