-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
proposal: os: File.IsTerminal #28572
Comments
At one time we discussed having a golang.org/x/terminal package to provide some more-or-less generic terminal handling capabilities. I wonder if |
One thing I want it for is to let protoc-gen-go print an error if it's invoked interactively. There's a progress bar library used fairly extensively inside Google which alters its output depending on whether it's writing to a terminal. Looking through imports of the existing package would presumably find more uses. A full terminal package would be nice, but I'd hate to make the perfect the enemy of the good. Plus, not all cases need a full terminal library. |
As for what you can do with just this function: I think it might be possible to write a full curses library using only existing functions in the os package--with the exception of this one. |
I agree that just knowing if a file is a terminal can be useful on its own. I currently use https://godoc.org/golang.org/x/crypto/ssh/terminal#IsTerminal, like:
If this is simple enough to add and maintain, my vote is in favor of adding this to the standard library. |
I think this should be simple enough to add by adding a copy of import "internal/syscall/unix"
func (f *File) IsTerminal() bool {
_, err := unix.IoctlGetTermios(f.Fd(), unix.IoctlReadTermios)
return err == nil
} For windows everything that is needed is already in func (f *File) IsTerminal() bool {
var st uint32
err := syscall.GetConsoleMode(syscall.Handle(f.Fd()), &st)
return err == nil
} I'm not sure about plan9. func IsTerminal(fd int) bool {
return false
} |
Looking at https://plan9.io/sources/plan9/sys/src/ape/lib/ap/plan9/isatty.c, I think the following might work for plan9: func (f *File) IsTerminal() bool {
return strings.HasSuffix(f.name, "/dev/cons")
} |
Why not print the error always? The main objection I have to isatty is programs that change behavior based on whether they are run on a tty. If you think protoc-gen-go should be invoked with a pipe you could always check that (os.Stdin.Fstat). |
Timed out in state WaitingForInfo. Closing. (I am just a bot, though. Please speak up if this is a mistake or you have the requested information.) |
The error in this case is "don't run this interactively", so printing the error always isn't the right thing. For the case of Another common use of isatty where that would not, however, suffice is to determine whether to colorize or otherwise add additional formatting to output; in that case, you really do need to distinguish between a terminal and a file/pipe/any other destination. |
@gopherbot tsk tsk. |
While I generally agree with @rsc that programs shouldn't change their behavior depending on whether they're run interactively, I think developers will find a way to do that in any case. Worse even, they'll pull in I think trying to discourage the use of One use case which I think is reasonable is whether or not to print a prompt in a shell-like program. For example:
I maintain such a program, and it's a shame that the only non-std dependency I pull is |
We looked for a little while at maybe having a FileInfo mode bit, but the bit seems expensive to calculate. For this:
Would it suffice to stat os.Stdin and check for ModeCharDevice? |
That's definitely not the same thing as |
Just a proof of concept implementation for golang#28572, proposal needs to be decided first. DO NOT REVIEW DO NOT SUBMIT Change-Id: I360c6a01650629e938f9454cb5180f45c67b82b7
Per discussion with @golang/proposal-review, if you want this function, it's likely you want much more (color libraries, ncurses helpers, etc.) and in that case you should rely on those packages to do this for you. It's unusual to want |
Did anyone actually check this empirically? Looking at my own work, I've used IsTerminal for about 8 different tools and only one of them uses any kind of auxiliary terminal package (for readline functionality). Edit: additionally, those all have a dependency on golang.org/x/crypto/ssh/terminal which they otherwise wouldn't need, which seems silly. |
I have a philosophical objection to most uses of isatty. For example, ls changes its output whether it's writing to a pipe or not, which means you can't see what its output looks like to a pipe by running it on a terminal. One learns this eventually, but I was offended by the property when BSD did this, and it remains surprising. I doubt many share my view. |
Add an
IsTerminal
method toos.File
, equivalent to the Unix stdlibisatty()
:The
github.com/mattn/go-isatty
package provides an equivalent function. It has 476 imports and 254 stars, which indicates that there is a fair degree of demand for this feature. I think the standard library should provide it.The text was updated successfully, but these errors were encountered: