4 ms·
> This is my first time hearing of this functionality. I was also surprised when I discovered this. IMO this should be used everywhere but I've rarely seen it.
by _rmcx 4y ago
> This is my first time hearing of this functionality.
I was also surprised when I discovered this. IMO this should be used everywhere but I've rarely seen it.
> How does it work with buffered stdout? For example, if you wanted to colour a single word?
This is not affected by buffering. What matters is what the output device/file/stream gets eventually.
How coloring a single word works depends on how you use it.
You can do
write_and_flush_to_dev_tty(BEGIN_RED_TEXT);
write_and_flush_to_dev_tty("word");
write_and_flush_to_dev_tty(END_RED_TEXT);
The write_and_flush_... pseudo functions are written in this way just to make it clear that I'm describing the behavior when the output gets the bytes immediately. I don't mean that you should use /dev/tty like this.
Redirection won't have any effect on these lines of code. You always get a red "word" on the terminal. The redirection target doesn't get anything.
write_and_flush_to_dev_tty(BEGIN_RED_TEXT);
write_and_flush_to_stdout("word");
write_and_flush_to_dev_tty(END_RED_TEXT);
When directly used on a terminal, you get a red "word" on your terminal, but when
you do redirection, the target only gets plaintext "word".
write_and_flush_to_dev_tty(BEGIN_RED_TEXT);
write_and_flush_to_stdout("word");
write_and_flush_to_stdout(END_RED_TEXT);
When redirected, your terminal stays red after the red "word" is printed, and your redirection target gets an extra escape code.
When stdout is a tty, /dev/tty is the same as stdout, so a write that goes to one goes to the other. In this case, even if you don't flush after write immediately it's likely not a problem. Still it's something that the developer should pay attention to.
-------------
Edit:
Please ignore all the pseudocode examples. They don't convey what I wanted to express.
Just use /dev/tty in the same way as how you would use stdin/stdout/stderr that is connected to a terminal. Only difference is that it is a rw device that can be used for input and output at the same time.
- hoseja 4y agoSo, the answer to "How does it work with buffered stdout?" is, "It doesn't, you have to keep flushing."
- geocar 4y ago> write_and_flush_to_dev_tty(BEGIN_RED_TEXT),write_and_flush_to_stdout("word"),write_and_flush_to_dev_tty(END_RED_TEXT); This isn't guaranteed to be serialized: Someone trying to log the output of your application might try: | tee /dev/tty | logger ... or they might be running under kubernetes/docker (which does much the same thing). I suggest the following: 1. If fd 0 and fd 1 are both ttys (isatty), and they point to the same tty (ttyname) then use it a tty (like your first example) 2. If fd 1 is not a tty, and fd 0 is a tty, write plaintext to fd 1. The user wants to filter output. 3. If neither fd 0 or 1 is a tty, write twice: do interactive stuff and send your vt-sequences with the text embedded to /dev/tty and a plaintext copy to fd 1. Now the user doesn't need the extra tee, and we no longer need to worry about synchronisation. Users don't typically (meaningfully) grep interactive applications, so I think it's a good compromise for interactive servers and tuis. But if you're not reading input or doing absolute cursor movement, and you just want some spicy log lines, I don't think you should be doing any of this fiddling: Just write sequences to stdout if it's a tty (or if the user specifically tells you to). I also recommend checking for $NO_COLOR in the environment and honouring the users wishes here: Some users are colourblind so this represents a real accessibility issue for them. One of the advantages of ncurses/terminfo is you get some accessibility features you might not have known you needed.
- sph 4y agoFlushing once at the end of every word is better than flushing every time you write, because at that point you might as well disable buffering.
- trasz 4y agoFWIW, all this stuff above about /dev/tty is absolutely wrong.