-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathmenu.py
More file actions
115 lines (94 loc) · 3.2 KB
/
menu.py
File metadata and controls
115 lines (94 loc) · 3.2 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
import shutil
import textwrap
import typing
import colorama
from xcoder.config import config
from xcoder.localization import locale
def print_feature(
feature_id: int, name: str, description: str | None = None, console_width: int = -1
):
text = f" {feature_id} {name}"
if description:
text += " " * (console_width // 2 - len(text)) + ": " + description
print(textwrap.fill(text, console_width))
def print_category(text: str, background_width: int = 10):
print(
colorama.Back.GREEN
+ colorama.Fore.BLACK
+ text
+ " " * (background_width - len(text))
+ colorama.Style.RESET_ALL
)
class Menu:
class Item:
def __init__(
self,
*,
name: str,
handler: typing.Callable,
description: str | None = None,
):
self.name: str = name
self.description: str | None = description
self.handler: typing.Callable = handler
class Category:
def __init__(self, _id: int, name: str):
self.id = _id
self.name = name
self.items = []
def item(self, name: str, description: str | None = None):
def wrapper(handler: typing.Callable):
self.add(Menu.Item(name=name, handler=handler, description=description))
return wrapper
def add(self, item):
self.items.append(item)
def __init__(self):
self.categories = []
def add_category(self, category):
self.categories.append(category)
return category
def choice(self):
console_width = shutil.get_terminal_size().columns
print(
(
colorama.Back.BLACK
+ colorama.Fore.GREEN
+ locale.xcoder_header % config.version
+ colorama.Style.RESET_ALL
).center(console_width + 12)
)
print(config.get_repo_url().center(console_width - 1))
self._print_divider_line(console_width)
for category in self.categories:
if len(category.items) == 0:
continue
print_category(category.name)
for item_index in range(len(category.items)):
item = category.items[item_index]
print_feature(
category.id * 10 + item_index + 1,
item.name,
item.description,
console_width,
)
self._print_divider_line(console_width)
choice = input(locale.choice)
try:
choice = int(choice) - 1
if choice < 0:
return None
except ValueError:
return None
self._print_divider_line(console_width)
category_id = choice // 10
item_index = choice % 10
for category in self.categories:
if category.id == category_id:
if len(category.items) > item_index:
item = category.items[item_index]
return item.handler
break
return None
@staticmethod
def _print_divider_line(console_width: int) -> None:
print((console_width - 1) * "-")