import os; import utils class Menu(): def __init__(self, options: list, title: str = None, cursor: str = "> ", cursor_pos: int = 0, preview_body_function = None, preview_title_function = None, preview_args: list = None, preview_ratio: float = 0.5, circular: bool = True, skip_empty_option: bool = False, quit_button: bool = False): self.options = options; self.title = title; self.cursor = cursor; self.cursor_pos = cursor_pos; self.cursor_pos_x = 0; self.preview_body_function = preview_body_function; self.preview_title_function = preview_title_function; if (preview_args == None): self.preview_args = options; else: self.preview_args = preview_args; self.circular = circular; self.skip_empty_option = skip_empty_option; self.size = len(options) self.preview_ratio = preview_ratio; def _up(self): if (self.circular == False): if (self.cursor_pos != 0): self.cursor_pos = self.cursor_pos - 1 else: self.cursor_pos = (self.cursor_pos - 1) % self.size; if (self.skip_empty_option == True): if (self.options[self.cursor_pos] == None or self.options[self.cursor_pos] == ""): self._up() self.cursor_pos_x = 0; def _down(self): if (self.circular == False): if (self.cursor_pos != self.size - 1): self.cursor_pos = self.cursor_pos + 1 else: self.cursor_pos = (self.cursor_pos + 1) % self.size; if (self.skip_empty_option == True): if (self.options[self.cursor_pos] == None or self.options[self.cursor_pos] == ""): self._down() self.cursor_pos_x = 0; def _left(self): if (self.cursor_pos_x > 0): self.cursor_pos_x = self.cursor_pos_x - 1; def _right(self): self.cursor_pos_x = self.cursor_pos_x + 1; def show(self): while (True): self._display_menu(); key = self._get_input() if (key == "up"): self._up() elif (key == "down"): self._down() if (key == "left"): self._left() elif (key == "right"): self._right() elif (key == "enter"): return (self.cursor_pos) def _display_menu(self): self._clear(); size = os.get_terminal_size(); size_x = size.columns; size_y = size.lines - 2; preview = self._preview(); content_size, preview_size = utils.get_sizes(self.size, preview.count("\n") + 1, size_y, self.preview_ratio) min_y, max_y, display_pos = utils.render(self.cursor_pos, 0, self.size, content_size // 2, self.options) for i, option in enumerate(self.options[min_y:max_y]): element = option if (i == display_pos): min_x, max_x, display_pos_x = utils.render(self.cursor_pos_x, 0, len(element), len(element) // 2, option) line = self.cursor + element[min_x:max_x] else: line = " " * len(self.cursor) + element print(line) print(preview) def _preview(self): if (len(self.preview_args) < self.cursor_pos): return title = "" if (self.preview_title_function != None): title = self.preview_title_function(self.preview_args[self.cursor_pos]) elif (self.preview_body_function != None): body = self.preview_body_function(self.preview_args[self.cursor_pos]) return (title + "\n" + body); def _clear(self): os.system("clear") def _get_input(self) -> str: flag_have_getch = False flag_have_msvcrt = False try : import getch flag_have_getch = True first_char = getch.getch() if first_char == '\x1b': #arrow keys a=getch.getch() b=getch.getch() return {'[A': 'up', '[B': 'down', '[C': 'right', '[D': 'left' }[a+b] if ord(first_char) == 10: return 'enter' if ord(first_char) == 32: return 'space' else: return first_char #normal keys like abcd 1234 except : pass try: import msvcrt flag_have_msvcrt = True key = msvcrt.getch() # get keypress if key == b'\x1b': # Esc key to exit return 'esc' elif key == b'\r': # Enter key to select return 'enter' elif key == b'\x48': # Up or Down arrow return 'up' elif key == b'\x50': # Up or Down arrow return 'down' else: return key.decode('utf-8') except: pass if flag_have_getch == False and flag_have_msvcrt == False: print('\nErr:\tcan\'t get input \nFix:\tpip install getch') exit() first_char = getch.getch() print (first_char) if first_char == '\x1b': #arrow keys a=getch.getch() b=getch.getch() return {'[A': 'up', '[B': 'down', '[C': 'right', '[D': 'left' }[a+b] if ord(first_char) == 10: return 'enter' if ord(first_char) == 32: return 'space' def preview(lst): return ("je suis la") menu = Menu("fdddddddddddddddddddddddddddddddddddddddddddddddddddddddda", preview_body_function=preview); menu.show()