entering text in the terminal is complicated https://jvns.ca/blog/2024/07/08/readline/
Entering text in the terminal is complicated

Entering text in the terminal is complicated

Julia Evans

someone in the replies elsewhere pointed out that Ctrl+J = 10 in the ASCII table = LF ("line feed") = Enter (because J is the 10th letter of the alphabet)

so Ctrl+J is the same as pressing enter

which I don't have any practical use for but is kind of cool

(edit: some corrections in this reply: https://pgh.social/@ben/112752235264922484)

Ben Cox (@[email protected])

@[email protected] This isn't quite right in a few ways. LF is decimal 10, ascii 0x0a. It is 10 because it's the 10th letter of the alphabet, though. But it's not the same as pressing enter except in cooked tty modes, where the terminal driver converts the return key (^M, \r, ASCII 13 / 0x0d) to a newline (^J, LF, 10/0xa) which your program then sees as its input.

pgh.social
also someone elsewhere left a comment like "I CAN’T BELIEVE IT TOOK HER 15 YEARS TO LEARN BASIC READLINE COMMANDS". those comments are very silly and I'm going to keep writing “it took me 15 years to learn this basic thing" forever because I think it's important for people to know that it's normal to take a long time to learn “basic" things

@b0rk haha yeah I have been doing this a lot longer than 15 years and this is the first time I have really _thought_ about how terminals work

one thing I don't get is: If ^W isn't handled by readline (or friends), what *is* doing it? How do backspace and word-backspace work?

How... does character entry work at all??

@njvack honestly I didn't dig into that in the post largely because I don't understand it well either, I think it's the "unix terminal driver", but like what is that?? how does it work? it's a weak point for me and I'm hoping to understand it at some point
@b0rk @njvack It helps to remember that a tty used to just be an RS-232 serial line. A character would come in, an interrupt would get generated, and the tty handler would read the char from a register and put it in a buffer for the attached program to eventually read(). That's raw mode. Cooked is when the driver kept a line-buffer, and would interpret chars as they came over the wire - printable? echo and place in buffer; ^J?, send buffer on to consumer to read(), ^U, kill buffer and start over
@b0rk @njvack ^H? send back '^H ^H' to erase char on terminal, and move the head of the buffer back one. Other chars like ^C, ^Z, ^\, etc would instead send a signal to the process group attached to that tty and the signal handler would be invoked or the process killed.
@b0rk @njvack Then X11 came along and we needed a tty-like abstraction to attach these newfangled terminal windows to processes, because all the I/O and job control was wired to talk to a tty-shaped device. And some new side channels were added (e.g. SIGWINCH). So there are a ton of ioctls() to talk to the driver and control/interrogate exactly what kind of tty it really is.
@b0rk @njvack Oh yeah, you also needed ptys for telnet/rlogin/ssh-like services. And the tty driver was already hellishly complex even before GUIs entered the picture. Tons of respect to anyone who unpeels the onion in the modern era - so many moving parts.
@b0rk @njvack One other thing that was an A-ha! moment for me back in the day was learning that stty uses an ioctl() to determine the tty behind stdin, so you can redirect from another tty (assuming you have permission) to see its settings. So, assuming /dev/ttys000 is a different window, I can 'stty -a < /dev/ttys000' and see how the flags change between cat, bash, and vim for example.
@gomijacogeo huh that stty trick is great