argenta 0.5.0b2__py3-none-any.whl → 1.0.0a0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- argenta/app/autocompleter/entity.py +32 -7
- argenta/app/defaults.py +4 -1
- argenta/app/dividing_line/models.py +55 -11
- argenta/app/exceptions.py +4 -6
- argenta/app/models.py +231 -105
- argenta/app/registered_routers/entity.py +21 -2
- argenta/command/exceptions.py +12 -0
- argenta/command/flag/defaults.py +4 -1
- argenta/command/flag/models.py +84 -6
- argenta/command/models.py +59 -7
- argenta/orchestrator/__init__.py +4 -0
- argenta/orchestrator/argparser/__init__.py +4 -0
- argenta/orchestrator/argparser/arguments/__init__.py +6 -0
- argenta/orchestrator/argparser/arguments/models.py +55 -0
- argenta/orchestrator/argparser/entity.py +49 -0
- argenta/orchestrator/entity.py +36 -0
- argenta/router/command_handler/entity.py +63 -5
- argenta/router/defaults.py +1 -2
- argenta/router/entity.py +99 -39
- argenta/router/exceptions.py +16 -1
- argenta-1.0.0a0.dist-info/METADATA +1438 -0
- argenta-1.0.0a0.dist-info/RECORD +33 -0
- {argenta-0.5.0b2.dist-info → argenta-1.0.0a0.dist-info}/WHEEL +1 -1
- argenta/router/command_handlers/__init__.py +0 -0
- argenta/router/command_handlers/entity.py +0 -21
- argenta-0.5.0b2.dist-info/METADATA +0 -601
- argenta-0.5.0b2.dist-info/RECORD +0 -29
- {argenta-0.5.0b2.dist-info → argenta-1.0.0a0.dist-info/licenses}/LICENSE +0 -0
@@ -3,13 +3,25 @@ import readline
|
|
3
3
|
|
4
4
|
|
5
5
|
class AutoCompleter:
|
6
|
-
def __init__(self, history_filename: str = False, autocomplete_button: str = 'tab'):
|
6
|
+
def __init__(self, history_filename: str = False, autocomplete_button: str = 'tab') -> None:
|
7
|
+
"""
|
8
|
+
Public. Configures and implements auto-completion of input command
|
9
|
+
:param history_filename: the name of the file for saving the history of the autocompleter
|
10
|
+
:param autocomplete_button: the button for auto-completion
|
11
|
+
:return: None
|
12
|
+
"""
|
7
13
|
self.history_filename = history_filename
|
8
14
|
self.autocomplete_button = autocomplete_button
|
9
|
-
self.matches = []
|
15
|
+
self.matches: list[str] = []
|
10
16
|
|
11
|
-
def complete(self, text, state):
|
12
|
-
|
17
|
+
def complete(self, text, state) -> str | None:
|
18
|
+
"""
|
19
|
+
Private. Auto-completion function
|
20
|
+
:param text: part of the command being entered
|
21
|
+
:param state: the current cursor position is relative to the beginning of the line
|
22
|
+
:return: the desired candidate as str or None
|
23
|
+
"""
|
24
|
+
matches: list[str] = sorted(cmd for cmd in self.get_history_items() if cmd.startswith(text))
|
13
25
|
if len(matches) > 1:
|
14
26
|
common_prefix = matches[0]
|
15
27
|
for match in matches[1:]:
|
@@ -26,7 +38,12 @@ class AutoCompleter:
|
|
26
38
|
else:
|
27
39
|
return None
|
28
40
|
|
29
|
-
def initial_setup(self, all_commands: list[str]):
|
41
|
+
def initial_setup(self, all_commands: list[str]) -> None:
|
42
|
+
"""
|
43
|
+
Private. Initial setup function
|
44
|
+
:param all_commands: Registered commands for adding them to the autocomplete history
|
45
|
+
:return: None
|
46
|
+
"""
|
30
47
|
if self.history_filename:
|
31
48
|
if os.path.exists(self.history_filename):
|
32
49
|
readline.read_history_file(self.history_filename)
|
@@ -38,10 +55,18 @@ class AutoCompleter:
|
|
38
55
|
readline.set_completer_delims(readline.get_completer_delims().replace(' ', ''))
|
39
56
|
readline.parse_and_bind(f'{self.autocomplete_button}: complete')
|
40
57
|
|
41
|
-
def exit_setup(self):
|
58
|
+
def exit_setup(self) -> None:
|
59
|
+
"""
|
60
|
+
Private. Exit setup function
|
61
|
+
:return: None
|
62
|
+
"""
|
42
63
|
if self.history_filename:
|
43
64
|
readline.write_history_file(self.history_filename)
|
44
65
|
|
45
66
|
@staticmethod
|
46
|
-
def get_history_items():
|
67
|
+
def get_history_items() -> list[str] | list:
|
68
|
+
"""
|
69
|
+
Private. Returns a list of all commands entered by the user
|
70
|
+
:return: all commands entered by the user as list[str]
|
71
|
+
"""
|
47
72
|
return [readline.get_history_item(i) for i in range(1, readline.get_current_history_length() + 1)]
|
argenta/app/defaults.py
CHANGED
@@ -2,7 +2,10 @@ from dataclasses import dataclass
|
|
2
2
|
|
3
3
|
|
4
4
|
@dataclass
|
5
|
-
class
|
5
|
+
class PredefinedMessages:
|
6
|
+
"""
|
7
|
+
Public. A dataclass with predetermined messages for quick use
|
8
|
+
"""
|
6
9
|
USAGE = '[b dim]Usage[/b dim]: [i]<command> <[green]flags[/green]>[/i]'
|
7
10
|
HELP = '[b dim]Help[/b dim]: [i]<command>[/i] [b red]--help[/b red]'
|
8
11
|
AUTOCOMPLETE = '[b dim]Autocomplete[/b dim]: [i]<part>[/i] [bold]<tab>'
|
@@ -1,24 +1,68 @@
|
|
1
|
-
|
2
|
-
def __init__(self, unit_part: str = '-'):
|
3
|
-
self.unit_part = unit_part
|
1
|
+
from abc import ABC
|
4
2
|
|
5
|
-
|
6
|
-
|
3
|
+
|
4
|
+
class BaseDividingLine(ABC):
|
5
|
+
def __init__(self, unit_part: str = '-') -> None:
|
6
|
+
"""
|
7
|
+
Private. The basic dividing line
|
8
|
+
:param unit_part: the single part of the dividing line
|
9
|
+
:return: None
|
10
|
+
"""
|
11
|
+
self._unit_part = unit_part
|
12
|
+
|
13
|
+
def get_unit_part(self) -> str:
|
14
|
+
"""
|
15
|
+
Private. Returns the unit part of the dividing line
|
16
|
+
:return: unit_part of dividing line as str
|
17
|
+
"""
|
18
|
+
if len(self._unit_part) == 0:
|
7
19
|
return ' '
|
8
20
|
else:
|
9
|
-
return self.
|
21
|
+
return self._unit_part[0]
|
22
|
+
|
10
23
|
|
11
24
|
class StaticDividingLine(BaseDividingLine):
|
12
|
-
def __init__(self, unit_part: str = '-', length: int = 25):
|
25
|
+
def __init__(self, unit_part: str = '-', length: int = 25) -> None:
|
26
|
+
"""
|
27
|
+
Public. The static dividing line
|
28
|
+
:param unit_part: the single part of the dividing line
|
29
|
+
:param length: the length of the dividing line
|
30
|
+
:return: None
|
31
|
+
"""
|
13
32
|
super().__init__(unit_part)
|
14
33
|
self.length = length
|
15
34
|
|
16
|
-
def
|
17
|
-
|
35
|
+
def get_full_static_line(self, is_override: bool) -> str:
|
36
|
+
"""
|
37
|
+
Private. Returns the full line of the dividing line
|
38
|
+
:param is_override: has the default text layout been redefined
|
39
|
+
:return: full line of dividing line as str
|
40
|
+
"""
|
41
|
+
if is_override:
|
42
|
+
return f'\n{self.length * self.get_unit_part()}\n'
|
43
|
+
else:
|
44
|
+
return f'\n[dim]{self.length * self.get_unit_part()}[/dim]\n'
|
18
45
|
|
19
46
|
|
20
47
|
class DynamicDividingLine(BaseDividingLine):
|
21
|
-
def
|
22
|
-
|
48
|
+
def __init__(self, unit_part: str = '-') -> None:
|
49
|
+
"""
|
50
|
+
Public. The dynamic dividing line
|
51
|
+
:param unit_part: the single part of the dividing line
|
52
|
+
:return: None
|
53
|
+
"""
|
54
|
+
super().__init__(unit_part)
|
55
|
+
|
56
|
+
def get_full_dynamic_line(self, length: int, is_override: bool) -> str:
|
57
|
+
"""
|
58
|
+
Private. Returns the full line of the dividing line
|
59
|
+
:param length: the length of the dividing line
|
60
|
+
:param is_override: has the default text layout been redefined
|
61
|
+
:return: full line of dividing line as str
|
62
|
+
"""
|
63
|
+
if is_override:
|
64
|
+
return f'\n{length * self.get_unit_part()}\n'
|
65
|
+
else:
|
66
|
+
return f'\n[dim]{self.get_unit_part() * length}[/dim]\n'
|
23
67
|
|
24
68
|
|
argenta/app/exceptions.py
CHANGED
@@ -1,10 +1,8 @@
|
|
1
|
-
class NoRegisteredRoutersException(Exception):
|
2
|
-
def __str__(self):
|
3
|
-
return "No Registered Router Found"
|
4
|
-
|
5
|
-
|
6
1
|
class NoRegisteredHandlersException(Exception):
|
7
|
-
|
2
|
+
"""
|
3
|
+
The router has no registered handlers
|
4
|
+
"""
|
5
|
+
def __init__(self, router_name) -> None:
|
8
6
|
self.router_name = router_name
|
9
7
|
def __str__(self):
|
10
8
|
return f"No Registered Handlers Found For '{self.router_name}'"
|
argenta/app/models.py
CHANGED
@@ -15,29 +15,29 @@ from argenta.command.exceptions import (UnprocessedInputFlagException,
|
|
15
15
|
RepeatedInputFlagsException,
|
16
16
|
EmptyInputCommandException,
|
17
17
|
BaseInputCommandException)
|
18
|
-
from argenta.app.exceptions import
|
19
|
-
NoRegisteredHandlersException)
|
18
|
+
from argenta.app.exceptions import NoRegisteredHandlersException
|
20
19
|
from argenta.app.registered_routers.entity import RegisteredRouters
|
21
20
|
|
22
21
|
|
23
22
|
|
24
|
-
class
|
23
|
+
class BaseApp:
|
25
24
|
def __init__(self,
|
26
|
-
prompt: str
|
27
|
-
initial_message: str
|
28
|
-
farewell_message: str
|
29
|
-
exit_command: Command
|
30
|
-
|
31
|
-
ignore_command_register: bool
|
32
|
-
dividing_line: StaticDividingLine | DynamicDividingLine
|
33
|
-
repeat_command_groups: bool
|
34
|
-
override_system_messages: bool
|
35
|
-
autocompleter: AutoCompleter
|
36
|
-
print_func: Callable[[str], None]
|
25
|
+
prompt: str,
|
26
|
+
initial_message: str,
|
27
|
+
farewell_message: str,
|
28
|
+
exit_command: Command,
|
29
|
+
system_router_title: str | None,
|
30
|
+
ignore_command_register: bool,
|
31
|
+
dividing_line: StaticDividingLine | DynamicDividingLine,
|
32
|
+
repeat_command_groups: bool,
|
33
|
+
override_system_messages: bool,
|
34
|
+
autocompleter: AutoCompleter,
|
35
|
+
print_func: Callable[[str], None]) -> None:
|
36
|
+
|
37
37
|
self._prompt = prompt
|
38
38
|
self._print_func = print_func
|
39
39
|
self._exit_command = exit_command
|
40
|
-
self.
|
40
|
+
self._system_router_title = system_router_title
|
41
41
|
self._dividing_line = dividing_line
|
42
42
|
self._ignore_command_register = ignore_command_register
|
43
43
|
self._repeat_command_groups_description = repeat_command_groups
|
@@ -48,44 +48,79 @@ class AppInit:
|
|
48
48
|
self._initial_message = initial_message
|
49
49
|
|
50
50
|
|
51
|
-
self._description_message_gen: Callable[[str, str], str] = lambda command, description: f'[
|
51
|
+
self._description_message_gen: Callable[[str, str], str] = lambda command, description: f'[{command}] *=*=* {description}'
|
52
52
|
self._registered_routers: RegisteredRouters = RegisteredRouters()
|
53
|
-
self._messages_on_startup = []
|
53
|
+
self._messages_on_startup: list[str] = []
|
54
|
+
|
55
|
+
self._all_registered_triggers_in_lower: list[str] = []
|
56
|
+
self._all_registered_triggers_in_default_case: list[str] = []
|
54
57
|
|
55
|
-
self._invalid_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'
|
56
|
-
self._repeated_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'
|
57
|
-
self._empty_input_command_handler: Callable[[], None] = lambda: print_func('
|
58
|
-
self._unknown_command_handler: Callable[[InputCommand], None] = lambda command: print_func(f"
|
58
|
+
self._invalid_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'Incorrect flag syntax: {raw_command}')
|
59
|
+
self._repeated_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'Repeated input flags: {raw_command}')
|
60
|
+
self._empty_input_command_handler: Callable[[], None] = lambda: print_func('Empty input command')
|
61
|
+
self._unknown_command_handler: Callable[[InputCommand], None] = lambda command: print_func(f"Unknown command: {command.get_trigger()}")
|
59
62
|
self._exit_command_handler: Callable[[], None] = lambda: print_func(self._farewell_message)
|
60
63
|
|
61
64
|
|
62
|
-
class AppSetters(AppInit):
|
63
65
|
def set_description_message_pattern(self, pattern: Callable[[str, str], str]) -> None:
|
66
|
+
"""
|
67
|
+
Public. Sets the output pattern of the available commands
|
68
|
+
:param pattern: output pattern of the available commands
|
69
|
+
:return: None
|
70
|
+
"""
|
64
71
|
self._description_message_gen: Callable[[str, str], str] = pattern
|
65
72
|
|
66
73
|
|
67
74
|
def set_invalid_input_flags_handler(self, handler: Callable[[str], None]) -> None:
|
75
|
+
"""
|
76
|
+
Public. Sets the handler for incorrect flags when entering a command
|
77
|
+
:param handler: handler for incorrect flags when entering a command
|
78
|
+
:return: None
|
79
|
+
"""
|
68
80
|
self._invalid_input_flags_handler = handler
|
69
81
|
|
70
82
|
|
71
83
|
def set_repeated_input_flags_handler(self, handler: Callable[[str], None]) -> None:
|
84
|
+
"""
|
85
|
+
Public. Sets the handler for repeated flags when entering a command
|
86
|
+
:param handler: handler for repeated flags when entering a command
|
87
|
+
:return: None
|
88
|
+
"""
|
72
89
|
self._repeated_input_flags_handler = handler
|
73
90
|
|
74
91
|
|
75
92
|
def set_unknown_command_handler(self, handler: Callable[[str], None]) -> None:
|
93
|
+
"""
|
94
|
+
Public. Sets the handler for unknown commands when entering a command
|
95
|
+
:param handler: handler for unknown commands when entering a command
|
96
|
+
:return: None
|
97
|
+
"""
|
76
98
|
self._unknown_command_handler = handler
|
77
99
|
|
78
100
|
|
79
101
|
def set_empty_command_handler(self, handler: Callable[[], None]) -> None:
|
102
|
+
"""
|
103
|
+
Public. Sets the handler for empty commands when entering a command
|
104
|
+
:param handler: handler for empty commands when entering a command
|
105
|
+
:return: None
|
106
|
+
"""
|
80
107
|
self._empty_input_command_handler = handler
|
81
108
|
|
82
109
|
|
83
110
|
def set_exit_command_handler(self, handler: Callable[[], None]) -> None:
|
111
|
+
"""
|
112
|
+
Public. Sets the handler for exit command when entering a command
|
113
|
+
:param handler: handler for exit command when entering a command
|
114
|
+
:return: None
|
115
|
+
"""
|
84
116
|
self._exit_command_handler = handler
|
85
117
|
|
86
118
|
|
87
|
-
|
88
|
-
|
119
|
+
def _print_command_group_description(self) -> None:
|
120
|
+
"""
|
121
|
+
Private. Prints the description of the available commands
|
122
|
+
:return: None
|
123
|
+
"""
|
89
124
|
for registered_router in self._registered_routers:
|
90
125
|
if registered_router.get_title():
|
91
126
|
self._print_func(registered_router.get_title())
|
@@ -96,54 +131,74 @@ class AppPrinters(AppInit):
|
|
96
131
|
self._print_func('')
|
97
132
|
|
98
133
|
|
99
|
-
def
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
134
|
+
def _print_framed_text(self, text: str) -> None:
|
135
|
+
"""
|
136
|
+
Private. Outputs text by framing it in a static or dynamic split strip
|
137
|
+
:param text: framed text
|
138
|
+
:return: None
|
139
|
+
"""
|
140
|
+
if isinstance(self._dividing_line, StaticDividingLine):
|
141
|
+
self._print_func(self._dividing_line.get_full_static_line(self._override_system_messages))
|
142
|
+
self._print_func(text)
|
143
|
+
self._print_func(self._dividing_line.get_full_static_line(self._override_system_messages))
|
107
144
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
if
|
112
|
-
|
145
|
+
elif isinstance(self._dividing_line, DynamicDividingLine):
|
146
|
+
clear_text = re.sub(r'\u001b\[[0-9;]*m', '', text)
|
147
|
+
max_length_line = max([len(line) for line in clear_text.split('\n')])
|
148
|
+
max_length_line = max_length_line if 10 <= max_length_line <= 80 else 80 if max_length_line > 80 else 10
|
149
|
+
|
150
|
+
self._print_func(self._dividing_line.get_full_dynamic_line(max_length_line, self._override_system_messages))
|
151
|
+
print(text.strip('\n'))
|
152
|
+
self._print_func(self._dividing_line.get_full_dynamic_line(max_length_line, self._override_system_messages))
|
153
|
+
|
154
|
+
|
155
|
+
def _is_exit_command(self, command: InputCommand) -> bool:
|
156
|
+
"""
|
157
|
+
Private. Checks if the given command is an exit command
|
158
|
+
:param command: command to check
|
159
|
+
:return: is it an exit command or not as bool
|
160
|
+
"""
|
161
|
+
if self._ignore_command_register:
|
162
|
+
if command.get_trigger().lower() == self._exit_command.get_trigger().lower():
|
113
163
|
return True
|
114
|
-
elif command.get_trigger()
|
115
|
-
|
164
|
+
elif command.get_trigger().lower() in [x.lower() for x in self._exit_command.get_aliases()]:
|
165
|
+
return True
|
166
|
+
else:
|
167
|
+
if command.get_trigger() == self._exit_command.get_trigger():
|
168
|
+
return True
|
169
|
+
elif command.get_trigger() in self._exit_command.get_aliases():
|
116
170
|
return True
|
117
171
|
return False
|
118
172
|
|
119
173
|
|
120
|
-
def _is_unknown_command(self, command: InputCommand):
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
self._print_func(self._dividing_line.get_full_line())
|
174
|
+
def _is_unknown_command(self, command: InputCommand) -> bool:
|
175
|
+
"""
|
176
|
+
Private. Checks if the given command is an unknown command
|
177
|
+
:param command: command to check
|
178
|
+
:return: is it an unknown command or not as bool
|
179
|
+
"""
|
180
|
+
input_command_trigger = command.get_trigger()
|
181
|
+
if self._ignore_command_register:
|
182
|
+
if input_command_trigger.lower() in self._all_registered_triggers_in_lower:
|
183
|
+
return False
|
184
|
+
else:
|
185
|
+
if input_command_trigger in self._all_registered_triggers_in_default_case:
|
186
|
+
return False
|
187
|
+
|
188
|
+
with redirect_stdout(io.StringIO()) as f:
|
136
189
|
self._unknown_command_handler(command)
|
137
|
-
|
138
|
-
|
139
|
-
with redirect_stdout(io.StringIO()) as f:
|
140
|
-
self._unknown_command_handler(command)
|
141
|
-
res: str = f.getvalue()
|
142
|
-
self._print_framed_text_with_dynamic_line(res)
|
190
|
+
res: str = f.getvalue()
|
191
|
+
self._print_framed_text(res)
|
143
192
|
return True
|
144
193
|
|
145
194
|
|
146
195
|
def _error_handler(self, error: BaseInputCommandException, raw_command: str) -> None:
|
196
|
+
"""
|
197
|
+
Private. Handles parsing errors of the entered command
|
198
|
+
:param error: error being handled
|
199
|
+
:param raw_command: the raw input command
|
200
|
+
:return: None
|
201
|
+
"""
|
147
202
|
match error:
|
148
203
|
case UnprocessedInputFlagException():
|
149
204
|
self._invalid_input_flags_handler(raw_command)
|
@@ -153,61 +208,127 @@ class AppNonStandardHandlers(AppPrinters):
|
|
153
208
|
self._empty_input_command_handler()
|
154
209
|
|
155
210
|
|
156
|
-
class AppValidators(AppInit):
|
157
|
-
def _validate_number_of_routers(self) -> None:
|
158
|
-
if not self._registered_routers:
|
159
|
-
raise NoRegisteredRoutersException()
|
160
|
-
|
161
|
-
|
162
211
|
def _validate_included_routers(self) -> None:
|
212
|
+
"""
|
213
|
+
Private. Validates included routers
|
214
|
+
:return: None
|
215
|
+
"""
|
163
216
|
for router in self._registered_routers:
|
164
217
|
if not router.get_command_handlers():
|
165
218
|
raise NoRegisteredHandlersException(router.get_name())
|
166
219
|
|
167
220
|
|
168
|
-
|
169
|
-
|
170
|
-
|
221
|
+
def _setup_system_router(self) -> None:
|
222
|
+
"""
|
223
|
+
Private. Sets up system router
|
224
|
+
:return: None
|
225
|
+
"""
|
226
|
+
system_router.set_title(self._system_router_title)
|
171
227
|
|
172
228
|
@system_router.command(self._exit_command)
|
173
229
|
def exit_command():
|
174
230
|
self._exit_command_handler()
|
175
231
|
|
176
232
|
if system_router not in self._registered_routers.get_registered_routers():
|
177
|
-
system_router.
|
233
|
+
system_router.set_command_register_ignore(self._ignore_command_register)
|
178
234
|
self._registered_routers.add_registered_router(system_router)
|
179
235
|
|
180
|
-
def _setup_default_view(self):
|
181
|
-
if not self._override_system_messages:
|
182
|
-
self._initial_message = f'\n[bold red]{text2art(self._initial_message, font='tarty1')}\n\n'
|
183
|
-
self._farewell_message = (
|
184
|
-
f'[bold red]\n{text2art(f'\n{self._farewell_message}\n', font='chanky')}[/bold red]\n'
|
185
|
-
f'[red i]github.com/koloideal/Argenta[/red i] | [red bold i]made by kolo[/red bold i]\n')
|
186
236
|
|
187
|
-
def
|
237
|
+
def _setup_default_view(self) -> None:
|
238
|
+
"""
|
239
|
+
Private. Sets up default app view
|
240
|
+
:return: None
|
241
|
+
"""
|
242
|
+
if not self._override_system_messages:
|
243
|
+
self._initial_message = f'\n[bold red]{text2art(self._initial_message, font="tarty1")}\n\n'
|
244
|
+
self._farewell_message = (f'[bold red]\n{text2art(f"\n{self._farewell_message}\n", font="chanky")}[/bold red]\n'
|
245
|
+
f'[red i]github.com/koloideal/Argenta[/red i] | [red bold i]made by kolo[/red bold i]\n')
|
246
|
+
self._description_message_gen = lambda command, description: (f'[bold red]{escape("[" + command + "]")}[/bold red] '
|
247
|
+
f'[blue dim]*=*=*[/blue dim] '
|
248
|
+
f'[bold yellow italic]{escape(description)}')
|
249
|
+
self._invalid_input_flags_handler = lambda raw_command: self._print_func(f'[red bold]Incorrect flag syntax: {escape(raw_command)}')
|
250
|
+
self._repeated_input_flags_handler = lambda raw_command: self._print_func(f'[red bold]Repeated input flags: {escape(raw_command)}')
|
251
|
+
self._empty_input_command_handler = lambda: self._print_func('[red bold]Empty input command')
|
252
|
+
self._unknown_command_handler = lambda command: self._print_func(f"[red bold]Unknown command: {escape(command.get_trigger())}")
|
253
|
+
|
254
|
+
|
255
|
+
def _pre_cycle_setup(self) -> None:
|
256
|
+
"""
|
257
|
+
Private. Configures various aspects of the application before the start of the cycle
|
258
|
+
:return: None
|
259
|
+
"""
|
188
260
|
self._setup_default_view()
|
189
261
|
self._setup_system_router()
|
190
|
-
self._validate_number_of_routers()
|
191
262
|
self._validate_included_routers()
|
192
263
|
|
193
|
-
all_triggers: list[str] = []
|
194
264
|
for router_entity in self._registered_routers:
|
195
|
-
|
196
|
-
|
197
|
-
|
265
|
+
self._all_registered_triggers_in_default_case.extend(router_entity.get_triggers())
|
266
|
+
self._all_registered_triggers_in_default_case.extend(router_entity.get_aliases())
|
267
|
+
|
268
|
+
self._all_registered_triggers_in_lower.extend([x.lower() for x in router_entity.get_triggers()])
|
269
|
+
self._all_registered_triggers_in_lower.extend([x.lower() for x in router_entity.get_aliases()])
|
270
|
+
|
271
|
+
self._autocompleter.initial_setup(self._all_registered_triggers_in_lower)
|
198
272
|
|
199
273
|
self._print_func(self._initial_message)
|
200
274
|
|
201
275
|
for message in self._messages_on_startup:
|
202
276
|
self._print_func(message)
|
203
|
-
|
277
|
+
if self._messages_on_startup:
|
278
|
+
print('\n\n')
|
204
279
|
|
205
280
|
if not self._repeat_command_groups_description:
|
206
281
|
self._print_command_group_description()
|
207
282
|
|
208
283
|
|
209
|
-
|
210
|
-
|
284
|
+
|
285
|
+
class App(BaseApp):
|
286
|
+
def __init__(self,
|
287
|
+
prompt: str = '[italic dim bold]What do you want to do?\n',
|
288
|
+
initial_message: str = '\nArgenta\n',
|
289
|
+
farewell_message: str = '\nSee you\n',
|
290
|
+
exit_command: Command = Command('Q', 'Exit command'),
|
291
|
+
system_router_title: str | None = 'System points:',
|
292
|
+
ignore_command_register: bool = True,
|
293
|
+
dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
|
294
|
+
repeat_command_groups: bool = True,
|
295
|
+
override_system_messages: bool = False,
|
296
|
+
autocompleter: AutoCompleter = AutoCompleter(),
|
297
|
+
print_func: Callable[[str], None] = Console().print) -> None:
|
298
|
+
"""
|
299
|
+
Public. The essence of the application itself.
|
300
|
+
Configures and manages all aspects of the behavior and presentation of the user interacting with the user
|
301
|
+
:param prompt: displayed before entering the command
|
302
|
+
:param initial_message: displayed at the start of the app
|
303
|
+
:param farewell_message: displayed at the end of the app
|
304
|
+
:param exit_command: the entity of the command that will be terminated when entered
|
305
|
+
:param system_router_title: system router title
|
306
|
+
:param ignore_command_register: whether to ignore the case of the entered commands
|
307
|
+
:param dividing_line: the entity of the dividing line
|
308
|
+
:param repeat_command_groups: whether to repeat the available commands and their description
|
309
|
+
:param override_system_messages: whether to redefine the default formatting of system messages
|
310
|
+
:param autocompleter: the entity of the autocompleter
|
311
|
+
:param print_func: system messages text output function
|
312
|
+
:return: None
|
313
|
+
"""
|
314
|
+
super().__init__(prompt=prompt,
|
315
|
+
initial_message=initial_message,
|
316
|
+
farewell_message=farewell_message,
|
317
|
+
exit_command=exit_command,
|
318
|
+
system_router_title=system_router_title,
|
319
|
+
ignore_command_register=ignore_command_register,
|
320
|
+
dividing_line=dividing_line,
|
321
|
+
repeat_command_groups=repeat_command_groups,
|
322
|
+
override_system_messages=override_system_messages,
|
323
|
+
autocompleter=autocompleter,
|
324
|
+
print_func=print_func)
|
325
|
+
|
326
|
+
|
327
|
+
def run_polling(self) -> None:
|
328
|
+
"""
|
329
|
+
Private. Starts the user input processing cycle
|
330
|
+
:return: None
|
331
|
+
"""
|
211
332
|
self._pre_cycle_setup()
|
212
333
|
while True:
|
213
334
|
if self._repeat_command_groups_description:
|
@@ -218,50 +339,55 @@ class App(AppSetters, AppNonStandardHandlers, AppSetups):
|
|
218
339
|
try:
|
219
340
|
input_command: InputCommand = InputCommand.parse(raw_command=raw_command)
|
220
341
|
except BaseInputCommandException as error:
|
221
|
-
|
222
|
-
self._print_func(self._dividing_line.get_full_line())
|
342
|
+
with redirect_stdout(io.StringIO()) as f:
|
223
343
|
self._error_handler(error, raw_command)
|
224
|
-
|
225
|
-
|
226
|
-
with redirect_stdout(io.StringIO()) as f:
|
227
|
-
self._error_handler(error, raw_command)
|
228
|
-
res: str = f.getvalue()
|
229
|
-
self._print_framed_text_with_dynamic_line(res)
|
344
|
+
res: str = f.getvalue()
|
345
|
+
self._print_framed_text(res)
|
230
346
|
continue
|
231
347
|
|
232
348
|
if self._is_exit_command(input_command):
|
349
|
+
system_router.finds_appropriate_handler(input_command)
|
233
350
|
self._autocompleter.exit_setup()
|
234
351
|
return
|
235
352
|
|
236
353
|
if self._is_unknown_command(input_command):
|
237
354
|
continue
|
238
355
|
|
239
|
-
|
240
|
-
self._print_func(self._dividing_line.get_full_line())
|
356
|
+
with redirect_stdout(io.StringIO()) as f:
|
241
357
|
for registered_router in self._registered_routers:
|
242
|
-
registered_router.
|
243
|
-
|
244
|
-
|
245
|
-
with redirect_stdout(io.StringIO()) as f:
|
246
|
-
for registered_router in self._registered_routers:
|
247
|
-
registered_router.input_command_handler(input_command)
|
248
|
-
res: str = f.getvalue()
|
249
|
-
self._print_framed_text_with_dynamic_line(res)
|
358
|
+
registered_router.finds_appropriate_handler(input_command)
|
359
|
+
res: str = f.getvalue()
|
360
|
+
self._print_framed_text(res)
|
250
361
|
|
251
362
|
if not self._repeat_command_groups_description:
|
252
363
|
self._print_func(self._prompt)
|
253
364
|
|
254
365
|
|
255
366
|
def include_router(self, router: Router) -> None:
|
256
|
-
|
367
|
+
"""
|
368
|
+
Public. Registers the router in the application
|
369
|
+
:param router: registered router
|
370
|
+
:return: None
|
371
|
+
"""
|
372
|
+
router.set_command_register_ignore(self._ignore_command_register)
|
257
373
|
self._registered_routers.add_registered_router(router)
|
258
374
|
|
259
375
|
|
260
376
|
def include_routers(self, *routers: Router) -> None:
|
377
|
+
"""
|
378
|
+
Public. Registers the routers in the application
|
379
|
+
:param routers: registered routers
|
380
|
+
:return: None
|
381
|
+
"""
|
261
382
|
for router in routers:
|
262
383
|
self.include_router(router)
|
263
384
|
|
264
385
|
|
265
386
|
def add_message_on_startup(self, message: str) -> None:
|
387
|
+
"""
|
388
|
+
Public. Adds a message that will be displayed when the application is launched
|
389
|
+
:param message: the message being added
|
390
|
+
:return: None
|
391
|
+
"""
|
266
392
|
self._messages_on_startup.append(message)
|
267
393
|
|