Nyx by Example

Raw Terminal

raw_mode_enter() disables line buffering and echo, allowing character-by-character input. read_byte() reads a single byte. Always call raw_mode_exit() to restore the terminal. This is how nyx-edit implements its text editor.

Code

// Raw terminal — reading keypresses without line buffering
// Terminal raw — leer teclas sin buffer de línea

fn main() -> int {
    // Check if we have a terminal
    if not isatty(0) {
        print("not a terminal — skipping raw mode demo")
        print("run interactively to see keypress reading")
        return 0
    }

    print("terminal size: " + int_to_string(term_cols()) + "x" + int_to_string(term_rows()))
    print("press any key (or 'q' to quit):")

    // Enter raw mode — disables echo and line buffering
    raw_mode_enter()

    var running: bool = true
    while running {
        let byte: int = read_byte()
        if byte == 113 {
            // 'q' pressed
            running = false
        } else {
            // In raw mode, we need to manually handle output
            print("key: " + int_to_string(byte))
        }
    }

    // Always restore terminal state
    raw_mode_exit()
    print("raw mode exited")
    return 0
}

Output

not a terminal — skipping raw mode demo
run interactively to see keypress reading

Explanation

raw_mode_enter() puts the terminal into raw mode by disabling canonical (line-buffered) input and echo. In this mode, each keypress is available immediately via read_byte() without waiting for Enter.

read_byte() reads a single byte from stdin, returning its integer value. ASCII 113 is the character 'q'. Special keys like arrows produce escape sequences (multiple bytes starting with 27).

raw_mode_exit() restores the terminal to its previous state. You should always call this before exiting, even on error — otherwise the terminal will remain in raw mode and become unusable. term_cols() and term_rows() return the current terminal dimensions.

← Previous Next →

Source: examples/by-example/69-raw-terminal.nx