import keyboard import os TEXT_REGULAR = '\033[38;5;2m' TEXT_HIGHLIGHTED = '\033[38;5;0m\033[48;5;2m' RESET_CODE = '\033[2;0;0m' class Text: def __init__(self, text: str): self.text = text self.prefix = TEXT_REGULAR self.suffix = RESET_CODE def highlight(self): self.prefix = TEXT_HIGHLIGHTED return self def regular(self): self.prefix = TEXT_REGULAR return self def draw_at(self, line: int, col: int): position = f'\033[{int(line)};{int(col)}f' print(f'{position}{self.prefix}{self.text}{self.suffix}', end='\r') class Menu: def __init__(self, title: str, options: dict): self.title = f'[{title}]' self.options = options self.selected = 0 def next(self): self.selected += 1 if self.selected > len(self.options) - 1: self.selected = 0 def prev(self): self.selected -= 1 if self.selected < 0: self.selected = len(self.options) - 1 def draw(self): term_dims = os.get_terminal_size() title_start = int((term_dims.columns / 2) - (len(self.title) / 2)) Text(self.title).draw_at(1, title_start) for i, k in enumerate(self.options): if i == self.selected: Text(k).highlight().draw_at(i + 2, 1) else: Text(k).draw_at(i + 2, 1) def main(): os.system('clear') os.system('stty -echo') print('\033[?25l', end='') menu = Menu('Test Menu', { 'Option 1:': 'opt', 'Option 2:': 'opt2', 'Option 3:': 'opt3' }) menu.draw() while True: pressed_key = keyboard.read_event() if pressed_key.event_type == 'down': if pressed_key.name == 'j': menu.next() elif pressed_key.name == 'k': menu.prev() menu.draw() if __name__ == '__main__': main()