Skip to content

Commit

Permalink
gh-85984: New additions and improvements to the tty library. (#101832)
Browse files Browse the repository at this point in the history
New additions to the tty library. Functions added: cfmakeraw(), and cfmakecbreak(). The
functions setcbreak() and setraw() now return original termios to save an extra tcgetattr() call.

---------

Signed-off-by: Soumendra Ganguly <soumendraganguly@gmail.com>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Gregory P. Smith [Google LLC] <greg@krypto.org>
  • Loading branch information
3 people committed May 19, 2023
1 parent 3ac856e commit 486bc8e
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 18 deletions.
22 changes: 20 additions & 2 deletions Doc/library/tty.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,36 @@ Because it requires the :mod:`termios` module, it will work only on Unix.
The :mod:`tty` module defines the following functions:


.. function:: cfmakeraw(mode)

Convert the tty attribute list *mode*, which is a list like the one returned
by :func:`termios.tcgetattr`, to that of a tty in raw mode.

.. versionadded:: 3.12


.. function:: cfmakecbreak(mode)

Convert the tty attribute list *mode*, which is a list like the one returned
by :func:`termios.tcgetattr`, to that of a tty in cbreak mode.

.. versionadded:: 3.12


.. function:: setraw(fd, when=termios.TCSAFLUSH)

Change the mode of the file descriptor *fd* to raw. If *when* is omitted, it
defaults to :const:`termios.TCSAFLUSH`, and is passed to
:func:`termios.tcsetattr`.
:func:`termios.tcsetattr`. The return value of :func:`termios.tcgetattr`
is saved before setting *fd* to raw mode; this value is returned.


.. function:: setcbreak(fd, when=termios.TCSAFLUSH)

Change the mode of file descriptor *fd* to cbreak. If *when* is omitted, it
defaults to :const:`termios.TCSAFLUSH`, and is passed to
:func:`termios.tcsetattr`.
:func:`termios.tcsetattr`. The return value of :func:`termios.tcgetattr`
is saved before setting *fd* to cbreak mode; this value is returned.


.. seealso::
Expand Down
70 changes: 54 additions & 16 deletions Lib/tty.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

from termios import *

__all__ = ["setraw", "setcbreak"]
__all__ = ["cfmakeraw", "cfmakecbreak", "setraw", "setcbreak"]

# Indexes for termios list.
# Indices for termios list.
IFLAG = 0
OFLAG = 1
CFLAG = 2
Expand All @@ -15,22 +15,60 @@
OSPEED = 5
CC = 6

def setraw(fd, when=TCSAFLUSH):
"""Put terminal into a raw mode."""
mode = tcgetattr(fd)
mode[IFLAG] = mode[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
mode[OFLAG] = mode[OFLAG] & ~(OPOST)
mode[CFLAG] = mode[CFLAG] & ~(CSIZE | PARENB)
mode[CFLAG] = mode[CFLAG] | CS8
mode[LFLAG] = mode[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
def cfmakeraw(mode):
"""Make termios mode raw."""
# Clear all POSIX.1-2017 input mode flags.
# See chapter 11 "General Terminal Interface"
# of POSIX.1-2017 Base Definitions.
mode[IFLAG] &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP |
INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF)

# Do not post-process output.
mode[OFLAG] &= ~OPOST

# Disable parity generation and detection; clear character size mask;
# let character size be 8 bits.
mode[CFLAG] &= ~(PARENB | CSIZE)
mode[CFLAG] |= CS8

# Clear all POSIX.1-2017 local mode flags.
mode[LFLAG] &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON |
IEXTEN | ISIG | NOFLSH | TOSTOP)

# POSIX.1-2017, 11.1.7 Non-Canonical Mode Input Processing,
# Case B: MIN>0, TIME=0
# A pending read shall block until MIN (here 1) bytes are received,
# or a signal is received.
mode[CC][VMIN] = 1
mode[CC][VTIME] = 0
tcsetattr(fd, when, mode)

def setcbreak(fd, when=TCSAFLUSH):
"""Put terminal into a cbreak mode."""
mode = tcgetattr(fd)
mode[LFLAG] = mode[LFLAG] & ~(ECHO | ICANON)
def cfmakecbreak(mode):
"""Make termios mode cbreak."""
# Do not map CR to NL on input.
mode[IFLAG] &= ~(ICRNL)

# Do not echo characters; disable canonical input.
mode[LFLAG] &= ~(ECHO | ICANON)

# POSIX.1-2017, 11.1.7 Non-Canonical Mode Input Processing,
# Case B: MIN>0, TIME=0
# A pending read shall block until MIN (here 1) bytes are received,
# or a signal is received.
mode[CC][VMIN] = 1
mode[CC][VTIME] = 0
tcsetattr(fd, when, mode)

def setraw(fd, when=TCSAFLUSH):
"""Put terminal into raw mode."""
mode = tcgetattr(fd)
new = list(mode)
cfmakeraw(new)
tcsetattr(fd, when, new)
return mode

def setcbreak(fd, when=TCSAFLUSH):
"""Put terminal into cbreak mode."""
mode = tcgetattr(fd)
new = list(mode)
cfmakecbreak(new)
tcsetattr(fd, when, new)
return mode
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Add :func:`tty.cfmakeraw` and :func:`tty.cfmakecbreak` to :mod:`tty` and
modernize, the behavior of :func:`tty.setraw` and :func:`tty.setcbreak` to use
POSIX.1-2017 Chapter 11 "General Terminal Interface" flag masks by default.

0 comments on commit 486bc8e

Please sign in to comment.