eris/fill3/fill3/terminal.py
Andrew Hamilton 77eca03be3 Raw mode for ctrl-c and ctrl-z.
- No special behaviour for ctrl-c and ctrl-z by default.
2022-01-04 08:28:07 +10:00

111 lines
2.7 KiB
Python

import contextlib
import string
import sys
import termios
ESC = "\x1b"
UP = ESC + "[A"
DOWN = ESC + "[B"
RIGHT = ESC + "[C"
LEFT = ESC + "[D"
PAGE_UP = ESC + "[5~"
PAGE_DOWN = ESC + "[6~"
HOME = ESC + "[H"
END = ESC + "[F"
CTRL_UP = ESC + "[1;5A"
CTRL_DOWN = ESC + "[1;5B"
CTRL_LEFT = ESC + "[1;5D"
CTRL_RIGHT = ESC + "[1;5C"
CTRL_SPACE = "\x00"
ENTER = "\n"
BACKSPACE = "\x7f"
ALT_BACKSPACE = ESC + BACKSPACE
ALT_CARROT = ESC + "^"
ALT_SEMICOLON = ESC + ";"
ALT_UP = ESC + "[1;3A"
ALT_DOWN = ESC + "[1;3B"
ALT_LEFT = ESC + "[1;3D"
ALT_RIGHT = ESC + "[1;3C"
globals().update({f"ALT_{letter}": ESC + letter for letter in string.ascii_letters})
globals().update({f"CTRL_{letter}": chr(index + 1)
for index, letter in enumerate(string.ascii_uppercase)})
def move(x, y):
return ESC + f"[{y + 1:d};{x + 1:d}H"
@contextlib.contextmanager
def title(title):
sys.stdout.write(ESC + "7") # save
sys.stdout.write(f"\033]0;{title}\007") # set title
try:
yield
finally:
sys.stdout.write(ESC + "8") # restore
@contextlib.contextmanager
def mouse_tracking():
sys.stdout.write(ESC + "[?1000h" + ESC + "[?1002h") # tracking on
try:
yield
finally:
sys.stdout.write(ESC + "[?1002l" + ESC + "[?1000l") # tracking off
@contextlib.contextmanager
def alternate_buffer():
sys.stdout.write(ESC + "[?1049h") # switch to alternate buffer
try:
yield
finally:
sys.stdout.write(ESC + "[?1049l") # restore normal buffer
@contextlib.contextmanager
def interactive(raw_ctrl_c_and_z=True):
old_termios_settings = termios.tcgetattr(sys.stdin)
new_settings = termios.tcgetattr(sys.stdin)
new_settings[0] = new_settings[0] & ~termios.IXON
new_settings[3] = new_settings[3] & ~termios.ECHO & ~termios.ICANON
if raw_ctrl_c_and_z:
new_settings[3] = new_settings[3] & ~termios.ISIG
new_settings[6][termios.VMIN] = 0
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, new_settings)
sys.stdout.write(ESC + "[?1l") # Ensure normal cursor key codes
try:
yield
finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_termios_settings)
MOUSE = ESC + "[M"
MOUSE_RELEASE = 0
MOUSE_DRAG = 1
MOUSE_CLICK = 2
MOUSE_PRESS = 3
MOUSE_WHEEL_UP = 4
MOUSE_WHEEL_DOWN = 5
def decode_mouse_input(term_code):
keys = [ord(byte) for byte in term_code]
b = keys[0] - 32
x, y = (keys[1] - 33) % 256, (keys[2] - 33) % 256
button = ((b & 64) / 64 * 3) + (b & 3) + 1
if b & 3 == 3:
action = MOUSE_RELEASE
button = 0
elif b & 2048:
action = MOUSE_RELEASE
elif b & 32:
action = MOUSE_DRAG
elif b & 1536:
action = MOUSE_CLICK
else:
action = MOUSE_PRESS
return action, button, x, y