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.
@gomijacogeo @b0rk I think the thing I need to keep remembering is that at some point, ... something (I'm not 100% sure what — the tty handler? readline?) is telling _my terminal emulator_ to do something with the characters
@njvack @b0rk Yeah, it was a lot simpler 40+ years ago where each component was a separate, tangible box connected by wires. Made it easy to keep track of what was done where. A modern terminal emulator, on one side talks to the window system and sees keypress events and does advanced font rendering. On the other side, it talks to a pty which is an abstraction of that ancient RS-232 line and is mostly a serialized byte stream that the kernel then treats as input and output.
@njvack @b0rk If the tty is in cooked mode, those simple tasks - echoing, ^H, ^W, etc are done by the tty driver. In raw or cbreak (like raw, but still looks for things like ^C ^Z ^\ etc), then it is the consuming program (eg readline, vim, etc) that reads chars and then decides what to send back to the tty and then to the emulator to be displayed (usually lots of escape codes to handle positioning along with the one or two chars to actually display).