argenta 0.4.10__tar.gz → 0.5.0__tar.gz
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-0.4.10 → argenta-0.5.0}/PKG-INFO +33 -13
- {argenta-0.4.10 → argenta-0.5.0}/README.md +32 -12
- argenta-0.5.0/argenta/app/autocompleter/__init__.py +4 -0
- argenta-0.5.0/argenta/app/autocompleter/entity.py +47 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/app/defaults.py +1 -0
- argenta-0.5.0/argenta/app/exceptions.py +10 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/app/models.py +54 -49
- {argenta-0.4.10 → argenta-0.5.0}/argenta/command/models.py +7 -2
- {argenta-0.4.10 → argenta-0.5.0}/argenta/router/command_handler/entity.py +6 -6
- {argenta-0.4.10 → argenta-0.5.0}/argenta/router/entity.py +44 -21
- {argenta-0.4.10 → argenta-0.5.0}/pyproject.toml +1 -1
- argenta-0.4.10/argenta/app/exceptions.py +0 -25
- {argenta-0.4.10 → argenta-0.5.0}/LICENSE +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/app/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/app/dividing_line/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/app/dividing_line/models.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/app/registered_routers/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/app/registered_routers/entity.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/command/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/command/exceptions.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/command/flag/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/command/flag/defaults.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/command/flag/models.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/router/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/router/command_handler/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/router/command_handlers/__init__.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/router/command_handlers/entity.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/router/defaults.py +0 -0
- {argenta-0.4.10 → argenta-0.5.0}/argenta/router/exceptions.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: argenta
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.5.0
|
4
4
|
Summary: Python library for creating TUI
|
5
5
|
License: MIT
|
6
6
|
Author: kolo
|
@@ -22,7 +22,7 @@ Description-Content-Type: text/markdown
|
|
22
22
|
## Описание
|
23
23
|
**Argenta** — Python library for creating TUI
|
24
24
|
|
25
|
-

