8 ms·
Terminals Are Weird
- userbinator 12y ago...and here is a good historical perspective on the whole subsystem, which could explain why terminals are weird: http://www.linusakesson.net/programming/tty/ http://www.linusakesson.net/programming/tty/
- klibertp 12y agoNot only why, but also how they work in some more detail. Only after reading this I understood, for example, why C-u works in the terminal even if right/left arrows do not in this particular moment (like after using read builtin or cat without arguments). Very good read.
- jacobolus 12y agoThis, like many things, is a case where many different problems get complected, because no one is able to step back and tweak every level of the stack to cleanly separate out the relevant models/abstractions. Ideally, a computer keyboard would be able to directly send both an arbitrary number of named control functions, and arbitrary unicode text (either as full strings or as code units one by one). Instead though, keyboards (in every existing keyboard protocol) send a very limited number of scan codes, and what to do with those is left entirely up to the operating system. Thus the operating system can’t just get a symbol from a foreign-language keyboard and know what to do with it, but needs to be put into a special mode depending on what keyboard is plugged in. If multiple keyboards are plugged in with different language layouts, too bad: at least one of them will not behave as expected. Then at every level of the software stack, from the low-level device drivers, up through operating system services, to end user applications (e.g. browsers or terminals) and then on to custom behavior running on those applications/platforms (like a webapp or whatever), everyone gets to take a whack at the meaning of the keyboard code. At each level, there’s logic which intercepts the keyboard signal coming in, digests it, and then excretes something different to the next layer. As a result, it’s almost impossible for application authors (much less web app / terminal app authors) to know precisely what the user intended by their keystrokes. And it’s almost impossible for users to fully customize the keyboard behavior, because at several of the levels user access is impossible or difficult (especially in proprietary operating systems, or in locked-down keyboard firmware e.g.), and even where users do have access, it’s very easy to make a minor change that totally screws something up at another level, because none of the relevant abstractions are clean. Furthermore, custom user changes at any of these levels are almost never portable across applications, operating systems, or hardware devices. Every change is tied to the specific hacks developed in a particular little habitat. Overall, a very disempowering and wasteful part of the computing stack.
- goldfeld 12y agoThat's a bleak outlook to have. Like the author said, you can always just go for graphical toolkits and ignore terminals. Whereas, embracing unix and terminals, I personally find it an empowering and frugal part of the computing stack: predictable, works everywhere, light and simple. Limiting factors can be a positive thing.
- jacobolus 12y agoI think you are misunderstanding me. I am not calling terminals disempowering. I am criticizing the keyboard handling (and general input device handling) at all levels of the computing stack from device firmware and drivers up through web or curses applications. As a user, it is effectively impossible to get the keyboard to behave the way I want (or even in a way that I can anticipate with some kind of mental model) in every context.
- jacobolus 12y agoAs a concrete example: the spacebar key has its behavior overloaded all over the place. Some people make their keyboard firmware turn holding down the spacebar into a modifier key. At the operating system level, modifier + spacebar often has a special meaning: for instance in OS X command + spacebar indicates "switch to the next available keyboard layout", but then later that shortcut was also adopted by the Spotlight search feature (recent versions of OS X change the keyboard layout shortcut to command-shift-space but for a few versions the shortcuts collided and the results were unpredictable). System-wide utility software (for instance Quicksilver) uses or at once point used command-space as a default shortcut to pop up its UI regardless of the current application. Then various applications want to interpret the spacebar in several ways, for example for activating a selected button or other UI widget, or for scrolling, or for entering a physical space character. Photoshop famously uses a held-down spacebar to switch the active tool to the grabber hand, with command-space switching to the zoom in tool and option-space switching to the zoom out tool; other design/image software followed Photoshop’s lead, but sometimes implements things a bit inconsistently, for example in Illustrator command-option-space is required for zoom out instead. In the browser, things really get gnarly, because the browser UI itself uses the spacebar for all three of scrolling (space = page down, shift-space = page up), activating UI widgets, and entering space characters in text fields, depending on the current context, and then certain in-browser applications/widgets try to reinterpret the spacebar, for example a video widget will interpret the spacebar as play/pause, or a game will interpret the spacebar as shoot or jump. All of these layers are clobbering each-other, so that existing software is already incompatible with defaults set at other levels of the stack. But as a user, if I try to make any changes to how one part works, I’m almost guaranteed to break something at another level. Perhaps worse, the application keyboard context often changes without making the change obvious to the user, so that moment by moment I often can’t predict precisely what will happen if I press the spacebar. (And this is not limited to the spacebar: enter, tab, arrow keys, and most other keyboard commands change their meaning based on the context in inconsistent and confusing ways. Once you get to the terminal, as explored in the original linked post, you get all kinds of other inconsistencies with certain keystrokes which only work in some contexts but not others, and various duplicate keystrokes which cannot be separately assigned, and so on. But these problems are not unique to terminals.)
- dllthomas 12y agoTerminals are weird. I welcome the various approaches to getting a shell homed somewhere else, though I've not yet found one I've really bought into.
- agumonkey 12y agoAll the devices from pre 80s era are 'funny' because they conflate everything inside the implementation.
- jacobolus 12y agoIt’s not like we’re doing any better with the client-side web development stack (to take one example). Building simple composable abstractions and systems is just really hard, and takes a lot of practice and refinement. Unfortunately, programmers don’t necessarily get much practice before their designs become the foundation on which everyone else needs to work (for example, there is very little emphasis placed on designing effective software abstractions in academic computer science programs), and there’s often no easy way to go fix the defects afterward.
- contingencies 12y agoThis is the most perceptive comment in the thread, IMHO.
- goldfeld 12y ago"If you do still want or need to make a terminal application that is interactive rather than just being a command-line tool, what is the best way to go about it? You should write it inside Emacs, using Emacs Lisp, and run it as an application by invoking Emacs to run the function that is the entry point for your application. This way you can have legacy terminal support to make use of ssh and tmux, by running Emacs in a terminal, and modern graphical support to display fancy graphics and use more keybindings, by running Emacs in a graphical environment." Though the latter point is interesting, I find the suggestion unexpected. Isn't curses-based applications a possibility for the author? Why would you limit your users to those that use Emacs, unless the application is just for you? I'm working on a ClojureScript on Node.js (i.e. instant boot) functional UI library[1] and I find it pretty empowering. I also kept the Node.js touchpoints very separate so I can soon provide a JS Canvas implementation so the same UI code runs on terminal and browser for free. I was suprised how easy it was to implement vi/Emacs-like sequence keybinds, with prefixes and all that. I'm really liking the ability to easily whip up terminal user interfaces for various simple and complex applications. 1: https://github.com/goldfeld/i9n https://github.com/goldfeld/i9n
- codezero 12y agoThe summary of this well written page is: If you do still want or need to make a terminal application that is interactive rather than just being a command-line tool, what is the best way to go about it? You should write it inside Emacs, using Emacs Lisp...
- philsnow 12y agoWasn't there a time when actual, serious apps were written using XULRunner ? This is not that different of a suggestion.
- coldtea 12y ago>Wasn't there a time when actual, serious apps were written using XULRunner? Not really. At least nothing to write home about. But in general what you mean I guess is some kind of runtime environment. Sure there are lots, but not that many for the Terminal and Emacs is not really a lightweight and proper option.
- pnathan 12y agoI was just thinking about this the other day. To do it, you have to develop a new protocol in order to separate out the control and data planes. I think it would be extremely useful and valuable to start on such a project, but I'm not sure how much interest such a thing would have. I certainly don't agree that Emacs Lisp is the appropriate development engine.
- dllthomas 12y ago"I'm not sure how much interest such a thing would have." I'd be phenomenally interested, although my involvement would be limited by the other demands on my time...
- ajuc 12y agoCouldn't that new protocol just be html subset?
- pnathan 12y agoNo. To clarify somewhat: html is a presentation language. That's not appropriate for either control or data planes by default. example- let's define the data plane as an associated list of byte-strings of u8 characters. This covers current common unix pipe usage on the terminal. If we include some lisp syntax for routing & choose to complect some control and data on the command line we then can compose: `cat thing (. stdout) wc -l ( (. stdout cat) (. sterr echo "error!")` But, fundamentally, the control plane needs to be asynchronous, so there needs to be a signal handler that a program can listen on that takes a stream of associated-lists with the rough form of: `(((keys . (control alt del)) (duration . 1000)) ((keys . (alt tab)) (duration . 10)))` the program listening needs to be able to register with its parent process that it gets a key stream. anyway. we can work out this system in some level of detail with different representations. The key point is that this needs to be just data addressable easily, without significant difficulty parsing. It also needs to be lossless by default and not dependent upon hacks like timeouts as part of its interface to its consumers. (n.b., it should allow adding as many bucky bits as a keyboard developer wants). now, if the terminal wants to formally specify as its interface that it takes all output streams keyed by "html-presentation" and render them as html, that seems like a very featureful possibility. I would not write that, but I could see others doing so.
- dllthomas 12y agoInteresting that there was no mention anywhere of termcap/terminfo or curses. In making a new terminal standard, you need some way of doing what the old ones did (or refusing to), but if you support some basic set of primitives and provide a terminfo file, a lot of the tooling should fall into place.
- RevolverOce 12y agotitle reminds me of : https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRPuVjeyi-SqjN7QskPCV4UodQEEsA7kav7rw1hCGjmVV4HHZFbPA https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcRPuVje...
- kazinator 12y agoTerminals aren't weird. It's just that they work by sending and receiving strictly characters. If you look into ASCII or Unicode, there is no Ctrl+Shift+I character, so such a thing cannot be transmitted. That's not quite the end of the story because terminals can certainly generate special escape sequences for certain keys, depending on the terminal type. For example, although there is also no ASCII character corresponding to the arrow keys, VT-100 type terminals can transmit the arrow keys somehow, so you can use them in text editors and shells. This is because they send a special sequence instead of a single character. For instance, left arrow is actually the three characters ESC[D. You can easily see this at the Bash prompt in your xterm or Gnome terminal or whatever VT100-type console you're using. Type Ctrl-V, and then hit your left arrow key. You will see ^[[D. In principle, your terminal could also turn Ctrl-Shift-I into some special escape sequence which an application could parse. Such a sequence just doesn't exist in the terminal protocol you are using, that is all. Moreover, your terminal emulator application probably steals some of these combinations for itself. Shift+PgUp is commonly used for scroll back these days, and so won't be sent into the terminal session even if there exists a code for it. The function keys have VT100 escape sequences, but some function keys are mapped already. In Gnome Terminal, F1 brings up help. But F2 sends the escape ESC[OQ escape sequence. If we go into Gnome Terminal "Edit/Keyboard Shortcuts" and remap help to some other key, we can then use F1 in the terminal: it sends the escape sequence: It is ESC[OP.
- dezgeg 12y ago> In principle, your terminal could also turn Ctrl-Shift-I into some special escape sequence which an application could parse. Such a sequence just doesn't exist in the terminal protocol you are using, that is all. A specification that allows all key combinations to be recognized by terminal applications does indeed exist: http://www.leonerd.org.uk/hacks/fixterms/ http://www.leonerd.org.uk/hacks/fixterms/ Sadly, very few apps use it. Vim for example doesn't, but maybe there is hope that NeoVim will: https://github.com/neovim/neovim/issues/176 https://github.com/neovim/neovim/issues/176
- ajross 12y agoTerminals are weird, but it's not because of the data stream. The real mind-bending weirdness is in the kernel tty layer, for historical performance reasons. Userspace apps weren't able to keep up with typing in the early days, so the kernel is expected to handle stuff like simple editting (^H) and line buffering. And it has to handle baud rate and uart settings, of course. And it has to trap "special" keys like ^C so that hung applications can be reliably terminated via a signal. And it has to detect dropped lines to free up the terminal for other users. And it still does all this nonsense even in a world where those use cases are all forgotten. Terminals are weird. (But no, there aren't any other good alternatives, so we just deal with it.)
- barosl 12y ago"Whether Alt+char is succesfully picked up by your terminal application is dependent on the quality of your connection." This! The most annoying behavior in my daily terminal usage. Whenever I encounter this problem, I feel like "gosh, someone must reinvent the entire stack." But I didn't know that mosh is able to process the sequence correctly. What a good boy. But doesn't this mean the official OpenSSH client is also capable of fixing the problem?
- yudlejoza 12y agoI totally don't buy the recommendation. If you're going to do something new, you better stop worrying about backward compatibility. ssh and tmux won't work? big effin deal. Those projects would need to grow up in order to keep up with the times. You can't be conservative like that if the goal is to right the wrongs and learn from past mistakes. The road is going to be bumpy but the light at the tunnel would be worth the travel. I say if the limited scancode thing is in the keyboard hardware then we need to fix the hardware itself as well. New keyboard standard that sends Ctrl/Shift/Alt as separate scancodes. Hell a completely programmable keyboard firmware sounds even better. Throw in some n-key rollover and now we're talking! I would like to see some convergence of terminal and windowing-system happening. I initially dreamt of a graphical terminal but then I thought why not go one step further and make it the main interface (so something in the middle of a graphical terminal and a tiling window manager). However I still need to carve out the details.
- dded 12y ago> ssh and tmux won't work? big effin deal So when I want to ssh into a remote machine, I don't use your new program, unless you've also written an ssh replacement. If I want virtual screens, I don't use your new program, unless you've also written a tmux (or screen) replacement. Et cetera. Your new terminal program is useless till you've replaced or updated "all" the programs that depend on traditional terminal behavior. And "all", in this case, is reasonably close to being literal. If you get 80% of what I need, it's not enough. And the last 20% will likely differ from person to person. And I'll need to replace my keyboard, too? I totally don't buy that you're not being tongue-in-cheek.
- dllthomas 12y ago"I would like to see some convergence of terminal and windowing-system happening. I initially dreamt of a graphical terminal but then I thought why not go one step further and make it the main interface (so something in the middle of a graphical terminal and a tiling window manager). However I still need to carve out the details." While I am skeptical about discarding (some amount of) backwards compatibility, I'm very interested in this. Feel free to shoot me an email.
- deleted 12y ago[deleted]
- blutgens 12y agoyour face is weird.
- Roboprog 12y agoWeird is a matter of perspective. I started programming, on terminals (mostly, for class work - some Apple/Commodore twiddling aside), in the early 80s. Learning about scan codes on PCs in the later 80s seemed complicated to me, because it wasn't what I was used to at first. If you are used to a remote device that sends and displays characters, then switch to local integrated devices which exchanges much lower level signals to be mapped in software, the new stuff seems strange. Whether or not it's better or worse depends, I guess.