đŸ Archived View for tilde.team âș ~simonb âș termios.gmi captured on 2022-03-01 at 15:24:45. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
You can change the special character associated with each action! ^C and ^D and so forth are just the defaults.
$ stty eof '^E' $ stty intr '^K' $ cat this is some text this is some text ^E $ cat this is some more text^K $
Or from C:
struct termios ts; tcgetattr(STDIN_FILENO, &ts); ts.c_cc[VEOF] = 5; ts.c_cc[VINTR] = 11; tcsetattr(STDIN_FILENO, TCSAFLUSH, &ts);
A useful feature: REPRINT (^R) reprints the current line, leaving the previous contents onscreen as a reference. For example, say you mistype the start of a line:
$ cat >/tmp/a Tihs is some text
No problem: type ^R and ^U to start over, leaving the old contents visible as a reference.
$ cat >/tmp/a Tihs is some text^R^U this is some text ^D $ cat /tmp/a this is some text $
EOF (^D) doesnât do what I thought it did, something about âclosing standard inputâ or âsignalling EOFâ. Really it just flushes any active read(2) calls. Let me show you what I mean.
During normal operation the kernel handles line editing automatically, interpreting keys like DEL, ^W, and ^C without any code in userspace. When you press RET it adds a newline to the end and sends it off to anyone reading from your terminal.
If you press ^D instead of RET, the kernel still passes the line on! But this time, no trailing newline is added to terminate it. So ^D lets you send incomplete lines over to a program, if you wish to do so:
$ cat This is some text^DThis is some text
The first ^D passes âThis is some textâ to cat, which echoes that phrase back to the terminal.
Here's the important bit: pressing ^D at the start of the line gives cat a âlineâ of text with 0 bytes of content. This is almost universally interpreted as EOF:
If successful, the number of bytes actually read is returned. Upon reading end-of-file, zero is returned. Otherwise, a -1 is returned and the global variable errno is set to indicate the error.
You can see this in various libc implementations: musl, OpenBSD, even 7th Edition Unix.
But remember: ^D hasnât actually closed the file! It makes read() return 0, but *only once*. cat can keep reading from the terminal, if it wants to, and ed is one program that actually does this: ^D is like â.â or âqâ, depending on the context, and ed can keep reading commands after it.
$ ed file.c # Open file.c. 31253 # (file.c has 31253 bytes.) a # Append some text. /* CC0 */ ^D # End input mode. p # Print out the current line. /* CC0 */ ^D # Quit ed. ? # (file.c has unsaved changes.) ^D # Okay, quit without saving.
(However, notice that ed always exits after a couple of ^Ds. This is by design: ed should handle real EOF gracefully when itâs reading from an ed script. zsh does a similar thing with the IGNORE_EOF option.)
âŻâŻâŻâŻ
Written by Simon Branch <simonmbranch@gmail.com> in February 2022. Licensed under CC0.