liveBook · Manning

Cbreak mode

As explained in Python Concurrency with asyncio

Cbreak mode is a terminal input mode that delivers keystrokes individually while retaining selected terminal handling such as interpretation of interrupt keys.

Cbreak mode delivers keystrokes to the application individually while retaining terminal interpretation of keys such as CTRL-C. It provides finer input control than cooked mode without requiring all raw-mode handling. section 8.4.1

Using cbreak mode requires the application to take responsibility for input behavior:

  • Enter the mode with Python’s tty.setcbreak function. section 8.4.1
  • Read one character at a time with read(1), store characters in an internal buffer, and echo them explicitly. section 8.4.1
  • Handle editing, screen placement, and asynchronous output so messages do not overwrite the input line. section 8.4.1

Interactive asynchronous console

A delay console enters cbreak mode, keeps the input field at the bottom of the screen, redraws messages above it, and supports character deletion. The same structure extends to an asynchronous command-line SQL client. section 8.4.1

Listing 8.8 Reading input one character at a time
import sys
from asyncio import StreamReader
from collections import deque
from chapter_08.listing_8_7 import move_back_one_char, clear_line
 
 
async def read_line(stdin_reader: StreamReader) -> str:
    def erase_last_char():                                     #1
        move_back_one_char()
        sys.stdout.write(' ')
        move_back_one_char()
 
    delete_char = b'\x7f'
    input_buffer = deque()
    while (input_char := await stdin_reader.read(1)) != b'\n':
        if input_char == delete_char:                          #2
            if len(input_buffer) > 0:
                input_buffer.pop()
                erase_last_char()
                sys.stdout.flush()
        else:
            input_buffer.append(input_char)                    #3
            sys.stdout.write(input_char.decode())
            sys.stdout.flush()
    clear_line()
    return b''.join(input_buffer).decode()

Shows a character-by-character line reader that buffers input, echoes characters, and erases the previous character for deletion. section 8.4.1

How Python Concurrency with asyncio covers it

How deep it goes
Explains mode selection, character reads, buffering, echoing, deletion, cursor movement, and output redrawing.
Examples
Uses a delay console and an asynchronous command-line SQL client with buffered input and redrawn message output.
What you can do after
Build interactive asynchronous terminal applications that read, edit, echo, and display input without output collisions.
How it connects
Contrasts cbreak mode with cooked mode and raw mode, and connects it to coroutines, terminal input, and standard streams.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Python Concurrency with asyncio. The section links point to the parts of the book it draws on.