-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathui.py
More file actions
115 lines (84 loc) · 2.55 KB
/
ui.py
File metadata and controls
115 lines (84 loc) · 2.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
from enum import StrEnum, auto
from typing import List, Optional, Type
from utility import (
clear_screen,
pause,
read_input,
convert
)
from validation import validate, Validator, ValidationResult
# =========================
# Config
# =========================
BORDER_CHAR = "="
BORDER_LENGTH = 50
# =========================
# Message Types
# =========================
class MessageType(StrEnum):
INFO = auto()
SUCCESS = auto()
WARNING = auto()
NOTE = auto()
ERROR = auto()
MESSAGE_PREFIXES = {
MessageType.INFO: "",
MessageType.SUCCESS: "[✔] SUCCESS: ",
MessageType.WARNING: "[⚠️] WARNING: ",
MessageType.NOTE: "[!] NOTE: ",
MessageType.ERROR: "[✖] ERROR: "
}
# =========================
# Display Functions
# =========================
def display_divider():
print(BORDER_CHAR * BORDER_LENGTH)
def display_message(message: str, message_type: MessageType = MessageType.INFO):
prefix = MESSAGE_PREFIXES.get(message_type, "")
print(f"{prefix}{message}")
def display_header(title: str):
display_divider()
print(f"{title:^{BORDER_LENGTH}}")
display_divider()
def display_menu(title: str, items: List[str], indent: int = 2):
print(title)
max_digits = len(str(len(items)))
space = " " * indent
for i, item in enumerate(items, start=1):
print(f"{space}{i:0{max_digits}d}. {item}")
# =========================
# Input Handler
# =========================
def get_valid_input(
prompt: str,
validators: Optional[List[Validator]] = None,
return_type: Optional[Type] = None
):
while True:
value = read_input(prompt)
if validators:
result = validate(value, validators)
if not result.is_valid:
display_message(result.message, MessageType.ERROR)
continue
try:
return convert(value, return_type)
except Exception:
display_message("Conversion failed", MessageType.ERROR)
# =========================
# Menu Component
# =========================
def prompt_menu_selection(title: str, items: List[str]) -> int:
if not items:
raise ValueError("Menu cannot be empty")
display_menu(title, items)
display_divider()
validators = [
lambda x: ValidationResult(x.isdigit(), "Enter a number"),
lambda x: ValidationResult(
(1 <= int(x) <= len(items)) if x.isdigit() else False,
"Choice out of range"
)
]
choice = get_valid_input("Enter your choice: ", validators)
return int(choice)