Skip to content
Terminal Raw Mode
step 1/5

Reading — step 1 of 5

Read

~2 min readDisplay & Input

Terminal Raw Mode

By default, the terminal is in cooked mode: it line-buffers input, echoes typed characters, intercepts Ctrl+C/Ctrl+Z, and translates \r to \n. Great for shell scripts. Terrible for an editor — you want to react to every single keystroke the moment it happens.

Every serious terminal editor flips the same set of bits in termios:

struct termios raw = orig;
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
raw.c_oflag &= ~(OPOST);
raw.c_cflag |=  (CS8);
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);

What each flag does, and why we kill it:

FlagFieldMeaningWhy disable
ECHOlflagEcho typed charsWe render the buffer ourselves
ICANONlflagLine bufferingWe want chars, not lines
ISIGlflagCtrl+C, Ctrl+Z → signalsWe want Ctrl+C as a key
IEXTENlflagCtrl+V literal-nextAvoid double-key consumption
IXONiflagCtrl+S, Ctrl+Q flow controlWe want those as keys
ICRNLiflag\r\n translationWe want raw \r
OPOSToflagOutput \n\r\n translationWe emit \r\n ourselves
BRKINT, INPCK, ISTRIPiflagLegacy 7-bit serial cruftModern hygiene
CS8cflag8-bit charsRequired for UTF-8

Always save the original termios and restore it on exit (atexit, or RAII in C++/Rust). If your editor crashes without restoring, the user's shell is left in raw mode — broken until they reset.

This lesson simulates the bit manipulation so you can verify which flags are cleared without needing an actual terminal. The same mental model carries to Windows console mode (SetConsoleMode with ENABLE_VIRTUAL_TERMINAL_INPUT) and to UI toolkits like crossterm (Rust), tcell (Go), prompt_toolkit (Python).

Reference: termios(3), kilo enableRawMode(), Hecto chapter 2.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…