Added select menu to console

This commit is contained in:
Sven Heidemann 2021-03-12 18:06:05 +01:00
parent 9663e542f1
commit 15b1a82cce
3 changed files with 143 additions and 35 deletions

View File

@ -16,12 +16,12 @@
"LicenseName": "MIT",
"LicenseDescription": "MIT, see LICENSE for more details.",
"Dependencies": [
"discord.py",
"mysql-connector",
"SQLAlchemy",
"termcolor",
"pyfiglet",
"tabulate"
"tabulate",
"pynput"
],
"PythonVersion": ">=3.8"
},

View File

@ -3,6 +3,8 @@ from collections import Callable
from typing import Union, Optional
import pyfiglet
from pynput import keyboard
from pynput.keyboard import Key
from tabulate import tabulate
from termcolor import colored
@ -24,6 +26,15 @@ class Console:
_hold_back = False
_hold_back_calls: list[ConsoleCall] = []
_select_menu_items: list[str] = []
_is_first_select_menu_output = True
_selected_menu_item_index: int = 0
_selected_menu_item_char: str = ''
_selected_menu_option_foreground_color: ForegroundColorEnum = ForegroundColorEnum.default
_selected_menu_option_background_color: BackgroundColorEnum = BackgroundColorEnum.default
_selected_menu_cursor_foreground_color: ForegroundColorEnum = ForegroundColorEnum.default
_selected_menu_cursor_background_color: BackgroundColorEnum = BackgroundColorEnum.default
"""
Properties
"""
@ -99,6 +110,41 @@ class Console:
args.append(colored(*colored_args))
print(*args, end=end)
@classmethod
def _show_select_menu(cls):
if not cls._is_first_select_menu_output:
for _ in range(0, len(cls._select_menu_items) + 1):
print('\b', end="\r")
else:
cls._is_first_select_menu_output = False
for i in range(0, len(cls._select_menu_items)):
Console.set_foreground_color(cls._selected_menu_cursor_foreground_color)
Console.set_background_color(cls._selected_menu_cursor_background_color)
Console.write_line(f'{cls._selected_menu_item_char if cls._selected_menu_item_index == i else " "} ')
Console.set_foreground_color(cls._selected_menu_option_foreground_color)
Console.set_background_color(cls._selected_menu_option_background_color)
Console.write(f'{cls._select_menu_items[i]}')
Console.write_line()
@classmethod
def _select_menu_key_press(cls, key: Key):
if key == Key.down:
if cls._selected_menu_item_index == len(cls._select_menu_items) - 1:
return
cls._selected_menu_item_index += 1
cls._show_select_menu()
elif key == Key.up:
if cls._selected_menu_item_index == 0:
return
cls._selected_menu_item_index -= 1
cls._show_select_menu()
elif key == Key.enter:
return False
"""
Useful public methods
"""
@ -132,7 +178,7 @@ class Console:
cls._hold_back_calls.append(ConsoleCall(cls.close))
return
Console.reset()
Console.color_reset()
Console.write('\n\n\nPress any key to continue...')
Console.read_line()
exit()
@ -181,7 +227,7 @@ class Console:
return input()
@classmethod
def reset(cls):
def color_reset(cls):
cls._background_color = BackgroundColorEnum.default
cls._foreground_color = ForegroundColorEnum.default
@ -199,6 +245,72 @@ class Console:
Console.write_line(table)
Console.write('\n')
@classmethod
def select(cls, char: str, message: str, options: list[str],
header_foreground_color: Union[str, ForegroundColorEnum] = ForegroundColorEnum.default,
header_background_color: Union[str, BackgroundColorEnum] = BackgroundColorEnum.default,
option_foreground_color: Union[str, ForegroundColorEnum] = ForegroundColorEnum.default,
option_background_color: Union[str, BackgroundColorEnum] = BackgroundColorEnum.default,
cursor_foreground_color: Union[str, ForegroundColorEnum] = ForegroundColorEnum.default,
cursor_background_color: Union[str, BackgroundColorEnum] = BackgroundColorEnum.default
) -> str:
cls._selected_menu_item_char = char
cls._select_menu_items = options
if option_foreground_color is not None:
cls._selected_menu_option_foreground_color = option_foreground_color
if option_background_color is not None:
cls._selected_menu_option_background_color = option_background_color
if cursor_foreground_color is not None:
cls._selected_menu_cursor_foreground_color = cursor_foreground_color
if cursor_background_color is not None:
cls._selected_menu_cursor_background_color = cursor_background_color
Console.set_foreground_color(header_foreground_color)
Console.set_background_color(header_background_color)
Console.write_line(message)
cls._show_select_menu()
with keyboard.Listener(
on_press=cls._select_menu_key_press, suppress=True) as listener:
listener.join()
Console.color_reset()
return cls._select_menu_items[cls._selected_menu_item_index]
@classmethod
def spinner(cls, message: str, call: Callable, *args, text_foreground_color: Union[str, ForegroundColorEnum] = None,
spinner_foreground_color: Union[str, ForegroundColorEnum] = None,
text_background_color: Union[str, BackgroundColorEnum] = None,
spinner_background_color: Union[str, BackgroundColorEnum] = None) -> any:
if cls._hold_back:
cls._hold_back_calls.append(ConsoleCall(cls.spinner, message, call, *args))
return
if text_foreground_color is not None:
cls.set_foreground_color(text_foreground_color)
if text_background_color is not None:
cls.set_background_color(text_background_color)
cls.write_line(message)
cls.set_hold_back(True)
spinner = SpinnerThread(len(message), spinner_foreground_color, spinner_background_color)
spinner.start()
return_value = call(*args)
spinner.stop_spinning()
cls.set_hold_back(False)
cls.set_foreground_color(ForegroundColorEnum.default)
cls.set_background_color(BackgroundColorEnum.default)
for call in cls._hold_back_calls:
call.function(*call.args)
return return_value
@classmethod
def write(cls, *args):
if cls._disabled:
@ -250,34 +362,3 @@ class Console:
if not cls._is_first_write:
cls._output('', end='')
cls._output(string, x, y, end='')
@classmethod
def spinner(cls, message: str, call: Callable, *args, text_foreground_color: Union[str, ForegroundColorEnum] = None,
spinner_foreground_color: Union[str, ForegroundColorEnum] = None,
text_background_color: Union[str, BackgroundColorEnum] = None,
spinner_background_color: Union[str, BackgroundColorEnum] = None) -> any:
if cls._hold_back:
cls._hold_back_calls.append(ConsoleCall(cls.spinner, message, call, *args))
return
if text_foreground_color is not None:
cls.set_foreground_color(text_foreground_color)
if text_background_color is not None:
cls.set_background_color(text_background_color)
cls.write_line(message)
cls.set_hold_back(True)
spinner = SpinnerThread(len(message), spinner_foreground_color, spinner_background_color)
spinner.start()
return_value = call(*args)
spinner.stop_spinning()
cls.set_hold_back(False)
cls.set_foreground_color(ForegroundColorEnum.default)
cls.set_background_color(BackgroundColorEnum.default)
for call in cls._hold_back_calls:
call.function(*call.args)
return return_value

View File

@ -0,0 +1,27 @@
import time
from cpl.console import Console, ForegroundColorEnum
def test_spinner():
time.sleep(3)
if __name__ == '__main__':
Console.write_line('Hello World')
# Console.spinner('Test:', test_spinner, spinner_foreground_color=ForegroundColorEnum.cyan,
# text_foreground_color='green')
opts = [
'Option 1',
'Option 2',
'Option 3',
'Option 4'
]
selected = Console.select(
'>',
'Select item:',
opts,
header_foreground_color=ForegroundColorEnum.blue,
option_foreground_color=ForegroundColorEnum.green,
cursor_foreground_color=ForegroundColorEnum.red
)
Console.write_line(f'You selected: {selected}')