|
26
26
|
Пример внешнего вида TUI, написанного с помощью Argenta
|
27
27
|
|
28
28
|
---
|
@@ -112,16 +112,16 @@ def handler_with_flags(flags: InputFlags):
|
|
112
112
|
|
113
113
|
### Конструктор
|
114
114
|
```python
|
115
|
-
App(prompt: str = 'What do you want to do?\n',
|
116
|
-
initial_message: str = '
|
117
|
-
farewell_message: str = '
|
118
|
-
exit_command:
|
119
|
-
|
120
|
-
system_points_title: str = 'System points:',
|
115
|
+
App(prompt: str = '[italic dim bold]What do you want to do?\n',
|
116
|
+
initial_message: str = '\nArgenta\n',
|
117
|
+
farewell_message: str = '\nSee you\n',
|
118
|
+
exit_command: Command = Command('Q', 'Exit command'),
|
119
|
+
system_points_title: str | None = 'System points:',
|
121
120
|
ignore_command_register: bool = True,
|
122
121
|
dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
|
123
122
|
repeat_command_groups: bool = True,
|
124
|
-
|
123
|
+
override_system_messages: bool = False,
|
124
|
+
autocompleter: AutoCompleter = AutoCompleter(),
|
125
125
|
print_func: Callable[[str], None] = Console().print)
|
126
126
|
```
|
127
127
|
**Аргументы:**
|
@@ -129,13 +129,13 @@ App(prompt: str = 'What do you want to do?\n',
|
|
129
129
|
- `prompt` (`str`): Сообщение перед вводом команды.
|
130
130
|
- `initial_message` (`str`): Приветственное сообщение при запуске.
|
131
131
|
- `farewell_message` (`str`): Сообщение при выходе.
|
132
|
-
- `exit_command` (`
|
133
|
-
- `exit_command_description` (`str`): Описание команды выхода.
|
132
|
+
- `exit_command` (`Command`): Сущность команды, которая будет отвечать за завершение работы.
|
134
133
|
- `system_points_title` (`str`): Заголовок перед списком системных команд.
|
135
134
|
- `ignore_command_register` (`bool`): Игнорировать регистр всех команд.
|
136
135
|
- `dividing_line` (`StaticDividingLine | DynamicDividingLine`): Разделительная строка.
|
137
136
|
- `repeat_command_groups` (`bool`): Повторять описание команд перед вводом.
|
138
|
-
- `
|
137
|
+
- `override_system_messages` (`bool`): Переопределить ли дефолтное оформление сообщений ([подробнее см.](#override_defaults))
|
138
|
+
- `autocompleter` (`AutoCompleter`): Сущность автодополнителя ввода.
|
139
139
|
- `print_func` (`Callable[[str], None]`): Функция вывода текста в терминал.
|
140
140
|
|
141
141
|
---
|
@@ -260,6 +260,26 @@ App(prompt: str = 'What do you want to do?\n',
|
|
260
260
|
|
261
261
|
---
|
262
262
|
|
263
|
+
## *class* :: `AutoCompleter`
|
264
|
+
Класс, экземпляр которого представляет собой автодополнитель ввода
|
265
|
+
|
266
|
+
### Конструктор
|
267
|
+
```python
|
268
|
+
AutoCompleter(history_filename: str = False,
|
269
|
+
autocomplete_button: str = 'tab')
|
270
|
+
```
|
271
|
+
|
272
|
+
**Аргументы:**
|
273
|
+
- **name : mean**
|
274
|
+
- `history_filename` (`str` | `False`): Путь к файлу, который будет являться или является
|
275
|
+
историй пользовательского ввода, в последующем эти команды будут автодополняться, файл
|
276
|
+
может не существовать при инициализации, тогда он будет создан, при значении аргумента `False`
|
277
|
+
история пользовательского ввода будет существовать только в пределах сессии и не сохраняться в файл
|
278
|
+
- `autocomplete_button` (`str`): Строковое обозначение кнопки на клавиатуре, которая будет
|
279
|
+
использоваться для автодополнения при вводе, по умолчанию `tab`
|
280
|
+
|
281
|
+
---
|
282
|
+
|
263
283
|
## *class* :: `StaticDivideLine`
|
264
284
|
Класс, экземпляр которого представляет собой строковый разделитель фиксированной длины
|
265
285
|
|
@@ -295,7 +315,7 @@ DinamicDivideLine(unit_part: str = '-')
|
|
295
315
|
|
296
316
|
### Конструктор
|
297
317
|
```python
|
298
|
-
Router(title: str
|
318
|
+
Router(title: str | None = None,
|
299
319
|
name: str = 'Default')
|
300
320
|
```
|
301
321
|
|
@@ -5,7 +5,7 @@
|
|
5
5
|
## Описание
|
6
6
|
**Argenta** — Python library for creating TUI
|
7
7
|
|
8
|
-

|
9
9
|
Пример внешнего вида TUI, написанного с помощью Argenta
|
10
10
|
|
11
11
|
---
|
@@ -95,16 +95,16 @@ def handler_with_flags(flags: InputFlags):
|
|
95
95
|
|
96
96
|
### Конструктор
|
97
97
|
```python
|
98
|
-
App(prompt: str = 'What do you want to do?\n',
|
99
|
-
initial_message: str = '
|
100
|
-
farewell_message: str = '
|
101
|
-
exit_command:
|
102
|
-
|
103
|
-
system_points_title: str = 'System points:',
|
98
|
+
App(prompt: str = '[italic dim bold]What do you want to do?\n',
|
99
|
+
initial_message: str = '\nArgenta\n',
|
100
|
+
farewell_message: str = '\nSee you\n',
|
101
|
+
exit_command: Command = Command('Q', 'Exit command'),
|
102
|
+
system_points_title: str | None = 'System points:',
|
104
103
|
ignore_command_register: bool = True,
|
105
104
|
dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
|
106
105
|
repeat_command_groups: bool = True,
|
107
|
-
|
106
|
+
override_system_messages: bool = False,
|
107
|
+
autocompleter: AutoCompleter = AutoCompleter(),
|
108
108
|
print_func: Callable[[str], None] = Console().print)
|
109
109
|
```
|
110
110
|
**Аргументы:**
|
@@ -112,13 +112,13 @@ App(prompt: str = 'What do you want to do?\n',
|
|
112
112
|
- `prompt` (`str`): Сообщение перед вводом команды.
|
113
113
|
- `initial_message` (`str`): Приветственное сообщение при запуске.
|
114
114
|
- `farewell_message` (`str`): Сообщение при выходе.
|
115
|
-
- `exit_command` (`
|
116
|
-
- `exit_command_description` (`str`): Описание команды выхода.
|
115
|
+
- `exit_command` (`Command`): Сущность команды, которая будет отвечать за завершение работы.
|
117
116
|
- `system_points_title` (`str`): Заголовок перед списком системных команд.
|
118
117
|
- `ignore_command_register` (`bool`): Игнорировать регистр всех команд.
|
119
118
|
- `dividing_line` (`StaticDividingLine | DynamicDividingLine`): Разделительная строка.
|
120
119
|
- `repeat_command_groups` (`bool`): Повторять описание команд перед вводом.
|
121
|
-
- `
|
120
|
+
- `override_system_messages` (`bool`): Переопределить ли дефолтное оформление сообщений ([подробнее см.](#override_defaults))
|
121
|
+
- `autocompleter` (`AutoCompleter`): Сущность автодополнителя ввода.
|
122
122
|
- `print_func` (`Callable[[str], None]`): Функция вывода текста в терминал.
|
123
123
|
|
124
124
|
---
|
@@ -243,6 +243,26 @@ App(prompt: str = 'What do you want to do?\n',
|
|
243
243
|
|
244
244
|
---
|
245
245
|
|
246
|
+
## *class* :: `AutoCompleter`
|
247
|
+
Класс, экземпляр которого представляет собой автодополнитель ввода
|
248
|
+
|
249
|
+
### Конструктор
|
250
|
+
```python
|
251
|
+
AutoCompleter(history_filename: str = False,
|
252
|
+
autocomplete_button: str = 'tab')
|
253
|
+
```
|
254
|
+
|
255
|
+
**Аргументы:**
|
256
|
+
- **name : mean**
|
257
|
+
- `history_filename` (`str` | `False`): Путь к файлу, который будет являться или является
|
258
|
+
историй пользовательского ввода, в последующем эти команды будут автодополняться, файл
|
259
|
+
может не существовать при инициализации, тогда он будет создан, при значении аргумента `False`
|
260
|
+
история пользовательского ввода будет существовать только в пределах сессии и не сохраняться в файл
|
261
|
+
- `autocomplete_button` (`str`): Строковое обозначение кнопки на клавиатуре, которая будет
|
262
|
+
использоваться для автодополнения при вводе, по умолчанию `tab`
|
263
|
+
|
264
|
+
---
|
265
|
+
|
246
266
|
## *class* :: `StaticDivideLine`
|
247
267
|
Класс, экземпляр которого представляет собой строковый разделитель фиксированной длины
|
248
268
|
|
@@ -278,7 +298,7 @@ DinamicDivideLine(unit_part: str = '-')
|
|
278
298
|
|
279
299
|
### Конструктор
|
280
300
|
```python
|
281
|
-
Router(title: str
|
301
|
+
Router(title: str | None = None,
|
282
302
|
name: str = 'Default')
|
283
303
|
```
|
284
304
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
import os
|
2
|
+
import readline
|
3
|
+
|
4
|
+
|
5
|
+
class AutoCompleter:
|
6
|
+
def __init__(self, history_filename: str = False, autocomplete_button: str = 'tab'):
|
7
|
+
self.history_filename = history_filename
|
8
|
+
self.autocomplete_button = autocomplete_button
|
9
|
+
self.matches = []
|
10
|
+
|
11
|
+
def complete(self, text, state):
|
12
|
+
matches = sorted(cmd for cmd in self.get_history_items() if cmd.startswith(text))
|
13
|
+
if len(matches) > 1:
|
14
|
+
common_prefix = matches[0]
|
15
|
+
for match in matches[1:]:
|
16
|
+
i = 0
|
17
|
+
while i < len(common_prefix) and i < len(match) and common_prefix[i] == match[i]:
|
18
|
+
i += 1
|
19
|
+
common_prefix = common_prefix[:i]
|
20
|
+
if state == 0:
|
21
|
+
readline.insert_text(common_prefix[len(text):])
|
22
|
+
readline.redisplay()
|
23
|
+
return None
|
24
|
+
elif len(matches) == 1:
|
25
|
+
return matches[0] if state == 0 else None
|
26
|
+
else:
|
27
|
+
return None
|
28
|
+
|
29
|
+
def initial_setup(self, all_commands: list[str]):
|
30
|
+
if self.history_filename:
|
31
|
+
if os.path.exists(self.history_filename):
|
32
|
+
readline.read_history_file(self.history_filename)
|
33
|
+
else:
|
34
|
+
for line in all_commands:
|
35
|
+
readline.add_history(line)
|
36
|
+
|
37
|
+
readline.set_completer(self.complete)
|
38
|
+
readline.set_completer_delims(readline.get_completer_delims().replace(' ', ''))
|
39
|
+
readline.parse_and_bind(f'{self.autocomplete_button}: complete')
|
40
|
+
|
41
|
+
def exit_setup(self):
|
42
|
+
if self.history_filename:
|
43
|
+
readline.write_history_file(self.history_filename)
|
44
|
+
|
45
|
+
@staticmethod
|
46
|
+
def get_history_items():
|
47
|
+
return [readline.get_history_item(i) for i in range(1, readline.get_current_history_length() + 1)]
|
@@ -5,4 +5,5 @@ from dataclasses import dataclass
|
|
5
5
|
class PredeterminedMessages:
|
6
6
|
USAGE = '[b dim]Usage[/b dim]: [i]<command> <[green]flags[/green]>[/i]'
|
7
7
|
HELP = '[b dim]Help[/b dim]: [i]<command>[/i] [b red]--help[/b red]'
|
8
|
+
AUTOCOMPLETE = '[b dim]Autocomplete[/b dim]: [i]<part>[/i] [bold]<tab>'
|
8
9
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class NoRegisteredRoutersException(Exception):
|
2
|
+
def __str__(self):
|
3
|
+
return "No Registered Router Found"
|
4
|
+
|
5
|
+
|
6
|
+
class NoRegisteredHandlersException(Exception):
|
7
|
+
def __init__(self, router_name):
|
8
|
+
self.router_name = router_name
|
9
|
+
def __str__(self):
|
10
|
+
return f"No Registered Handlers Found For '{self.router_name}'"
|
@@ -1,5 +1,6 @@
|
|
1
1
|
from typing import Callable
|
2
2
|
from rich.console import Console
|
3
|
+
from rich.markup import escape
|
3
4
|
from art import text2art
|
4
5
|
from contextlib import redirect_stdout
|
5
6
|
import io
|
@@ -8,14 +9,13 @@ import re
|
|
8
9
|
from argenta.command.models import Command, InputCommand
|
9
10
|
from argenta.router import Router
|
10
11
|
from argenta.router.defaults import system_router
|
12
|
+
from argenta.app.autocompleter import AutoCompleter
|
11
13
|
from argenta.app.dividing_line.models import StaticDividingLine, DynamicDividingLine
|
12
14
|
from argenta.command.exceptions import (UnprocessedInputFlagException,
|
13
15
|
RepeatedInputFlagsException,
|
14
16
|
EmptyInputCommandException,
|
15
17
|
BaseInputCommandException)
|
16
|
-
from argenta.app.exceptions import (
|
17
|
-
InvalidDescriptionMessagePatternException,
|
18
|
-
NoRegisteredRoutersException,
|
18
|
+
from argenta.app.exceptions import (NoRegisteredRoutersException,
|
19
19
|
NoRegisteredHandlersException)
|
20
20
|
from argenta.app.registered_routers.entity import RegisteredRouters
|
21
21
|
|
@@ -26,47 +26,42 @@ class AppInit:
|
|
26
26
|
prompt: str = '[italic dim bold]What do you want to do?\n',
|
27
27
|
initial_message: str = '\nArgenta\n',
|
28
28
|
farewell_message: str = '\nSee you\n',
|
29
|
-
exit_command:
|
30
|
-
|
31
|
-
system_points_title: str = 'System points:',
|
29
|
+
exit_command: Command = Command('Q', 'Exit command'),
|
30
|
+
system_points_title: str | None = 'System points:',
|
32
31
|
ignore_command_register: bool = True,
|
33
32
|
dividing_line: StaticDividingLine | DynamicDividingLine = StaticDividingLine(),
|
34
33
|
repeat_command_groups: bool = True,
|
35
|
-
|
34
|
+
override_system_messages: bool = False,
|
35
|
+
autocompleter: AutoCompleter = AutoCompleter(),
|
36
36
|
print_func: Callable[[str], None] = Console().print) -> None:
|
37
37
|
self._prompt = prompt
|
38
38
|
self._print_func = print_func
|
39
39
|
self._exit_command = exit_command
|
40
|
-
self._exit_command_description = exit_command_description
|
41
40
|
self._system_points_title = system_points_title
|
42
41
|
self._dividing_line = dividing_line
|
43
42
|
self._ignore_command_register = ignore_command_register
|
44
43
|
self._repeat_command_groups_description = repeat_command_groups
|
45
|
-
self.
|
44
|
+
self._override_system_messages = override_system_messages
|
45
|
+
self._autocompleter = autocompleter
|
46
46
|
|
47
47
|
self._farewell_message = farewell_message
|
48
48
|
self._initial_message = initial_message
|
49
49
|
|
50
|
-
|
50
|
+
|
51
|
+
self._description_message_gen: Callable[[str, str], str] = lambda command, description: f'[bold red]{escape('['+command+']')}[/bold red] [blue dim]*=*=*[/blue dim] [bold yellow italic]{escape(description)}'
|
51
52
|
self._registered_routers: RegisteredRouters = RegisteredRouters()
|
52
53
|
self._messages_on_startup = []
|
53
54
|
|
54
|
-
self._invalid_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'[red bold]Incorrect flag syntax: {raw_command}')
|
55
|
-
self._repeated_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'[red bold]Repeated input flags: {raw_command}')
|
55
|
+
self._invalid_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'[red bold]Incorrect flag syntax: {escape(raw_command)}')
|
56
|
+
self._repeated_input_flags_handler: Callable[[str], None] = lambda raw_command: print_func(f'[red bold]Repeated input flags: {escape(raw_command)}')
|
56
57
|
self._empty_input_command_handler: Callable[[], None] = lambda: print_func('[red bold]Empty input command')
|
57
|
-
self._unknown_command_handler: Callable[[InputCommand], None] = lambda command: print_func(f"[red bold]Unknown command: {command.get_trigger()}")
|
58
|
+
self._unknown_command_handler: Callable[[InputCommand], None] = lambda command: print_func(f"[red bold]Unknown command: {escape(command.get_trigger())}")
|
58
59
|
self._exit_command_handler: Callable[[], None] = lambda: print_func(self._farewell_message)
|
59
60
|
|
60
61
|
|
61
62
|
class AppSetters(AppInit):
|
62
|
-
def set_description_message_pattern(self, pattern: str) -> None:
|
63
|
-
|
64
|
-
second_check = re.match(r'.*{description}.*', pattern)
|
65
|
-
|
66
|
-
if bool(first_check) and bool(second_check):
|
67
|
-
self._description_message_pattern: str = pattern
|
68
|
-
else:
|
69
|
-
raise InvalidDescriptionMessagePatternException(pattern)
|
63
|
+
def set_description_message_pattern(self, pattern: Callable[[str, str], str]) -> None:
|
64
|
+
self._description_message_gen: Callable[[str, str], str] = pattern
|
70
65
|
|
71
66
|
|
72
67
|
def set_invalid_input_flags_handler(self, handler: Callable[[str], None]) -> None:
|
@@ -92,11 +87,12 @@ class AppSetters(AppInit):
|
|
92
87
|
class AppPrinters(AppInit):
|
93
88
|
def _print_command_group_description(self):
|
94
89
|
for registered_router in self._registered_routers:
|
95
|
-
|
90
|
+
if registered_router.get_title():
|
91
|
+
self._print_func(registered_router.get_title())
|
96
92
|
for command_handler in registered_router.get_command_handlers():
|
97
|
-
self._print_func(self.
|
98
|
-
|
99
|
-
|
93
|
+
self._print_func(self._description_message_gen(
|
94
|
+
command_handler.get_handled_command().get_trigger(),
|
95
|
+
command_handler.get_handled_command().get_description()))
|
100
96
|
self._print_func('')
|
101
97
|
|
102
98
|
|
@@ -109,13 +105,22 @@ class AppPrinters(AppInit):
|
|
109
105
|
self._print_func(self._dividing_line.get_full_line(max_length_line))
|
110
106
|
|
111
107
|
|
108
|
+
def _print_framed_text(self, text: str):
|
109
|
+
if isinstance(self._dividing_line, StaticDividingLine):
|
110
|
+
self._print_func(self._dividing_line.get_full_line())
|
111
|
+
self._print_func(text)
|
112
|
+
self._print_func(self._dividing_line.get_full_line())
|
113
|
+
elif isinstance(self._dividing_line, DynamicDividingLine):
|
114
|
+
self._print_framed_text_with_dynamic_line(text)
|
115
|
+
|
116
|
+
|
112
117
|
class AppNonStandardHandlers(AppPrinters):
|
113
118
|
def _is_exit_command(self, command: InputCommand):
|
114
|
-
if command.get_trigger().lower() == self._exit_command.lower():
|
119
|
+
if command.get_trigger().lower() == self._exit_command.get_trigger().lower():
|
115
120
|
if self._ignore_command_register:
|
116
121
|
system_router.input_command_handler(command)
|
117
122
|
return True
|
118
|
-
elif command.get_trigger() == self._exit_command:
|
123
|
+
elif command.get_trigger() == self._exit_command.get_trigger():
|
119
124
|
system_router.input_command_handler(command)
|
120
125
|
return True
|
121
126
|
return False
|
@@ -125,10 +130,16 @@ class AppNonStandardHandlers(AppPrinters):
|
|
125
130
|
for router_entity in self._registered_routers:
|
126
131
|
for command_handler in router_entity.get_command_handlers():
|
127
132
|
handled_command_trigger = command_handler.get_handled_command().get_trigger()
|
133
|
+
handled_command_aliases = command_handler.get_handled_command().get_aliases()
|
128
134
|
if handled_command_trigger.lower() == command.get_trigger().lower() and self._ignore_command_register:
|
129
135
|
return False
|
130
136
|
elif handled_command_trigger == command.get_trigger():
|
131
137
|
return False
|
138
|
+
elif handled_command_aliases:
|
139
|
+
if (command.get_trigger().lower() in [x.lower() for x in handled_command_aliases]) and self._ignore_command_register:
|
140
|
+
return False
|
141
|
+
elif command.get_trigger() in handled_command_trigger:
|
142
|
+
return False
|
132
143
|
if isinstance(self._dividing_line, StaticDividingLine):
|
133
144
|
self._print_func(self._dividing_line.get_full_line())
|
134
145
|
self._unknown_command_handler(command)
|
@@ -167,7 +178,7 @@ class AppSetups(AppValidators, AppPrinters):
|
|
167
178
|
def _setup_system_router(self):
|
168
179
|
system_router.set_title(self._system_points_title)
|
169
180
|
|
170
|
-
@system_router.command(
|
181
|
+
@system_router.command(self._exit_command)
|
171
182
|
def exit_command():
|
172
183
|
self._exit_command_handler()
|
173
184
|
|
@@ -176,7 +187,7 @@ class AppSetups(AppValidators, AppPrinters):
|
|
176
187
|
self._registered_routers.add_registered_router(system_router)
|
177
188
|
|
178
189
|
def _setup_default_view(self):
|
179
|
-
if not self.
|
190
|
+
if not self._override_system_messages:
|
180
191
|
self._initial_message = f'\n[bold red]{text2art(self._initial_message, font='tarty1')}\n\n'
|
181
192
|
self._farewell_message = (
|
182
193
|
f'[bold red]\n{text2art(f'\n{self._farewell_message}\n', font='chanky')}[/bold red]\n'
|
@@ -188,10 +199,17 @@ class AppSetups(AppValidators, AppPrinters):
|
|
188
199
|
self._validate_number_of_routers()
|
189
200
|
self._validate_included_routers()
|
190
201
|
|
202
|
+
all_triggers: list[str] = []
|
203
|
+
for router_entity in self._registered_routers:
|
204
|
+
all_triggers.extend(router_entity.get_triggers())
|
205
|
+
all_triggers.extend(router_entity.get_aliases())
|
206
|
+
self._autocompleter.initial_setup(all_triggers)
|
207
|
+
|
191
208
|
self._print_func(self._initial_message)
|
192
209
|
|
193
210
|
for message in self._messages_on_startup:
|
194
211
|
self._print_func(message)
|
212
|
+
print('\n\n')
|
195
213
|
|
196
214
|
if not self._repeat_command_groups_description:
|
197
215
|
self._print_command_group_description()
|
@@ -209,43 +227,30 @@ class App(AppSetters, AppNonStandardHandlers, AppSetups):
|
|
209
227
|
try:
|
210
228
|
input_command: InputCommand = InputCommand.parse(raw_command=raw_command)
|
211
229
|
except BaseInputCommandException as error:
|
212
|
-
|
213
|
-
self._print_func(self._dividing_line.get_full_line())
|
230
|
+
with redirect_stdout(io.StringIO()) as f:
|
214
231
|
self._error_handler(error, raw_command)
|
215
|
-
|
216
|
-
|
217
|
-
with redirect_stdout(io.StringIO()) as f:
|
218
|
-
self._error_handler(error, raw_command)
|
219
|
-
res: str = f.getvalue()
|
220
|
-
self._print_framed_text_with_dynamic_line(res)
|
232
|
+
res: str = f.getvalue()
|
233
|
+
self._print_framed_text(res)
|
221
234
|
continue
|
222
235
|
|
223
236
|
if self._is_exit_command(input_command):
|
237
|
+
self._autocompleter.exit_setup()
|
224
238
|
return
|
225
239
|
|
226
240
|
if self._is_unknown_command(input_command):
|
227
241
|
continue
|
228
242
|
|
229
|
-
|
230
|
-
self._print_func(self._dividing_line.get_full_line())
|
243
|
+
with redirect_stdout(io.StringIO()) as f:
|
231
244
|
for registered_router in self._registered_routers:
|
232
245
|
registered_router.input_command_handler(input_command)
|
233
|
-
|
234
|
-
|
235
|
-
with redirect_stdout(io.StringIO()) as f:
|
236
|
-
for registered_router in self._registered_routers:
|
237
|
-
registered_router.input_command_handler(input_command)
|
238
|
-
res: str = f.getvalue()
|
239
|
-
self._print_framed_text_with_dynamic_line(res)
|
246
|
+
res: str = f.getvalue()
|
247
|
+
self._print_framed_text(res)
|
240
248
|
|
241
249
|
if not self._repeat_command_groups_description:
|
242
250
|
self._print_func(self._prompt)
|
243
251
|
|
244
252
|
|
245
253
|
def include_router(self, router: Router) -> None:
|
246
|
-
if not isinstance(router, Router):
|
247
|
-
raise InvalidRouterInstanceException()
|
248
|
-
|
249
254
|
router.set_ignore_command_register(self._ignore_command_register)
|
250
255
|
self._registered_routers.add_registered_router(router)
|
251
256
|
|
@@ -19,14 +19,19 @@ class BaseCommand:
|
|
19
19
|
class Command(BaseCommand):
|
20
20
|
def __init__(self, trigger: str,
|
21
21
|
description: str = None,
|
22
|
-
flags: Flag | Flags = None
|
22
|
+
flags: Flag | Flags = None,
|
23
|
+
aliases: list[str] = None):
|
23
24
|
super().__init__(trigger)
|
24
25
|
self._registered_flags: Flags = flags if isinstance(flags, Flags) else Flags(flags) if isinstance(flags, Flag) else Flags()
|
25
|
-
self._description = f'
|
26
|
+
self._description = f'Description for "{self._trigger}" command' if not description else description
|
27
|
+
self._aliases = aliases
|
26
28
|
|
27
29
|
def get_registered_flags(self) -> Flags:
|
28
30
|
return self._registered_flags
|
29
31
|
|
32
|
+
def get_aliases(self) -> list[str] | None:
|
33
|
+
return self._aliases
|
34
|
+
|
30
35
|
def validate_input_flag(self, flag: InputFlag):
|
31
36
|
registered_flags: Flags | None = self.get_registered_flags()
|
32
37
|
if registered_flags:
|
@@ -5,17 +5,17 @@ from argenta.command.flag.models import InputFlags
|
|
5
5
|
|
6
6
|
class CommandHandler:
|
7
7
|
def __init__(self, handler: Callable[[], None] | Callable[[InputFlags], None], handled_command: Command):
|
8
|
-
self.
|
9
|
-
self.
|
8
|
+
self._handler = handler
|
9
|
+
self._handled_command = handled_command
|
10
10
|
|
11
11
|
def handling(self, input_flags: InputFlags = None):
|
12
12
|
if input_flags is not None:
|
13
|
-
self.
|
13
|
+
self._handler(input_flags)
|
14
14
|
else:
|
15
|
-
self.
|
15
|
+
self._handler()
|
16
16
|
|
17
17
|
def get_handler(self):
|
18
|
-
return self.
|
18
|
+
return self._handler
|
19
19
|
|
20
20
|
def get_handled_command(self):
|
21
|
-
return self.
|
21
|
+
return self._handled_command
|
@@ -7,15 +7,15 @@ from argenta.router.command_handlers.entity import CommandHandlers
|
|
7
7
|
from argenta.router.command_handler.entity import CommandHandler
|
8
8
|
from argenta.command.flag.models import Flag, Flags, InputFlags
|
9
9
|
from argenta.router.exceptions import (RepeatedFlagNameException,
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
TooManyTransferredArgsException,
|
11
|
+
RequiredArgumentNotPassedException,
|
12
|
+
IncorrectNumberOfHandlerArgsException,
|
13
|
+
TriggerCannotContainSpacesException)
|
14
14
|
|
15
15
|
|
16
16
|
class Router:
|
17
17
|
def __init__(self,
|
18
|
-
title: str =
|
18
|
+
title: str = None,
|
19
19
|
name: str = 'Default'):
|
20
20
|
self._title = title
|
21
21
|
self._name = name
|
@@ -54,21 +54,29 @@ class Router:
|
|
54
54
|
for command_handler in self._command_handlers:
|
55
55
|
handle_command = command_handler.get_handled_command()
|
56
56
|
if input_command_name.lower() == handle_command.get_trigger().lower():
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
57
|
+
self._validate_input_command(input_command_flags, command_handler)
|
58
|
+
elif handle_command.get_aliases():
|
59
|
+
if input_command_name.lower() in handle_command.get_aliases():
|
60
|
+
self._validate_input_command(input_command_flags, command_handler)
|
61
|
+
|
62
|
+
|
63
|
+
def _validate_input_command(self, input_command_flags: InputFlags, command_handler: CommandHandler):
|
64
|
+
handle_command = command_handler.get_handled_command()
|
65
|
+
if handle_command.get_registered_flags().get_flags():
|
66
|
+
if input_command_flags.get_flags():
|
67
|
+
if self._validate_input_flags(handle_command, input_command_flags):
|
68
|
+
command_handler.handling(input_command_flags)
|
69
|
+
return
|
70
|
+
else:
|
71
|
+
command_handler.handling(input_command_flags)
|
72
|
+
return
|
73
|
+
else:
|
74
|
+
if input_command_flags.get_flags():
|
75
|
+
self._not_valid_flag_handler(input_command_flags[0])
|
76
|
+
return
|
77
|
+
else:
|
78
|
+
command_handler.handling()
|
79
|
+
return
|
72
80
|
|
73
81
|
|
74
82
|
def _validate_input_flags(self, handle_command: Command, input_flags: InputFlags):
|
@@ -110,6 +118,21 @@ class Router:
|
|
110
118
|
self._ignore_command_register = ignore_command_register
|
111
119
|
|
112
120
|
|
121
|
+
def get_triggers(self):
|
122
|
+
all_triggers: list[str] = []
|
123
|
+
for command_handler in self._command_handlers:
|
124
|
+
all_triggers.append(command_handler.get_handled_command().get_trigger())
|
125
|
+
return all_triggers
|
126
|
+
|
127
|
+
|
128
|
+
def get_aliases(self):
|
129
|
+
all_aliases: list[str] = []
|
130
|
+
for command_handler in self._command_handlers:
|
131
|
+
if command_handler.get_handled_command().get_aliases():
|
132
|
+
all_aliases.extend(command_handler.get_handled_command().get_aliases())
|
133
|
+
return all_aliases
|
134
|
+
|
135
|
+
|
113
136
|
def get_command_handlers(self) -> CommandHandlers:
|
114
137
|
return self._command_handlers
|
115
138
|
|
@@ -118,7 +141,7 @@ class Router:
|
|
118
141
|
return self._name
|
119
142
|
|
120
143
|
|
121
|
-
def get_title(self) -> str:
|
144
|
+
def get_title(self) -> str | None:
|
122
145
|
return self._title
|
123
146
|
|
124
147
|
|
@@ -1,25 +0,0 @@
|
|
1
|
-
class InvalidRouterInstanceException(Exception):
|
2
|
-
def __str__(self):
|
3
|
-
return "Invalid Router Instance"
|
4
|
-
|
5
|
-
|
6
|
-
class InvalidDescriptionMessagePatternException(Exception):
|
7
|
-
def __init__(self, pattern: str):
|
8
|
-
self.pattern = pattern
|
9
|
-
def __str__(self):
|
10
|
-
return ("Invalid Description Message Pattern\n"
|
11
|
-
"Correct pattern example: [{command}] *=*=* {description}\n"
|
12
|
-
"The pattern must contain two variables: `command` and `description` - description of the command\n"
|
13
|
-
f"Your pattern: {self.pattern}")
|
14
|
-
|
15
|
-
|
16
|
-
class NoRegisteredRoutersException(Exception):
|
17
|
-
def __str__(self):
|
18
|
-
return "No Registered Router Found"
|
19
|
-
|
20
|
-
|
21
|
-
class NoRegisteredHandlersException(Exception):
|
22
|
-
def __init__(self, router_name):
|
23
|
-
self.router_name = router_name
|
24
|
-
def __str__(self):
|
25
|
-
return f"No Registered Handlers Found For '{self.router_name}'"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|