Now you know why I get unreasonably grumpy when an app doesn’t support the standard C-a/C-e keys (cough cough, Firefox Linux). 35 years of muscle memory is a real hurdle.
I feel the same when it jumps to the beginning of something, rather than doing some form of select-all :) We need a standard, simple, and supported (ambient / environmental) way for programs to be given commands alongside keystrokes, so the user can have their preferences in one place rather than having to configure every different thing we use.
i have implemented readline emulation independently on multiple occasions, and am rather annoyed about the fact. once was for a work thing in @adam_d_ruppe’s text library (https://github.com/adamdruppe/arsd/pull/268 i remember we raced on it—oops), once for my nethack fork (https://github.com/moon-chilled/slashem9/blob/master/src/readline.c it’s a decades-longstanding pain point and was trivial to implement—i did a bunch of stuff like that :\—i have no idea why no one had done it already). might have been more instances i forget lol. also stupid tty state machines even more times—awful, awful
also some vi/vim-ish stuff but more composable on better substrata which i’m more proud of as an actually worthwhile/novel project, though not complete-usable and a bunch of the details are crap so mehh
About the time you opened that PR, i got a complaint from a user that some of those things didn’t work and I didn’t even know the controls existed. Been a bash user for a long time, but never used these. I recall noticing ctrl+a just because I go to select all and the cursor jumps instead… but if I triggered most the others, it was just frustration. Like the ctrl+r history search is so…. just weird to me, that if I did try to use it I’d just get lost and mess up my input anyway. (You’ll find that my library handles history search and tab complete slightly differently than gnu readline, with history search using an interactive highlight and tab complete aligning text so you can quickly scan to see the next key to try, and also has mouse support if you use my custom terminal emulator, since I like clicking on things. tbh readline is a lot better than the default input, but i still don’t think it is especially great)
Anyway, I sympathize with the author of this post not knowing about much of this stuff for a long time, since I didn’t either.
also stupid tty state machines even more times—awful, awful
yeah, the more ive worked with linux (edit: and mac and bsd etc.) terminals, the more i dislike them. implementing that client api library was enough pain, then implementing my own emulator showed me it isn’t much better on the other side either, so much weird stuff.
no yeah for arsd.terminal somebody brought it up, and it had been bugging me anyway so i just went ahead and started implementing it; i was just confused about nethack
history search
same. i’ve figured out how to work with it, more or less, but it’s not smooth and it still mystifies me and i’m eternally frustrated by the fact that i’m sure i’m doing some things suboptimally (the alternative, that there’s no smoother way to do the things i do, would be even worse)
A friend and I once tried to modify readline so that it would go through curses instead of messing directly with the terminal, thus allowing readline to work with a curses-based app. It worked great, but it was much too messy to have any hope of being accepted as a code change. Doing it properly would have required a major rewrite of readline. (Though I’ve no doubt readline would have been originally written to work with curses had it been birthed from anywhere other than within a shell.)
I’ve heard of one person to made readline work with curses by implementing an entire virtual terminal (emulating a VT52, if memory serves) for readline to use, and then duplicated its final output to their curses display. That struck me as incredibly heavyweight, but it was a way to get readline to work with curses without rewriting it.
it took me maybe 15 years of using the terminal every single day to get used to using Ctrl+A to go to the beginning of the line (or Ctrl+E for the end)
How to spot a user of a keyboard “blessed” by the absence of those useless Home and End keys that take up all the valuable space. :-)
This, along with many other gotchas like not being able to delete words with Ctrl+Delete or Ctrl+Backspace, was why I could never get used to a Mac.
Interestingly, on Windows, the system’s read line function has built in history, completion, and some degree of editing (the Windows implementation is a bit weird, but it is there), and I think the OS on linux should provide it by default too. When the terminal is in cooked mode, you do get a little bit of processing - the backspace key at least usually (but not always, i do hate the whole unix terminal world) works, but the arrows generally don’t… and I don’t think it has to be that way. Make fgets call out to readline if the input is a tty in cooked mode, an there you go, things just work by default.
It would have been nice if some time around 1980 unix’s cooked terminal mode had been ripped out of the kernel and moved into libc stdio. That way it could have been integrated with curses and grown in capabilities as computers got bigger, instead of remaining a fossil of the paper teletype era.
Kernel interfaces are hard to change so it’s much easier to experiment with different interaction models if the kernel isn’t in the way. That’s why everything uses raw mode. And libc doesn’t have to be part of this: we were talking about stdio and libc is where stdio lives, but libcurses and libreadline are separate.
The in-kernel version is, for the linux case, around 130 thousand lines of code, most of which gains nothing and suffers hard from being in the kernel. That’s about the size of the scene-graph/input/drawing/protocol parts of Xorg. It is among the worst parts of the kernel code base, riddled with TODOs and FIXMEs and changing anything breaks something. This is the support structure before the layer of your regular terminal emulator kicks (with xterm at 96kloc) before the support of ncurses (250kloc) before the support of readline (55kloc).
There are systems on which the default readline config doesn’t make Ctrl-LeftArrow/RightArrow do the things mentioned in the article, or they don’t treat some non-whitespace characters as word separators (I find it’s useful to treat slashes as such). Slapping the right incantation in .inputrc helps. Don’t have it on hand right now though.
Now you know why I get unreasonably grumpy when an app doesn’t support the standard C-a/C-e keys (cough cough, Firefox Linux). 35 years of muscle memory is a real hurdle.
I feel the same when it jumps to the beginning of something, rather than doing some form of select-all :) We need a standard, simple, and supported (ambient / environmental) way for programs to be given commands alongside keystrokes, so the user can have their preferences in one place rather than having to configure every different thing we use.
i have implemented readline emulation independently on multiple occasions, and am rather annoyed about the fact. once was for a work thing in @adam_d_ruppe’s text library (https://github.com/adamdruppe/arsd/pull/268 i remember we raced on it—oops), once for my nethack fork (https://github.com/moon-chilled/slashem9/blob/master/src/readline.c it’s a decades-longstanding pain point and was trivial to implement—i did a bunch of stuff like that :\—i have no idea why no one had done it already). might have been more instances i forget lol. also stupid tty state machines even more times—awful, awful
also some vi/vim-ish stuff but more composable on better substrata which i’m more proud of as an actually worthwhile/novel project, though not complete-usable and a bunch of the details are crap so mehh
About the time you opened that PR, i got a complaint from a user that some of those things didn’t work and I didn’t even know the controls existed. Been a bash user for a long time, but never used these. I recall noticing ctrl+a just because I go to select all and the cursor jumps instead… but if I triggered most the others, it was just frustration. Like the ctrl+r history search is so…. just weird to me, that if I did try to use it I’d just get lost and mess up my input anyway. (You’ll find that my library handles history search and tab complete slightly differently than gnu readline, with history search using an interactive highlight and tab complete aligning text so you can quickly scan to see the next key to try, and also has mouse support if you use my custom terminal emulator, since I like clicking on things. tbh readline is a lot better than the default input, but i still don’t think it is especially great)
Anyway, I sympathize with the author of this post not knowing about much of this stuff for a long time, since I didn’t either.
yeah, the more ive worked with linux (edit: and mac and bsd etc.) terminals, the more i dislike them. implementing that client api library was enough pain, then implementing my own emulator showed me it isn’t much better on the other side either, so much weird stuff.
no yeah for arsd.terminal somebody brought it up, and it had been bugging me anyway so i just went ahead and started implementing it; i was just confused about nethack
same. i’ve figured out how to work with it, more or less, but it’s not smooth and it still mystifies me and i’m eternally frustrated by the fact that i’m sure i’m doing some things suboptimally (the alternative, that there’s no smoother way to do the things i do, would be even worse)
A friend and I once tried to modify readline so that it would go through curses instead of messing directly with the terminal, thus allowing readline to work with a curses-based app. It worked great, but it was much too messy to have any hope of being accepted as a code change. Doing it properly would have required a major rewrite of readline. (Though I’ve no doubt readline would have been originally written to work with curses had it been birthed from anywhere other than within a shell.)
I’ve heard of one person to made readline work with curses by implementing an entire virtual terminal (emulating a VT52, if memory serves) for readline to use, and then duplicated its final output to their curses display. That struck me as incredibly heavyweight, but it was a way to get readline to work with curses without rewriting it.
[Comment removed by author]
Good to learn about
rlwrap, that should make the OCaml REPL tolerable.How to spot a user of a keyboard “blessed” by the absence of those useless Home and End keys that take up all the valuable space. :-)
This, along with many other gotchas like not being able to delete words with Ctrl+Delete or Ctrl+Backspace, was why I could never get used to a Mac.
Interestingly, on Windows, the system’s read line function has built in history, completion, and some degree of editing (the Windows implementation is a bit weird, but it is there), and I think the OS on linux should provide it by default too. When the terminal is in cooked mode, you do get a little bit of processing - the backspace key at least usually (but not always, i do hate the whole unix terminal world) works, but the arrows generally don’t… and I don’t think it has to be that way. Make fgets call out to readline if the input is a tty in cooked mode, an there you go, things just work by default.
It would have been nice if some time around 1980 unix’s cooked terminal mode had been ripped out of the kernel and moved into libc stdio. That way it could have been integrated with curses and grown in capabilities as computers got bigger, instead of remaining a fossil of the paper teletype era.
Hm why would you want that though? Wouldn’t you rather want the in-kernel version to get expanded? Lots of software doesn’t use the system’s libc
Would I want curses in the kernel?????
Kernel interfaces are hard to change so it’s much easier to experiment with different interaction models if the kernel isn’t in the way. That’s why everything uses raw mode. And libc doesn’t have to be part of this: we were talking about stdio and libc is where stdio lives, but libcurses and libreadline are separate.
The in-kernel version is, for the linux case, around 130 thousand lines of code, most of which gains nothing and suffers hard from being in the kernel. That’s about the size of the scene-graph/input/drawing/protocol parts of Xorg. It is among the worst parts of the kernel code base, riddled with TODOs and FIXMEs and changing anything breaks something. This is the support structure before the layer of your regular terminal emulator kicks (with xterm at 96kloc) before the support of ncurses (250kloc) before the support of readline (55kloc).
There are systems on which the default readline config doesn’t make Ctrl-LeftArrow/RightArrow do the things mentioned in the article, or they don’t treat some non-whitespace characters as word separators (I find it’s useful to treat slashes as such). Slapping the right incantation in
.inputrchelps. Don’t have it on hand right now though.