For better or for worse, unix simply wasn't designed that way. Changing this now would mean breaking so many assumptions hard-coded into a vast majority of unix applications. Considering how complex unix TTYs are, there is practically zero chance this can be done transparently to existing programs. It's going to need a redesign of the I/O system, at which point, we might as well call this new system Plan10.
I also think there are problems with the approach itself. Making the shell sit between programs would complicate the interaction between various programs and introduce new bottlenecks in the shell. Additionally, it likely won't be an improvement over the current situation. Rather, it would just introduce another layer of incompatibility in the shell that programs would have to deal with.
I did this originally with my shell and it's actually not as painful as you'd think. Most CLI tools don't care where fd 0, 1 and 2 are coming from / going to (after all, if you're piping those programs then they're no longer writing to the TTY anyway).
The only programs that cause an issue are tools that send ANSI escape sequences (eg for ncurses) and check if STDOUT is a TTY before sending them. In those cases you'll just get a message written saying something along the lines of "STDOUT is not a TTY".
In theory you could write another workaround to fix that workaround but it was a horrible kludge that I didn't like in the first place so ended up finding another solution (which isn't as elegant as the zsh / fish fix and I'll soon be adapting that into my own shell too).
> The only programs that cause an issue are tools that send ANSI escape sequences (eg for ncurses) and check if STDOUT is a TTY before sending them.
Sure, but aren't those programs the whole point of having sophisticated terminal emulators? If plain streams of text was all we cared about for CLI applications, it would indeed make things a lot easier. So much easier, in fact, that we can dump our current terminal emulators in favor of a more simple alternative without ever having to complicate the shell. But since people do care about terminal UIs, this isn't a realistic solution.
> Sure, but aren't those programs the whole point of having sophisticated terminal emulators?
What we currently have isn't sophisticated terminal emulators. It's a buggy superset of hundreds of kludges due to 60s years of legacy. I mean there's a lot I do love about the design but there's a lot to legitimately dislike as well.
> If plain streams of text was all we cared about for CLI applications, it would indeed make things a lot easier. So much easier, in fact, that we can dump our current terminal emulators in favour of a more simple alternative without ever having to complicate the shell.
The shell isn't the complication here. The shell is just a program launcher. The real issues with terminals is:
- Formatting is inlined with the data stream.
- There isn't any type information in pipes (it is just a raw byte stream) so applications can't easily do context sensitive processing.
- ASCII isn't just a text format but also a data format (there's ASCII characters for tables and records) and flow control (EOF) and job control (^c, ^z).
- It's that responsibility for all of this is divvied up between the TTY driver (in Linux's case, the kernel), the terminal emulator, and any user space applications reading and writing to their respective file descriptors.
- Terminals were never built to be API driven and while there are some interactive ANSI escape sequences they're not widely supported by terminal emulators. So from a shell or tty perspective, the terminal is a black box
- Plus since file descriptors are literally files and TTYs are literally files, it means actually any other process can write to the TTY even if they're not part of the shell's process group (hence why tools like `wall` can exist). So even if the shell could keep track of what was in STDOUT of the processes it spawned, it can't possibly know if anyone else has written to that same TTY.
There some ingenious design in Linux terminals but there are soooo many rough patches thrown in too.
> But since people do care about terminal UIs, this isn't a realistic solution.
Right, but I was never suggesting people don't care about terminal UIs nor that shells don't offer a valuable function. In fact the opposite is true: I've written my own shell because I thought I could create a better UI/UX than Bash.
It does kind of "sit between the program and the terminal," but it's not much useful in the context of this discussion. Going back to the starting point, the problem is that programs and terminal emulators have very limited means of communication. This is why a seemingly straightforward feature can't be implemented by the shell in a straightforward manner.
screen is just another terminal emulator and nothing more. While screen is undoubtedly a useful program, it offers no additional means to solve the problem.
I also think there are problems with the approach itself. Making the shell sit between programs would complicate the interaction between various programs and introduce new bottlenecks in the shell. Additionally, it likely won't be an improvement over the current situation. Rather, it would just introduce another layer of incompatibility in the shell that programs would have to deal with.